summaryrefslogtreecommitdiff
path: root/src/lib/libc
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libc')
-rw-r--r--src/lib/libc/crypt/Makefile.inc14
-rw-r--r--src/lib/libc/crypt/arc4random.3110
-rw-r--r--src/lib/libc/crypt/arc4random.c195
-rw-r--r--src/lib/libc/crypt/bcrypt.c334
-rw-r--r--src/lib/libc/crypt/blowfish.3106
-rw-r--r--src/lib/libc/crypt/blowfish.c694
-rw-r--r--src/lib/libc/crypt/cast.c779
-rw-r--r--src/lib/libc/crypt/crypt.3314
-rw-r--r--src/lib/libc/crypt/crypt.c713
-rw-r--r--src/lib/libc/crypt/md5crypt.c156
-rw-r--r--src/lib/libc/crypt/morecrypt.c628
-rw-r--r--src/lib/libc/crypt/skipjack.c258
-rw-r--r--src/lib/libc/include/namespace.h2
-rw-r--r--src/lib/libc/include/thread_private.h134
-rw-r--r--src/lib/libc/net/Makefile.inc77
-rw-r--r--src/lib/libc/net/base64.c318
-rw-r--r--src/lib/libc/net/byteorder.3151
-rw-r--r--src/lib/libc/net/ethers.367
-rw-r--r--src/lib/libc/net/ethers.c204
-rw-r--r--src/lib/libc/net/freeaddrinfo.c49
-rw-r--r--src/lib/libc/net/gai_strerror.c76
-rw-r--r--src/lib/libc/net/getaddrinfo.3581
-rw-r--r--src/lib/libc/net/getaddrinfo.c1866
-rw-r--r--src/lib/libc/net/gethostbyname.3175
-rw-r--r--src/lib/libc/net/gethostnamadr.c958
-rw-r--r--src/lib/libc/net/getifaddrs.3159
-rw-r--r--src/lib/libc/net/getifaddrs.c277
-rw-r--r--src/lib/libc/net/getnameinfo.3297
-rw-r--r--src/lib/libc/net/getnameinfo.c368
-rw-r--r--src/lib/libc/net/getnetbyaddr.c14
-rw-r--r--src/lib/libc/net/getnetbyname.c16
-rw-r--r--src/lib/libc/net/getnetent.375
-rw-r--r--src/lib/libc/net/getnetent.c34
-rw-r--r--src/lib/libc/net/getnetnamadr.c411
-rw-r--r--src/lib/libc/net/getproto.c10
-rw-r--r--src/lib/libc/net/getprotoent.354
-rw-r--r--src/lib/libc/net/getprotoent.c32
-rw-r--r--src/lib/libc/net/getprotoname.c10
-rw-r--r--src/lib/libc/net/getrrsetbyname.3166
-rw-r--r--src/lib/libc/net/getrrsetbyname.c512
-rw-r--r--src/lib/libc/net/getservbyname.c34
-rw-r--r--src/lib/libc/net/getservbyport.c10
-rw-r--r--src/lib/libc/net/getservent.362
-rw-r--r--src/lib/libc/net/getservent.c32
-rw-r--r--src/lib/libc/net/herror.c38
-rw-r--r--src/lib/libc/net/htonl.c18
-rw-r--r--src/lib/libc/net/htons.c13
-rw-r--r--src/lib/libc/net/if_indextoname.3140
-rw-r--r--src/lib/libc/net/if_indextoname.c86
-rw-r--r--src/lib/libc/net/if_nameindex.c140
-rw-r--r--src/lib/libc/net/if_nametoindex.c81
-rw-r--r--src/lib/libc/net/inet.3234
-rw-r--r--src/lib/libc/net/inet6_option_space.3448
-rw-r--r--src/lib/libc/net/inet6_rthdr_space.3321
-rw-r--r--src/lib/libc/net/inet_addr.c91
-rw-r--r--src/lib/libc/net/inet_lnaof.c12
-rw-r--r--src/lib/libc/net/inet_makeaddr.c12
-rw-r--r--src/lib/libc/net/inet_net.3181
-rw-r--r--src/lib/libc/net/inet_net_ntop.c153
-rw-r--r--src/lib/libc/net/inet_net_pton.c206
-rw-r--r--src/lib/libc/net/inet_neta.c91
-rw-r--r--src/lib/libc/net/inet_netof.c12
-rw-r--r--src/lib/libc/net/inet_network.c25
-rw-r--r--src/lib/libc/net/inet_ntoa.c10
-rw-r--r--src/lib/libc/net/inet_ntop.c213
-rw-r--r--src/lib/libc/net/inet_pton.c222
-rw-r--r--src/lib/libc/net/ip6opt.c388
-rw-r--r--src/lib/libc/net/ipx.3127
-rw-r--r--src/lib/libc/net/ipx_addr.c228
-rw-r--r--src/lib/libc/net/ipx_ntoa.c58
-rw-r--r--src/lib/libc/net/iso_addr.313
-rw-r--r--src/lib/libc/net/iso_addr.c8
-rw-r--r--src/lib/libc/net/link_addr.3 (renamed from src/lib/libc/net/linkaddr.3)28
-rw-r--r--src/lib/libc/net/linkaddr.c8
-rw-r--r--src/lib/libc/net/net_addrcmp.391
-rw-r--r--src/lib/libc/net/net_addrcmp.c68
-rw-r--r--src/lib/libc/net/ns.331
-rw-r--r--src/lib/libc/net/ns_addr.c20
-rw-r--r--src/lib/libc/net/ns_ntoa.c78
-rw-r--r--src/lib/libc/net/nsap_addr.c109
-rw-r--r--src/lib/libc/net/ntohl.c18
-rw-r--r--src/lib/libc/net/ntohs.c13
-rw-r--r--src/lib/libc/net/rcmd.3166
-rw-r--r--src/lib/libc/net/rcmd.c546
-rw-r--r--src/lib/libc/net/rcmdsh.3 (renamed from src/lib/libc/string/index.3)111
-rw-r--r--src/lib/libc/net/rcmdsh.c192
-rw-r--r--src/lib/libc/net/recv.c8
-rw-r--r--src/lib/libc/net/res_comp.c227
-rw-r--r--src/lib/libc/net/res_data.c117
-rw-r--r--src/lib/libc/net/res_debug.c1524
-rw-r--r--src/lib/libc/net/res_init.c502
-rw-r--r--src/lib/libc/net/res_mkquery.c238
-rw-r--r--src/lib/libc/net/res_query.c223
-rw-r--r--src/lib/libc/net/res_random.c229
-rw-r--r--src/lib/libc/net/res_send.c870
-rw-r--r--src/lib/libc/net/resolver.393
-rw-r--r--src/lib/libc/net/rresvport.c118
-rw-r--r--src/lib/libc/net/rthdr.c310
-rw-r--r--src/lib/libc/net/send.c8
-rw-r--r--src/lib/libc/net/sethostent.c23
-rw-r--r--src/lib/libc/net/vars6.c42
-rw-r--r--src/lib/libc/stdlib/Makefile.inc56
-rw-r--r--src/lib/libc/stdlib/_rand48.c4
-rw-r--r--src/lib/libc/stdlib/a64l.3144
-rw-r--r--src/lib/libc/stdlib/a64l.c28
-rw-r--r--src/lib/libc/stdlib/abort.320
-rw-r--r--src/lib/libc/stdlib/abort.c25
-rw-r--r--src/lib/libc/stdlib/abs.317
-rw-r--r--src/lib/libc/stdlib/abs.c3
-rw-r--r--src/lib/libc/stdlib/alloca.335
-rw-r--r--src/lib/libc/stdlib/atexit.313
-rw-r--r--src/lib/libc/stdlib/atexit.c141
-rw-r--r--src/lib/libc/stdlib/atexit.h57
-rw-r--r--src/lib/libc/stdlib/atof.37
-rw-r--r--src/lib/libc/stdlib/atof.c3
-rw-r--r--src/lib/libc/stdlib/atoi.326
-rw-r--r--src/lib/libc/stdlib/atoi.c3
-rw-r--r--src/lib/libc/stdlib/atol.313
-rw-r--r--src/lib/libc/stdlib/atol.c3
-rw-r--r--src/lib/libc/stdlib/atoll.3 (renamed from src/lib/libc/stdlib/calloc.3)53
-rw-r--r--src/lib/libc/stdlib/atoll.c45
-rw-r--r--src/lib/libc/stdlib/bsearch.319
-rw-r--r--src/lib/libc/stdlib/bsearch.c5
-rw-r--r--src/lib/libc/stdlib/calloc.c14
-rw-r--r--src/lib/libc/stdlib/cfree.c49
-rw-r--r--src/lib/libc/stdlib/div.317
-rw-r--r--src/lib/libc/stdlib/div.c3
-rw-r--r--src/lib/libc/stdlib/drand48.c4
-rw-r--r--src/lib/libc/stdlib/ecvt.3172
-rw-r--r--src/lib/libc/stdlib/ecvt.c110
-rw-r--r--src/lib/libc/stdlib/erand48.c4
-rw-r--r--src/lib/libc/stdlib/exit.325
-rw-r--r--src/lib/libc/stdlib/exit.c36
-rw-r--r--src/lib/libc/stdlib/free.382
-rw-r--r--src/lib/libc/stdlib/gcvt.c106
-rw-r--r--src/lib/libc/stdlib/getenv.366
-rw-r--r--src/lib/libc/stdlib/getenv.c66
-rw-r--r--src/lib/libc/stdlib/getopt.3167
-rw-r--r--src/lib/libc/stdlib/getopt.c6
-rw-r--r--src/lib/libc/stdlib/getopt_long.3373
-rw-r--r--src/lib/libc/stdlib/getopt_long.c543
-rw-r--r--src/lib/libc/stdlib/getsubopt.3147
-rw-r--r--src/lib/libc/stdlib/getsubopt.c106
-rw-r--r--src/lib/libc/stdlib/heapsort.c5
-rw-r--r--src/lib/libc/stdlib/insque.3100
-rw-r--r--src/lib/libc/stdlib/insque.c52
-rw-r--r--src/lib/libc/stdlib/jrand48.c4
-rw-r--r--src/lib/libc/stdlib/l64a.c15
-rw-r--r--src/lib/libc/stdlib/labs.313
-rw-r--r--src/lib/libc/stdlib/labs.c3
-rw-r--r--src/lib/libc/stdlib/lcong48.c4
-rw-r--r--src/lib/libc/stdlib/ldiv.323
-rw-r--r--src/lib/libc/stdlib/ldiv.c3
-rw-r--r--src/lib/libc/stdlib/lrand48.c4
-rw-r--r--src/lib/libc/stdlib/lsearch.3 (renamed from src/lib/libc/stdlib/realloc.3)127
-rw-r--r--src/lib/libc/stdlib/lsearch.c90
-rw-r--r--src/lib/libc/stdlib/malloc.3376
-rw-r--r--src/lib/libc/stdlib/malloc.c1574
-rw-r--r--src/lib/libc/stdlib/memory.314
-rw-r--r--src/lib/libc/stdlib/merge.c17
-rw-r--r--src/lib/libc/stdlib/mrand48.c4
-rw-r--r--src/lib/libc/stdlib/multibyte.c9
-rw-r--r--src/lib/libc/stdlib/nrand48.c4
-rw-r--r--src/lib/libc/stdlib/putenv.c19
-rw-r--r--src/lib/libc/stdlib/qabs.312
-rw-r--r--src/lib/libc/stdlib/qabs.c3
-rw-r--r--src/lib/libc/stdlib/qdiv.316
-rw-r--r--src/lib/libc/stdlib/qdiv.c3
-rw-r--r--src/lib/libc/stdlib/qsort.357
-rw-r--r--src/lib/libc/stdlib/qsort.c34
-rw-r--r--src/lib/libc/stdlib/radixsort.333
-rw-r--r--src/lib/libc/stdlib/radixsort.c15
-rw-r--r--src/lib/libc/stdlib/rand.329
-rw-r--r--src/lib/libc/stdlib/rand.c18
-rw-r--r--src/lib/libc/stdlib/rand48.343
-rw-r--r--src/lib/libc/stdlib/rand48.h4
-rw-r--r--src/lib/libc/stdlib/random.3107
-rw-r--r--src/lib/libc/stdlib/random.c142
-rw-r--r--src/lib/libc/stdlib/realpath.320
-rw-r--r--src/lib/libc/stdlib/realpath.c27
-rw-r--r--src/lib/libc/stdlib/remque.c48
-rw-r--r--src/lib/libc/stdlib/seed48.c4
-rw-r--r--src/lib/libc/stdlib/setenv.c16
-rw-r--r--src/lib/libc/stdlib/srand48.c4
-rw-r--r--src/lib/libc/stdlib/strtod.337
-rw-r--r--src/lib/libc/stdlib/strtod.c253
-rw-r--r--src/lib/libc/stdlib/strtol.3142
-rw-r--r--src/lib/libc/stdlib/strtol.c70
-rw-r--r--src/lib/libc/stdlib/strtoll.c (renamed from src/lib/libc/stdlib/strtoq.c)90
-rw-r--r--src/lib/libc/stdlib/strtoul.3141
-rw-r--r--src/lib/libc/stdlib/strtoul.c44
-rw-r--r--src/lib/libc/stdlib/strtoull.c (renamed from src/lib/libc/stdlib/strtouq.c)62
-rw-r--r--src/lib/libc/stdlib/system.344
-rw-r--r--src/lib/libc/stdlib/system.c23
-rw-r--r--src/lib/libc/stdlib/tfind.c41
-rw-r--r--src/lib/libc/stdlib/tsearch.3127
-rw-r--r--src/lib/libc/stdlib/tsearch.c126
-rw-r--r--src/lib/libc/string/Makefile.inc64
-rw-r--r--src/lib/libc/string/__strerror.c40
-rw-r--r--src/lib/libc/string/__strsignal.c30
-rw-r--r--src/lib/libc/string/bcmp.310
-rw-r--r--src/lib/libc/string/bcmp.c8
-rw-r--r--src/lib/libc/string/bcopy.311
-rw-r--r--src/lib/libc/string/bcopy.c3
-rw-r--r--src/lib/libc/string/bm.3109
-rw-r--r--src/lib/libc/string/bm.c7
-rw-r--r--src/lib/libc/string/bstring.320
-rw-r--r--src/lib/libc/string/bzero.311
-rw-r--r--src/lib/libc/string/bzero.c7
-rw-r--r--src/lib/libc/string/ffs.39
-rw-r--r--src/lib/libc/string/ffs.c70
-rw-r--r--src/lib/libc/string/index.c8
-rw-r--r--src/lib/libc/string/memccpy.328
-rw-r--r--src/lib/libc/string/memccpy.c13
-rw-r--r--src/lib/libc/string/memchr.320
-rw-r--r--src/lib/libc/string/memchr.c11
-rw-r--r--src/lib/libc/string/memcmp.316
-rw-r--r--src/lib/libc/string/memcmp.c3
-rw-r--r--src/lib/libc/string/memcpy.315
-rw-r--r--src/lib/libc/string/memmove.312
-rw-r--r--src/lib/libc/string/memset.318
-rw-r--r--src/lib/libc/string/memset.c3
-rw-r--r--src/lib/libc/string/rindex.381
-rw-r--r--src/lib/libc/string/rindex.c8
-rw-r--r--src/lib/libc/string/strcasecmp.324
-rw-r--r--src/lib/libc/string/strcasecmp.c17
-rw-r--r--src/lib/libc/string/strcat.369
-rw-r--r--src/lib/libc/string/strcat.c9
-rw-r--r--src/lib/libc/string/strchr.352
-rw-r--r--src/lib/libc/string/strcmp.317
-rw-r--r--src/lib/libc/string/strcmp.c7
-rw-r--r--src/lib/libc/string/strcoll.311
-rw-r--r--src/lib/libc/string/strcoll.c3
-rw-r--r--src/lib/libc/string/strcpy.374
-rw-r--r--src/lib/libc/string/strcpy.c9
-rw-r--r--src/lib/libc/string/strcspn.331
-rw-r--r--src/lib/libc/string/strcspn.c3
-rw-r--r--src/lib/libc/string/strdup.355
-rw-r--r--src/lib/libc/string/strdup.c26
-rw-r--r--src/lib/libc/string/strerror.331
-rw-r--r--src/lib/libc/string/strerror.c5
-rw-r--r--src/lib/libc/string/strerror_r.c30
-rw-r--r--src/lib/libc/string/strftime.3202
-rw-r--r--src/lib/libc/string/strftime.c317
-rw-r--r--src/lib/libc/string/string.337
-rw-r--r--src/lib/libc/string/strlcat.c59
-rw-r--r--src/lib/libc/string/strlcpy.3179
-rw-r--r--src/lib/libc/string/strlcpy.c55
-rw-r--r--src/lib/libc/string/strlen.318
-rw-r--r--src/lib/libc/string/strlen.c20
-rw-r--r--src/lib/libc/string/strmode.372
-rw-r--r--src/lib/libc/string/strmode.c8
-rw-r--r--src/lib/libc/string/strncat.c3
-rw-r--r--src/lib/libc/string/strncmp.c7
-rw-r--r--src/lib/libc/string/strncpy.c3
-rw-r--r--src/lib/libc/string/strpbrk.316
-rw-r--r--src/lib/libc/string/strpbrk.c3
-rw-r--r--src/lib/libc/string/strrchr.353
-rw-r--r--src/lib/libc/string/strsep.384
-rw-r--r--src/lib/libc/string/strsep.c22
-rw-r--r--src/lib/libc/string/strsignal.35
-rw-r--r--src/lib/libc/string/strsignal.c5
-rw-r--r--src/lib/libc/string/strspn.330
-rw-r--r--src/lib/libc/string/strspn.c3
-rw-r--r--src/lib/libc/string/strstr.314
-rw-r--r--src/lib/libc/string/strstr.c3
-rw-r--r--src/lib/libc/string/strtok.384
-rw-r--r--src/lib/libc/string/strtok.c21
-rw-r--r--src/lib/libc/string/strxfrm.39
-rw-r--r--src/lib/libc/string/strxfrm.c3
-rw-r--r--src/lib/libc/string/swab.37
-rw-r--r--src/lib/libc/string/swab.c5
272 files changed, 25776 insertions, 4902 deletions
diff --git a/src/lib/libc/crypt/Makefile.inc b/src/lib/libc/crypt/Makefile.inc
new file mode 100644
index 0000000000..e64117fbd7
--- /dev/null
+++ b/src/lib/libc/crypt/Makefile.inc
@@ -0,0 +1,14 @@
1# $OpenBSD: Makefile.inc,v 1.13 1999/11/17 05:22:36 millert Exp $
2
3.PATH: ${LIBCSRCDIR}/arch/${MACHINE_ARCH}/crypt ${LIBCSRCDIR}/crypt
4
5SRCS+= cast.c crypt.c morecrypt.c md5crypt.c arc4random.c blowfish.c
6SRCS+= bcrypt.c skipjack.c
7
8MAN+= crypt.3 blowfish.3 arc4random.3
9MLINKS+=crypt.3 encrypt.3 crypt.3 setkey.3 crypt.3 des_cipher.3
10MLINKS+=crypt.3 des_setkey.3 blowfish.3 blf_key.3 blowfish.3 blf_enc.3
11MLINKS+=blowfish.3 blf_dec.3 blowfish.3 blf_ecb_encrypt.3
12MLINKS+=blowfish.3 blf_ecb_decrypt.3 blowfish.3 blf_cbc_encrypt.3
13MLINKS+=blowfish.3 blf_cbc_decrypt.3
14MLINKS+=arc4random.3 arc4random_stir.3 arc4random.3 arc4random_addrandom.3
diff --git a/src/lib/libc/crypt/arc4random.3 b/src/lib/libc/crypt/arc4random.3
new file mode 100644
index 0000000000..d8e0f8cda6
--- /dev/null
+++ b/src/lib/libc/crypt/arc4random.3
@@ -0,0 +1,110 @@
1.\" $OpenBSD: arc4random.3,v 1.17 2000/12/21 14:07:41 aaron Exp $
2.\"
3.\" Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>
4.\" All rights reserved.
5.\"
6.\" Redistribution and use in source and binary forms, with or without
7.\" modification, are permitted provided that the following conditions
8.\" are met:
9.\" 1. Redistributions of source code must retain the above copyright
10.\" notice, this list of conditions and the following disclaimer.
11.\" 2. Redistributions in binary form must reproduce the above copyright
12.\" notice, this list of conditions and the following disclaimer in the
13.\" documentation and/or other materials provided with the distribution.
14.\" 3. All advertising materials mentioning features or use of this software
15.\" must display the following acknowledgement:
16.\" This product includes software developed by Niels Provos.
17.\" 4. The name of the author may not be used to endorse or promote products
18.\" derived from this software without specific prior written permission.
19.\"
20.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30.\"
31.\" Manual page, using -mandoc macros
32.\"
33.Dd April 15, 1997
34.Dt ARC4RANDOM 3
35.Os
36.Sh NAME
37.Nm arc4random ,
38.Nm arc4random_stir ,
39.Nm arc4random_addrandom
40.Nd arc4 random number generator
41.Sh SYNOPSIS
42.Fd #include <stdlib.h>
43.Ft u_int32_t
44.Fn arc4random "void"
45.Ft void
46.Fn arc4random_stir "void"
47.Ft void
48.Fn arc4random_addrandom "u_char *dat" "int datlen"
49.Sh DESCRIPTION
50The
51.Fn arc4random
52function provides a high quality 32-bit pseudo-random
53number very quickly.
54.Fn arc4random
55seeds itself on a regular basis from the kernel strong random number
56subsystem described in
57.Xr random 4 .
58On each call, an ARC4 generator is used to generate a new result.
59The
60.Fn arc4random
61function uses the ARC4 cipher key stream generator,
62which uses 8*8 8 bit S-Boxes.
63The S-Boxes can be in about (2**1700) states.
64.Pp
65.Fn arc4random
66fits into a middle ground not covered by other subsystems such as
67the strong, slow, and resource expensive random
68devices described in
69.Xr random 4
70versus the fast but poor quality interfaces described in
71.Xr rand 3 ,
72.Xr random 3 ,
73and
74.Xr drand48 3 .
75.Pp
76The
77.Fn arc4random_stir
78function reads data from
79.Pa /dev/arandom
80and uses it to permute the S-Boxes via
81.Fn arc4random_addrandom .
82.Pp
83There is no need to call
84.Fn arc4random_stir
85before using
86.Fn arc4random ,
87since
88.Fn arc4random
89automatically initializes itself.
90.Sh SEE ALSO
91.Xr rand 3 ,
92.Xr rand48 3 ,
93.Xr random 3
94.Sh HISTORY
95An algorithm called
96.Pa RC4
97was designed by RSA Data Security, Inc.
98It was considered a trade secret, but not trademarked.
99Because it was a trade secret, it obviously could not be patented.
100A clone of this was posted anonymously to USENET and confirmed to
101be equivalent by several sources who had access to the original cipher.
102Because of the trade secret situation, RSA Data Security, Inc. can do
103nothing about the release of the ARC4 algorithm.
104Since
105.Pa RC4
106used to be a trade secret, the cipher is now referred to as
107.Pa ARC4 .
108.Pp
109These functions first appeared in
110.Ox 2.1 .
diff --git a/src/lib/libc/crypt/arc4random.c b/src/lib/libc/crypt/arc4random.c
new file mode 100644
index 0000000000..a41001bcc3
--- /dev/null
+++ b/src/lib/libc/crypt/arc4random.c
@@ -0,0 +1,195 @@
1/* $OpenBSD: arc4random.c,v 1.7 2003/02/14 17:12:54 deraadt Exp $ */
2
3/*
4 * Arc4 random number generator for OpenBSD.
5 * Copyright 1996 David Mazieres <dm@lcs.mit.edu>.
6 *
7 * Modification and redistribution in source and binary forms is
8 * permitted provided that due credit is given to the author and the
9 * OpenBSD project by leaving this copyright notice intact.
10 */
11
12/*
13 * This code is derived from section 17.1 of Applied Cryptography,
14 * second edition, which describes a stream cipher allegedly
15 * compatible with RSA Labs "RC4" cipher (the actual description of
16 * which is a trade secret). The same algorithm is used as a stream
17 * cipher called "arcfour" in Tatu Ylonen's ssh package.
18 *
19 * Here the stream cipher has been modified always to include the time
20 * when initializing the state. That makes it impossible to
21 * regenerate the same random sequence twice, so this can't be used
22 * for encryption, but will generate good random numbers.
23 *
24 * RC4 is a registered trademark of RSA Laboratories.
25 */
26
27#include <fcntl.h>
28#include <stdlib.h>
29#include <unistd.h>
30#include <sys/types.h>
31#include <sys/param.h>
32#include <sys/time.h>
33#include <sys/sysctl.h>
34
35#ifdef __GNUC__
36#define inline __inline
37#else /* !__GNUC__ */
38#define inline
39#endif /* !__GNUC__ */
40
41struct arc4_stream {
42 u_int8_t i;
43 u_int8_t j;
44 u_int8_t s[256];
45};
46
47static int rs_initialized;
48static struct arc4_stream rs;
49static pid_t arc4_stir_pid;
50
51static inline void
52arc4_init(as)
53 struct arc4_stream *as;
54{
55 int n;
56
57 for (n = 0; n < 256; n++)
58 as->s[n] = n;
59 as->i = 0;
60 as->j = 0;
61}
62
63static inline void
64arc4_addrandom(as, dat, datlen)
65 struct arc4_stream *as;
66 u_char *dat;
67 int datlen;
68{
69 int n;
70 u_int8_t si;
71
72 as->i--;
73 for (n = 0; n < 256; n++) {
74 as->i = (as->i + 1);
75 si = as->s[as->i];
76 as->j = (as->j + si + dat[n % datlen]);
77 as->s[as->i] = as->s[as->j];
78 as->s[as->j] = si;
79 }
80 as->j = as->i;
81}
82
83static void
84arc4_stir(as)
85 struct arc4_stream *as;
86{
87 int fd;
88 struct {
89 struct timeval tv;
90 u_int rnd[(128 - sizeof(struct timeval)) / sizeof(u_int)];
91 } rdat;
92
93 gettimeofday(&rdat.tv, NULL);
94 fd = open("/dev/arandom", O_RDONLY);
95 if (fd != -1) {
96 read(fd, rdat.rnd, sizeof(rdat.rnd));
97 close(fd);
98 } else {
99 int i, mib[2];
100 size_t len;
101
102 /* Device could not be opened, we might be chrooted, take
103 * randomness from sysctl. */
104
105 mib[0] = CTL_KERN;
106 mib[1] = KERN_ARND;
107
108 for (i = 0; i < sizeof(rdat.rnd) / sizeof(u_int); i ++) {
109 len = sizeof(u_int);
110 if (sysctl(mib, 2, &rdat.rnd[i], &len, NULL, 0) == -1)
111 break;
112 }
113 }
114 /* fd < 0 or failed sysctl ? Ah, what the heck. We'll just take
115 * whatever was on the stack... */
116
117 arc4_stir_pid = getpid();
118 arc4_addrandom(as, (void *) &rdat, sizeof(rdat));
119}
120
121static inline u_int8_t
122arc4_getbyte(as)
123 struct arc4_stream *as;
124{
125 u_int8_t si, sj;
126
127 as->i = (as->i + 1);
128 si = as->s[as->i];
129 as->j = (as->j + si);
130 sj = as->s[as->j];
131 as->s[as->i] = sj;
132 as->s[as->j] = si;
133 return (as->s[(si + sj) & 0xff]);
134}
135
136static inline u_int32_t
137arc4_getword(as)
138 struct arc4_stream *as;
139{
140 u_int32_t val;
141 val = arc4_getbyte(as) << 24;
142 val |= arc4_getbyte(as) << 16;
143 val |= arc4_getbyte(as) << 8;
144 val |= arc4_getbyte(as);
145 return val;
146}
147
148void
149arc4random_stir()
150{
151 if (!rs_initialized) {
152 arc4_init(&rs);
153 rs_initialized = 1;
154 }
155 arc4_stir(&rs);
156}
157
158void
159arc4random_addrandom(dat, datlen)
160 u_char *dat;
161 int datlen;
162{
163 if (!rs_initialized)
164 arc4random_stir();
165 arc4_addrandom(&rs, dat, datlen);
166}
167
168u_int32_t
169arc4random()
170{
171 if (!rs_initialized || arc4_stir_pid != getpid())
172 arc4random_stir();
173 return arc4_getword(&rs);
174}
175
176#if 0
177/*-------- Test code for i386 --------*/
178#include <stdio.h>
179#include <machine/pctr.h>
180int
181main(int argc, char **argv)
182{
183 const int iter = 1000000;
184 int i;
185 pctrval v;
186
187 v = rdtsc();
188 for (i = 0; i < iter; i++)
189 arc4random();
190 v = rdtsc() - v;
191 v /= iter;
192
193 printf("%qd cycles\n", v);
194}
195#endif
diff --git a/src/lib/libc/crypt/bcrypt.c b/src/lib/libc/crypt/bcrypt.c
new file mode 100644
index 0000000000..dec0093dd8
--- /dev/null
+++ b/src/lib/libc/crypt/bcrypt.c
@@ -0,0 +1,334 @@
1/* $OpenBSD: bcrypt.c,v 1.16 2002/02/19 19:39:36 millert Exp $ */
2
3/*
4 * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Niels Provos.
18 * 4. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33/* This password hashing algorithm was designed by David Mazieres
34 * <dm@lcs.mit.edu> and works as follows:
35 *
36 * 1. state := InitState ()
37 * 2. state := ExpandKey (state, salt, password) 3.
38 * REPEAT rounds:
39 * state := ExpandKey (state, 0, salt)
40 * state := ExpandKey(state, 0, password)
41 * 4. ctext := "OrpheanBeholderScryDoubt"
42 * 5. REPEAT 64:
43 * ctext := Encrypt_ECB (state, ctext);
44 * 6. RETURN Concatenate (salt, ctext);
45 *
46 */
47
48#if 0
49#include <stdio.h>
50#endif
51
52#include <stdio.h>
53#include <stdlib.h>
54#include <sys/types.h>
55#include <string.h>
56#include <pwd.h>
57#include <blf.h>
58
59/* This implementation is adaptable to current computing power.
60 * You can have up to 2^31 rounds which should be enough for some
61 * time to come.
62 */
63
64#define BCRYPT_VERSION '2'
65#define BCRYPT_MAXSALT 16 /* Precomputation is just so nice */
66#define BCRYPT_BLOCKS 6 /* Ciphertext blocks */
67#define BCRYPT_MINROUNDS 16 /* we have log2(rounds) in salt */
68
69char *bcrypt_gensalt(u_int8_t);
70
71static void encode_salt(char *, u_int8_t *, u_int16_t, u_int8_t);
72static void encode_base64(u_int8_t *, u_int8_t *, u_int16_t);
73static void decode_base64(u_int8_t *, u_int16_t, u_int8_t *);
74
75static char encrypted[_PASSWORD_LEN];
76static char gsalt[BCRYPT_MAXSALT * 4 / 3 + 1];
77static char error[] = ":";
78
79const static u_int8_t Base64Code[] =
80"./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
81
82const static u_int8_t index_64[128] =
83{
84 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
85 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
86 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
87 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
88 255, 255, 255, 255, 255, 255, 0, 1, 54, 55,
89 56, 57, 58, 59, 60, 61, 62, 63, 255, 255,
90 255, 255, 255, 255, 255, 2, 3, 4, 5, 6,
91 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
92 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
93 255, 255, 255, 255, 255, 255, 28, 29, 30,
94 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
95 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
96 51, 52, 53, 255, 255, 255, 255, 255
97};
98#define CHAR64(c) ( (c) > 127 ? 255 : index_64[(c)])
99
100static void
101decode_base64(u_int8_t *buffer, u_int16_t len, u_int8_t *data)
102{
103 u_int8_t *bp = buffer;
104 u_int8_t *p = data;
105 u_int8_t c1, c2, c3, c4;
106 while (bp < buffer + len) {
107 c1 = CHAR64(*p);
108 c2 = CHAR64(*(p + 1));
109
110 /* Invalid data */
111 if (c1 == 255 || c2 == 255)
112 break;
113
114 *bp++ = (c1 << 2) | ((c2 & 0x30) >> 4);
115 if (bp >= buffer + len)
116 break;
117
118 c3 = CHAR64(*(p + 2));
119 if (c3 == 255)
120 break;
121
122 *bp++ = ((c2 & 0x0f) << 4) | ((c3 & 0x3c) >> 2);
123 if (bp >= buffer + len)
124 break;
125
126 c4 = CHAR64(*(p + 3));
127 if (c4 == 255)
128 break;
129 *bp++ = ((c3 & 0x03) << 6) | c4;
130
131 p += 4;
132 }
133}
134
135static void
136encode_salt(char *salt, u_int8_t *csalt, u_int16_t clen, u_int8_t logr)
137{
138 salt[0] = '$';
139 salt[1] = BCRYPT_VERSION;
140 salt[2] = 'a';
141 salt[3] = '$';
142
143 snprintf(salt + 4, 4, "%2.2u$", logr);
144
145 encode_base64((u_int8_t *) salt + 7, csalt, clen);
146}
147/* Generates a salt for this version of crypt.
148 Since versions may change. Keeping this here
149 seems sensible.
150 */
151
152char *
153bcrypt_gensalt(u_int8_t log_rounds)
154{
155 u_int8_t csalt[BCRYPT_MAXSALT];
156 u_int16_t i;
157 u_int32_t seed = 0;
158
159 for (i = 0; i < BCRYPT_MAXSALT; i++) {
160 if (i % 4 == 0)
161 seed = arc4random();
162 csalt[i] = seed & 0xff;
163 seed = seed >> 8;
164 }
165
166 if (log_rounds < 4)
167 log_rounds = 4;
168
169 encode_salt(gsalt, csalt, BCRYPT_MAXSALT, log_rounds);
170 return gsalt;
171}
172/* We handle $Vers$log2(NumRounds)$salt+passwd$
173 i.e. $2$04$iwouldntknowwhattosayetKdJ6iFtacBqJdKe6aW7ou */
174
175char *
176bcrypt(key, salt)
177 const char *key;
178 const char *salt;
179{
180 blf_ctx state;
181 u_int32_t rounds, i, k;
182 u_int16_t j;
183 u_int8_t key_len, salt_len, logr, minor;
184 u_int8_t ciphertext[4 * BCRYPT_BLOCKS] = "OrpheanBeholderScryDoubt";
185 u_int8_t csalt[BCRYPT_MAXSALT];
186 u_int32_t cdata[BCRYPT_BLOCKS];
187
188 /* Discard "$" identifier */
189 salt++;
190
191 if (*salt > BCRYPT_VERSION) {
192 /* How do I handle errors ? Return ':' */
193 return error;
194 }
195
196 /* Check for minor versions */
197 if (salt[1] != '$') {
198 switch (salt[1]) {
199 case 'a':
200 /* 'ab' should not yield the same as 'abab' */
201 minor = salt[1];
202 salt++;
203 break;
204 default:
205 return error;
206 }
207 } else
208 minor = 0;
209
210 /* Discard version + "$" identifier */
211 salt += 2;
212
213 if (salt[2] != '$')
214 /* Out of sync with passwd entry */
215 return error;
216
217 /* Computer power doesn't increase linear, 2^x should be fine */
218 if ((rounds = (u_int32_t) 1 << (logr = atoi(salt))) < BCRYPT_MINROUNDS)
219 return error;
220
221 /* Discard num rounds + "$" identifier */
222 salt += 3;
223
224 if (strlen(salt) * 3 / 4 < BCRYPT_MAXSALT)
225 return error;
226
227 /* We dont want the base64 salt but the raw data */
228 decode_base64(csalt, BCRYPT_MAXSALT, (u_int8_t *) salt);
229 salt_len = BCRYPT_MAXSALT;
230 key_len = strlen(key) + (minor >= 'a' ? 1 : 0);
231
232 /* Setting up S-Boxes and Subkeys */
233 Blowfish_initstate(&state);
234 Blowfish_expandstate(&state, csalt, salt_len,
235 (u_int8_t *) key, key_len);
236 for (k = 0; k < rounds; k++) {
237 Blowfish_expand0state(&state, (u_int8_t *) key, key_len);
238 Blowfish_expand0state(&state, csalt, salt_len);
239 }
240
241 /* This can be precomputed later */
242 j = 0;
243 for (i = 0; i < BCRYPT_BLOCKS; i++)
244 cdata[i] = Blowfish_stream2word(ciphertext, 4 * BCRYPT_BLOCKS, &j);
245
246 /* Now do the encryption */
247 for (k = 0; k < 64; k++)
248 blf_enc(&state, cdata, BCRYPT_BLOCKS / 2);
249
250 for (i = 0; i < BCRYPT_BLOCKS; i++) {
251 ciphertext[4 * i + 3] = cdata[i] & 0xff;
252 cdata[i] = cdata[i] >> 8;
253 ciphertext[4 * i + 2] = cdata[i] & 0xff;
254 cdata[i] = cdata[i] >> 8;
255 ciphertext[4 * i + 1] = cdata[i] & 0xff;
256 cdata[i] = cdata[i] >> 8;
257 ciphertext[4 * i + 0] = cdata[i] & 0xff;
258 }
259
260
261 i = 0;
262 encrypted[i++] = '$';
263 encrypted[i++] = BCRYPT_VERSION;
264 if (minor)
265 encrypted[i++] = minor;
266 encrypted[i++] = '$';
267
268 snprintf(encrypted + i, 4, "%2.2u$", logr);
269
270 encode_base64((u_int8_t *) encrypted + i + 3, csalt, BCRYPT_MAXSALT);
271 encode_base64((u_int8_t *) encrypted + strlen(encrypted), ciphertext,
272 4 * BCRYPT_BLOCKS - 1);
273 return encrypted;
274}
275
276static void
277encode_base64(u_int8_t *buffer, u_int8_t *data, u_int16_t len)
278{
279 u_int8_t *bp = buffer;
280 u_int8_t *p = data;
281 u_int8_t c1, c2;
282 while (p < data + len) {
283 c1 = *p++;
284 *bp++ = Base64Code[(c1 >> 2)];
285 c1 = (c1 & 0x03) << 4;
286 if (p >= data + len) {
287 *bp++ = Base64Code[c1];
288 break;
289 }
290 c2 = *p++;
291 c1 |= (c2 >> 4) & 0x0f;
292 *bp++ = Base64Code[c1];
293 c1 = (c2 & 0x0f) << 2;
294 if (p >= data + len) {
295 *bp++ = Base64Code[c1];
296 break;
297 }
298 c2 = *p++;
299 c1 |= (c2 >> 6) & 0x03;
300 *bp++ = Base64Code[c1];
301 *bp++ = Base64Code[c2 & 0x3f];
302 }
303 *bp = '\0';
304}
305#if 0
306void
307main()
308{
309 char blubber[73];
310 char salt[100];
311 char *p;
312 salt[0] = '$';
313 salt[1] = BCRYPT_VERSION;
314 salt[2] = '$';
315
316 snprintf(salt + 3, 4, "%2.2u$", 5);
317
318 printf("24 bytes of salt: ");
319 fgets(salt + 6, 94, stdin);
320 salt[99] = 0;
321 printf("72 bytes of password: ");
322 fpurge(stdin);
323 fgets(blubber, 73, stdin);
324 blubber[72] = 0;
325
326 p = crypt(blubber, salt);
327 printf("Passwd entry: %s\n\n", p);
328
329 p = bcrypt_gensalt(5);
330 printf("Generated salt: %s\n", p);
331 p = crypt(blubber, p);
332 printf("Passwd entry: %s\n", p);
333}
334#endif
diff --git a/src/lib/libc/crypt/blowfish.3 b/src/lib/libc/crypt/blowfish.3
new file mode 100644
index 0000000000..3e600658fa
--- /dev/null
+++ b/src/lib/libc/crypt/blowfish.3
@@ -0,0 +1,106 @@
1.\" $OpenBSD: blowfish.3,v 1.10 2001/08/06 10:42:25 mpech Exp $
2.\"
3.\" Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>
4.\" All rights reserved.
5.\"
6.\" Redistribution and use in source and binary forms, with or without
7.\" modification, are permitted provided that the following conditions
8.\" are met:
9.\" 1. Redistributions of source code must retain the above copyright
10.\" notice, this list of conditions and the following disclaimer.
11.\" 2. Redistributions in binary form must reproduce the above copyright
12.\" notice, this list of conditions and the following disclaimer in the
13.\" documentation and/or other materials provided with the distribution.
14.\" 3. All advertising materials mentioning features or use of this software
15.\" must display the following acknowledgement:
16.\" This product includes software developed by Niels Provos.
17.\" 4. The name of the author may not be used to endorse or promote products
18.\" derived from this software without specific prior written permission.
19.\"
20.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30.\"
31.\" Manual page, using -mandoc macros
32.\"
33.Dd February 13, 1997
34.Dt BLOWFISH 3
35.Os
36.Sh NAME
37.Nm blf_key ,
38.Nm blf_enc ,
39.Nm blf_dec
40.Nd Blowfish encryption
41.Sh SYNOPSIS
42.Fd #include <blf.h>
43.Ft void
44.Fn blf_key "blf_ctx *state" "const u_int8_t *key" "u_int16_t keylen"
45.Ft void
46.Fn blf_enc "blf_ctx *state" "u_int32_t *data" "u_int16_t datalen"
47.Ft void
48.Fn blf_dec "blf_ctx *state" "u_int32_t *data" "u_int16_t datalen"
49.Ft void
50.Fn blf_ecb_encrypt "blf_ctx *state" "u_int8_t *data" "u_int32_t datalen"
51.Ft void
52.Fn blf_ecb_decrypt "blf_ctx *state" "u_int8_t *data" "u_int32_t datalen"
53.Ft void
54.Fn blf_cbc_encrypt "blf_ctx *state" "u_int8_t *iv" "u_int8_t *data" "u_int32_t datalen"
55.Ft void
56.Fn blf_cbc_decrypt "blf_ctx *state" "u_int8_t *iv" "u_int8_t *data" "u_int32_t datalen"
57.Sh DESCRIPTION
58.Pa Blowfish
59is a fast unpatented block cipher designed by Bruce Schneier.
60It basically consists of a 16 times iterated Feistel network.
61The block size is 64 bit and the key size is maximal 448 bit.
62.Pp
63The
64.Fn blf_key
65function initializes the 4 8bit S-boxes and the 18 Subkeys with
66the hexadecimal digits of Pi.
67The key is used for further randomization.
68The first argument to
69.Fn blf_enc
70is the initialized state derived from
71.Fn blf_key .
72The stream of 32-bit words is encrypted in Electronic Codebook
73Mode (ECB) and
74.Pa datalen
75must be even.
76.Fn blf_dec
77is used for decrypting Blowfish encrypted blocks.
78.Pp
79The functions
80.Fn blf_ecb_encrypt
81and
82.Fn blf_ecb_decrypt
83are used for encrypting and decrypting octet streams in ECB mode.
84The functions
85.Fn blf_cbc_encrypt
86and
87.Fn blf_cbc_decrypt
88are used for encrypting and decrypting octet streams in
89Cipherblock Chaining Mode (CBC).
90.Pp
91The functions
92.Fn Blowfish_initstate ,
93.Fn Blowfish_expand0state ,
94.Fn Blowfish_expandstate ,
95.Fn Blowfish_encipher
96and
97.Fn Blowfish_decipher
98are used for customization of the
99.Pa Blowfish
100cipher, e.g., for the blowfish password hashing function.
101.Sh SEE ALSO
102.Xr passwd 1 ,
103.Xr crypt 3 ,
104.Xr passwd 5
105.Sh AUTHORS
106Niels Provos <provos@physnet.uni-hamburg.de>
diff --git a/src/lib/libc/crypt/blowfish.c b/src/lib/libc/crypt/blowfish.c
new file mode 100644
index 0000000000..12226b5215
--- /dev/null
+++ b/src/lib/libc/crypt/blowfish.c
@@ -0,0 +1,694 @@
1/* $OpenBSD: blowfish.c,v 1.17 2003/04/09 21:46:02 markus Exp $ */
2/*
3 * Blowfish block cipher for OpenBSD
4 * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>
5 * All rights reserved.
6 *
7 * Implementation advice by David Mazieres <dm@lcs.mit.edu>.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by Niels Provos.
20 * 4. The name of the author may not be used to endorse or promote products
21 * derived from this software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35/*
36 * This code is derived from section 14.3 and the given source
37 * in section V of Applied Cryptography, second edition.
38 * Blowfish is an unpatented fast block cipher designed by
39 * Bruce Schneier.
40 */
41
42#if 0
43#include <stdio.h> /* used for debugging */
44#include <string.h>
45#endif
46
47#include <sys/types.h>
48#include <blf.h>
49
50#undef inline
51#ifdef __GNUC__
52#define inline __inline
53#else /* !__GNUC__ */
54#define inline
55#endif /* !__GNUC__ */
56
57/* Function for Feistel Networks */
58
59#define F(s, x) ((((s)[ (((x)>>24)&0xFF)] \
60 + (s)[0x100 + (((x)>>16)&0xFF)]) \
61 ^ (s)[0x200 + (((x)>> 8)&0xFF)]) \
62 + (s)[0x300 + ( (x) &0xFF)])
63
64#define BLFRND(s,p,i,j,n) (i ^= F(s,j) ^ (p)[n])
65
66void
67Blowfish_encipher(c, xl, xr)
68 blf_ctx *c;
69 u_int32_t *xl;
70 u_int32_t *xr;
71{
72 u_int32_t Xl;
73 u_int32_t Xr;
74 u_int32_t *s = c->S[0];
75 u_int32_t *p = c->P;
76
77 Xl = *xl;
78 Xr = *xr;
79
80 Xl ^= p[0];
81 BLFRND(s, p, Xr, Xl, 1); BLFRND(s, p, Xl, Xr, 2);
82 BLFRND(s, p, Xr, Xl, 3); BLFRND(s, p, Xl, Xr, 4);
83 BLFRND(s, p, Xr, Xl, 5); BLFRND(s, p, Xl, Xr, 6);
84 BLFRND(s, p, Xr, Xl, 7); BLFRND(s, p, Xl, Xr, 8);
85 BLFRND(s, p, Xr, Xl, 9); BLFRND(s, p, Xl, Xr, 10);
86 BLFRND(s, p, Xr, Xl, 11); BLFRND(s, p, Xl, Xr, 12);
87 BLFRND(s, p, Xr, Xl, 13); BLFRND(s, p, Xl, Xr, 14);
88 BLFRND(s, p, Xr, Xl, 15); BLFRND(s, p, Xl, Xr, 16);
89
90 *xl = Xr ^ p[17];
91 *xr = Xl;
92}
93
94void
95Blowfish_decipher(c, xl, xr)
96 blf_ctx *c;
97 u_int32_t *xl;
98 u_int32_t *xr;
99{
100 u_int32_t Xl;
101 u_int32_t Xr;
102 u_int32_t *s = c->S[0];
103 u_int32_t *p = c->P;
104
105 Xl = *xl;
106 Xr = *xr;
107
108 Xl ^= p[17];
109 BLFRND(s, p, Xr, Xl, 16); BLFRND(s, p, Xl, Xr, 15);
110 BLFRND(s, p, Xr, Xl, 14); BLFRND(s, p, Xl, Xr, 13);
111 BLFRND(s, p, Xr, Xl, 12); BLFRND(s, p, Xl, Xr, 11);
112 BLFRND(s, p, Xr, Xl, 10); BLFRND(s, p, Xl, Xr, 9);
113 BLFRND(s, p, Xr, Xl, 8); BLFRND(s, p, Xl, Xr, 7);
114 BLFRND(s, p, Xr, Xl, 6); BLFRND(s, p, Xl, Xr, 5);
115 BLFRND(s, p, Xr, Xl, 4); BLFRND(s, p, Xl, Xr, 3);
116 BLFRND(s, p, Xr, Xl, 2); BLFRND(s, p, Xl, Xr, 1);
117
118 *xl = Xr ^ p[0];
119 *xr = Xl;
120}
121
122void
123Blowfish_initstate(c)
124 blf_ctx *c;
125{
126
127/* P-box and S-box tables initialized with digits of Pi */
128
129 static const blf_ctx initstate =
130
131 { {
132 {
133 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7,
134 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
135 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
136 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
137 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee,
138 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
139 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef,
140 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
141 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
142 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
143 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce,
144 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
145 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e,
146 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
147 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
148 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
149 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88,
150 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
151 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e,
152 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
153 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
154 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,
155 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88,
156 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
157 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6,
158 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,
159 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
160 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
161 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba,
162 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
163 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f,
164 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
165 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
166 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,
167 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279,
168 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
169 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab,
170 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,
171 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
172 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
173 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0,
174 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
175 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790,
176 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,
177 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
178 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
179 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7,
180 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
181 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad,
182 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
183 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
184 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
185 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477,
186 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
187 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49,
188 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
189 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
190 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
191 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41,
192 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
193 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400,
194 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
195 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
196 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a},
197 {
198 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623,
199 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
200 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
201 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,
202 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6,
203 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
204 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e,
205 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
206 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
207 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,
208 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff,
209 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
210 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701,
211 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
212 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
213 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,
214 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf,
215 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
216 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e,
217 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
218 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
219 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2,
220 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16,
221 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
222 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b,
223 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
224 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
225 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,
226 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f,
227 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
228 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4,
229 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
230 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
231 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,
232 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802,
233 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
234 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510,
235 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
236 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
237 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e,
238 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50,
239 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
240 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8,
241 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
242 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
243 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
244 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128,
245 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
246 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0,
247 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
248 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
249 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,
250 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3,
251 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
252 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00,
253 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
254 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
255 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,
256 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735,
257 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
258 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9,
259 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
260 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
261 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7},
262 {
263 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934,
264 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
265 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
266 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
267 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45,
268 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
269 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a,
270 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
271 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
272 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
273 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42,
274 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
275 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2,
276 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
277 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
278 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
279 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33,
280 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
281 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3,
282 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
283 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
284 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
285 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b,
286 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
287 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922,
288 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
289 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
290 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
291 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37,
292 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
293 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804,
294 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
295 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
296 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
297 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d,
298 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
299 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350,
300 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
301 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
302 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
303 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d,
304 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
305 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f,
306 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
307 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
308 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
309 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2,
310 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
311 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e,
312 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,
313 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
314 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
315 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52,
316 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
317 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5,
318 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
319 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
320 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
321 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24,
322 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
323 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4,
324 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
325 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
326 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0},
327 {
328 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b,
329 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
330 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
331 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
332 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8,
333 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
334 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304,
335 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
336 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
337 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,
338 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9,
339 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
340 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593,
341 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
342 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
343 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,
344 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b,
345 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
346 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c,
347 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,
348 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
349 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
350 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb,
351 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
352 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991,
353 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,
354 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
355 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
356 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae,
357 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
358 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5,
359 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,
360 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
361 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,
362 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84,
363 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
364 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8,
365 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,
366 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
367 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,
368 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38,
369 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
370 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c,
371 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,
372 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
373 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
374 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964,
375 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
376 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8,
377 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,
378 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
379 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,
380 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02,
381 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
382 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614,
383 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,
384 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
385 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
386 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0,
387 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
388 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e,
389 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
390 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
391 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6}
392 },
393 {
394 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,
395 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,
396 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
397 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,
398 0x9216d5d9, 0x8979fb1b
399 } };
400
401 *c = initstate;
402
403}
404
405u_int32_t
406Blowfish_stream2word(const u_int8_t *data, u_int16_t databytes, u_int16_t *current)
407{
408 u_int8_t i;
409 u_int16_t j;
410 u_int32_t temp;
411
412 temp = 0x00000000;
413 j = *current;
414
415 for (i = 0; i < 4; i++, j++) {
416 if (j >= databytes)
417 j = 0;
418 temp = (temp << 8) | data[j];
419 }
420
421 *current = j;
422 return temp;
423}
424
425void
426Blowfish_expand0state(blf_ctx *c, const u_int8_t *key, u_int16_t keybytes)
427{
428 u_int16_t i;
429 u_int16_t j;
430 u_int16_t k;
431 u_int32_t temp;
432 u_int32_t datal;
433 u_int32_t datar;
434
435 j = 0;
436 for (i = 0; i < BLF_N + 2; i++) {
437 /* Extract 4 int8 to 1 int32 from keystream */
438 temp = Blowfish_stream2word(key, keybytes, &j);
439 c->P[i] = c->P[i] ^ temp;
440 }
441
442 j = 0;
443 datal = 0x00000000;
444 datar = 0x00000000;
445 for (i = 0; i < BLF_N + 2; i += 2) {
446 Blowfish_encipher(c, &datal, &datar);
447
448 c->P[i] = datal;
449 c->P[i + 1] = datar;
450 }
451
452 for (i = 0; i < 4; i++) {
453 for (k = 0; k < 256; k += 2) {
454 Blowfish_encipher(c, &datal, &datar);
455
456 c->S[i][k] = datal;
457 c->S[i][k + 1] = datar;
458 }
459 }
460}
461
462
463void
464Blowfish_expandstate(blf_ctx *c, const u_int8_t *data, u_int16_t databytes,
465 const u_int8_t *key, u_int16_t keybytes)
466{
467 u_int16_t i;
468 u_int16_t j;
469 u_int16_t k;
470 u_int32_t temp;
471 u_int32_t datal;
472 u_int32_t datar;
473
474 j = 0;
475 for (i = 0; i < BLF_N + 2; i++) {
476 /* Extract 4 int8 to 1 int32 from keystream */
477 temp = Blowfish_stream2word(key, keybytes, &j);
478 c->P[i] = c->P[i] ^ temp;
479 }
480
481 j = 0;
482 datal = 0x00000000;
483 datar = 0x00000000;
484 for (i = 0; i < BLF_N + 2; i += 2) {
485 datal ^= Blowfish_stream2word(data, databytes, &j);
486 datar ^= Blowfish_stream2word(data, databytes, &j);
487 Blowfish_encipher(c, &datal, &datar);
488
489 c->P[i] = datal;
490 c->P[i + 1] = datar;
491 }
492
493 for (i = 0; i < 4; i++) {
494 for (k = 0; k < 256; k += 2) {
495 datal ^= Blowfish_stream2word(data, databytes, &j);
496 datar ^= Blowfish_stream2word(data, databytes, &j);
497 Blowfish_encipher(c, &datal, &datar);
498
499 c->S[i][k] = datal;
500 c->S[i][k + 1] = datar;
501 }
502 }
503
504}
505
506void
507blf_key(blf_ctx *c, const u_int8_t *k, u_int16_t len)
508{
509 /* Initialize S-boxes and subkeys with Pi */
510 Blowfish_initstate(c);
511
512 /* Transform S-boxes and subkeys with key */
513 Blowfish_expand0state(c, k, len);
514}
515
516void
517blf_enc(blf_ctx *c, u_int32_t *data, u_int16_t blocks)
518{
519 u_int32_t *d;
520 u_int16_t i;
521
522 d = data;
523 for (i = 0; i < blocks; i++) {
524 Blowfish_encipher(c, d, d + 1);
525 d += 2;
526 }
527}
528
529void
530blf_dec(blf_ctx *c, u_int32_t *data, u_int16_t blocks)
531{
532 u_int32_t *d;
533 u_int16_t i;
534
535 d = data;
536 for (i = 0; i < blocks; i++) {
537 Blowfish_decipher(c, d, d + 1);
538 d += 2;
539 }
540}
541
542void
543blf_ecb_encrypt(blf_ctx *c, u_int8_t *data, u_int32_t len)
544{
545 u_int32_t l, r;
546 u_int32_t i;
547
548 for (i = 0; i < len; i += 8) {
549 l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
550 r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7];
551 Blowfish_encipher(c, &l, &r);
552 data[0] = l >> 24 & 0xff;
553 data[1] = l >> 16 & 0xff;
554 data[2] = l >> 8 & 0xff;
555 data[3] = l & 0xff;
556 data[4] = r >> 24 & 0xff;
557 data[5] = r >> 16 & 0xff;
558 data[6] = r >> 8 & 0xff;
559 data[7] = r & 0xff;
560 data += 8;
561 }
562}
563
564void
565blf_ecb_decrypt(blf_ctx *c, u_int8_t *data, u_int32_t len)
566{
567 u_int32_t l, r;
568 u_int32_t i;
569
570 for (i = 0; i < len; i += 8) {
571 l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
572 r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7];
573 Blowfish_decipher(c, &l, &r);
574 data[0] = l >> 24 & 0xff;
575 data[1] = l >> 16 & 0xff;
576 data[2] = l >> 8 & 0xff;
577 data[3] = l & 0xff;
578 data[4] = r >> 24 & 0xff;
579 data[5] = r >> 16 & 0xff;
580 data[6] = r >> 8 & 0xff;
581 data[7] = r & 0xff;
582 data += 8;
583 }
584}
585
586void
587blf_cbc_encrypt(blf_ctx *c, u_int8_t *iv, u_int8_t *data, u_int32_t len)
588{
589 u_int32_t l, r;
590 u_int32_t i, j;
591
592 for (i = 0; i < len; i += 8) {
593 for (j = 0; j < 8; j++)
594 data[j] ^= iv[j];
595 l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
596 r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7];
597 Blowfish_encipher(c, &l, &r);
598 data[0] = l >> 24 & 0xff;
599 data[1] = l >> 16 & 0xff;
600 data[2] = l >> 8 & 0xff;
601 data[3] = l & 0xff;
602 data[4] = r >> 24 & 0xff;
603 data[5] = r >> 16 & 0xff;
604 data[6] = r >> 8 & 0xff;
605 data[7] = r & 0xff;
606 iv = data;
607 data += 8;
608 }
609}
610
611void
612blf_cbc_decrypt(blf_ctx *c, u_int8_t *iva, u_int8_t *data, u_int32_t len)
613{
614 u_int32_t l, r;
615 u_int8_t *iv;
616 u_int32_t i, j;
617
618 iv = data + len - 16;
619 data = data + len - 8;
620 for (i = len - 8; i >= 8; i -= 8) {
621 l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
622 r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7];
623 Blowfish_decipher(c, &l, &r);
624 data[0] = l >> 24 & 0xff;
625 data[1] = l >> 16 & 0xff;
626 data[2] = l >> 8 & 0xff;
627 data[3] = l & 0xff;
628 data[4] = r >> 24 & 0xff;
629 data[5] = r >> 16 & 0xff;
630 data[6] = r >> 8 & 0xff;
631 data[7] = r & 0xff;
632 for (j = 0; j < 8; j++)
633 data[j] ^= iv[j];
634 iv -= 8;
635 data -= 8;
636 }
637 l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
638 r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7];
639 Blowfish_decipher(c, &l, &r);
640 data[0] = l >> 24 & 0xff;
641 data[1] = l >> 16 & 0xff;
642 data[2] = l >> 8 & 0xff;
643 data[3] = l & 0xff;
644 data[4] = r >> 24 & 0xff;
645 data[5] = r >> 16 & 0xff;
646 data[6] = r >> 8 & 0xff;
647 data[7] = r & 0xff;
648 for (j = 0; j < 8; j++)
649 data[j] ^= iva[j];
650}
651
652#if 0
653void
654report(u_int32_t data[], u_int16_t len)
655{
656 u_int16_t i;
657 for (i = 0; i < len; i += 2)
658 printf("Block %0hd: %08lx %08lx.\n",
659 i / 2, data[i], data[i + 1]);
660}
661void
662main(void)
663{
664
665 blf_ctx c;
666 char key[] = "AAAAA";
667 char key2[] = "abcdefghijklmnopqrstuvwxyz";
668
669 u_int32_t data[10];
670 u_int32_t data2[] =
671 {0x424c4f57l, 0x46495348l};
672
673 u_int16_t i;
674
675 /* First test */
676 for (i = 0; i < 10; i++)
677 data[i] = i;
678
679 blf_key(&c, (u_int8_t *) key, 5);
680 blf_enc(&c, data, 5);
681 blf_dec(&c, data, 1);
682 blf_dec(&c, data + 2, 4);
683 printf("Should read as 0 - 9.\n");
684 report(data, 10);
685
686 /* Second test */
687 blf_key(&c, (u_int8_t *) key2, strlen(key2));
688 blf_enc(&c, data2, 1);
689 printf("\nShould read as: 0x324ed0fe 0xf413a203.\n");
690 report(data2, 2);
691 blf_dec(&c, data2, 1);
692 report(data2, 2);
693}
694#endif
diff --git a/src/lib/libc/crypt/cast.c b/src/lib/libc/crypt/cast.c
new file mode 100644
index 0000000000..264138f03e
--- /dev/null
+++ b/src/lib/libc/crypt/cast.c
@@ -0,0 +1,779 @@
1/* $OpenBSD: cast.c,v 1.2 1998/07/21 22:42:03 provos Exp $ */
2/*
3 * CAST-128 in C
4 * Written by Steve Reid <sreid@sea-to-sky.net>
5 * 100% Public Domain - no warranty
6 * Released 1997.10.11
7 */
8
9#include <sys/types.h>
10
11#include <cast.h>
12
13/* CAST S-Boxes */
14
15static const u_int32_t cast_sbox1[256] = {
16 0x30FB40D4, 0x9FA0FF0B, 0x6BECCD2F, 0x3F258C7A,
17 0x1E213F2F, 0x9C004DD3, 0x6003E540, 0xCF9FC949,
18 0xBFD4AF27, 0x88BBBDB5, 0xE2034090, 0x98D09675,
19 0x6E63A0E0, 0x15C361D2, 0xC2E7661D, 0x22D4FF8E,
20 0x28683B6F, 0xC07FD059, 0xFF2379C8, 0x775F50E2,
21 0x43C340D3, 0xDF2F8656, 0x887CA41A, 0xA2D2BD2D,
22 0xA1C9E0D6, 0x346C4819, 0x61B76D87, 0x22540F2F,
23 0x2ABE32E1, 0xAA54166B, 0x22568E3A, 0xA2D341D0,
24 0x66DB40C8, 0xA784392F, 0x004DFF2F, 0x2DB9D2DE,
25 0x97943FAC, 0x4A97C1D8, 0x527644B7, 0xB5F437A7,
26 0xB82CBAEF, 0xD751D159, 0x6FF7F0ED, 0x5A097A1F,
27 0x827B68D0, 0x90ECF52E, 0x22B0C054, 0xBC8E5935,
28 0x4B6D2F7F, 0x50BB64A2, 0xD2664910, 0xBEE5812D,
29 0xB7332290, 0xE93B159F, 0xB48EE411, 0x4BFF345D,
30 0xFD45C240, 0xAD31973F, 0xC4F6D02E, 0x55FC8165,
31 0xD5B1CAAD, 0xA1AC2DAE, 0xA2D4B76D, 0xC19B0C50,
32 0x882240F2, 0x0C6E4F38, 0xA4E4BFD7, 0x4F5BA272,
33 0x564C1D2F, 0xC59C5319, 0xB949E354, 0xB04669FE,
34 0xB1B6AB8A, 0xC71358DD, 0x6385C545, 0x110F935D,
35 0x57538AD5, 0x6A390493, 0xE63D37E0, 0x2A54F6B3,
36 0x3A787D5F, 0x6276A0B5, 0x19A6FCDF, 0x7A42206A,
37 0x29F9D4D5, 0xF61B1891, 0xBB72275E, 0xAA508167,
38 0x38901091, 0xC6B505EB, 0x84C7CB8C, 0x2AD75A0F,
39 0x874A1427, 0xA2D1936B, 0x2AD286AF, 0xAA56D291,
40 0xD7894360, 0x425C750D, 0x93B39E26, 0x187184C9,
41 0x6C00B32D, 0x73E2BB14, 0xA0BEBC3C, 0x54623779,
42 0x64459EAB, 0x3F328B82, 0x7718CF82, 0x59A2CEA6,
43 0x04EE002E, 0x89FE78E6, 0x3FAB0950, 0x325FF6C2,
44 0x81383F05, 0x6963C5C8, 0x76CB5AD6, 0xD49974C9,
45 0xCA180DCF, 0x380782D5, 0xC7FA5CF6, 0x8AC31511,
46 0x35E79E13, 0x47DA91D0, 0xF40F9086, 0xA7E2419E,
47 0x31366241, 0x051EF495, 0xAA573B04, 0x4A805D8D,
48 0x548300D0, 0x00322A3C, 0xBF64CDDF, 0xBA57A68E,
49 0x75C6372B, 0x50AFD341, 0xA7C13275, 0x915A0BF5,
50 0x6B54BFAB, 0x2B0B1426, 0xAB4CC9D7, 0x449CCD82,
51 0xF7FBF265, 0xAB85C5F3, 0x1B55DB94, 0xAAD4E324,
52 0xCFA4BD3F, 0x2DEAA3E2, 0x9E204D02, 0xC8BD25AC,
53 0xEADF55B3, 0xD5BD9E98, 0xE31231B2, 0x2AD5AD6C,
54 0x954329DE, 0xADBE4528, 0xD8710F69, 0xAA51C90F,
55 0xAA786BF6, 0x22513F1E, 0xAA51A79B, 0x2AD344CC,
56 0x7B5A41F0, 0xD37CFBAD, 0x1B069505, 0x41ECE491,
57 0xB4C332E6, 0x032268D4, 0xC9600ACC, 0xCE387E6D,
58 0xBF6BB16C, 0x6A70FB78, 0x0D03D9C9, 0xD4DF39DE,
59 0xE01063DA, 0x4736F464, 0x5AD328D8, 0xB347CC96,
60 0x75BB0FC3, 0x98511BFB, 0x4FFBCC35, 0xB58BCF6A,
61 0xE11F0ABC, 0xBFC5FE4A, 0xA70AEC10, 0xAC39570A,
62 0x3F04442F, 0x6188B153, 0xE0397A2E, 0x5727CB79,
63 0x9CEB418F, 0x1CACD68D, 0x2AD37C96, 0x0175CB9D,
64 0xC69DFF09, 0xC75B65F0, 0xD9DB40D8, 0xEC0E7779,
65 0x4744EAD4, 0xB11C3274, 0xDD24CB9E, 0x7E1C54BD,
66 0xF01144F9, 0xD2240EB1, 0x9675B3FD, 0xA3AC3755,
67 0xD47C27AF, 0x51C85F4D, 0x56907596, 0xA5BB15E6,
68 0x580304F0, 0xCA042CF1, 0x011A37EA, 0x8DBFAADB,
69 0x35BA3E4A, 0x3526FFA0, 0xC37B4D09, 0xBC306ED9,
70 0x98A52666, 0x5648F725, 0xFF5E569D, 0x0CED63D0,
71 0x7C63B2CF, 0x700B45E1, 0xD5EA50F1, 0x85A92872,
72 0xAF1FBDA7, 0xD4234870, 0xA7870BF3, 0x2D3B4D79,
73 0x42E04198, 0x0CD0EDE7, 0x26470DB8, 0xF881814C,
74 0x474D6AD7, 0x7C0C5E5C, 0xD1231959, 0x381B7298,
75 0xF5D2F4DB, 0xAB838653, 0x6E2F1E23, 0x83719C9E,
76 0xBD91E046, 0x9A56456E, 0xDC39200C, 0x20C8C571,
77 0x962BDA1C, 0xE1E696FF, 0xB141AB08, 0x7CCA89B9,
78 0x1A69E783, 0x02CC4843, 0xA2F7C579, 0x429EF47D,
79 0x427B169C, 0x5AC9F049, 0xDD8F0F00, 0x5C8165BF
80};
81
82static const u_int32_t cast_sbox2[256] = {
83 0x1F201094, 0xEF0BA75B, 0x69E3CF7E, 0x393F4380,
84 0xFE61CF7A, 0xEEC5207A, 0x55889C94, 0x72FC0651,
85 0xADA7EF79, 0x4E1D7235, 0xD55A63CE, 0xDE0436BA,
86 0x99C430EF, 0x5F0C0794, 0x18DCDB7D, 0xA1D6EFF3,
87 0xA0B52F7B, 0x59E83605, 0xEE15B094, 0xE9FFD909,
88 0xDC440086, 0xEF944459, 0xBA83CCB3, 0xE0C3CDFB,
89 0xD1DA4181, 0x3B092AB1, 0xF997F1C1, 0xA5E6CF7B,
90 0x01420DDB, 0xE4E7EF5B, 0x25A1FF41, 0xE180F806,
91 0x1FC41080, 0x179BEE7A, 0xD37AC6A9, 0xFE5830A4,
92 0x98DE8B7F, 0x77E83F4E, 0x79929269, 0x24FA9F7B,
93 0xE113C85B, 0xACC40083, 0xD7503525, 0xF7EA615F,
94 0x62143154, 0x0D554B63, 0x5D681121, 0xC866C359,
95 0x3D63CF73, 0xCEE234C0, 0xD4D87E87, 0x5C672B21,
96 0x071F6181, 0x39F7627F, 0x361E3084, 0xE4EB573B,
97 0x602F64A4, 0xD63ACD9C, 0x1BBC4635, 0x9E81032D,
98 0x2701F50C, 0x99847AB4, 0xA0E3DF79, 0xBA6CF38C,
99 0x10843094, 0x2537A95E, 0xF46F6FFE, 0xA1FF3B1F,
100 0x208CFB6A, 0x8F458C74, 0xD9E0A227, 0x4EC73A34,
101 0xFC884F69, 0x3E4DE8DF, 0xEF0E0088, 0x3559648D,
102 0x8A45388C, 0x1D804366, 0x721D9BFD, 0xA58684BB,
103 0xE8256333, 0x844E8212, 0x128D8098, 0xFED33FB4,
104 0xCE280AE1, 0x27E19BA5, 0xD5A6C252, 0xE49754BD,
105 0xC5D655DD, 0xEB667064, 0x77840B4D, 0xA1B6A801,
106 0x84DB26A9, 0xE0B56714, 0x21F043B7, 0xE5D05860,
107 0x54F03084, 0x066FF472, 0xA31AA153, 0xDADC4755,
108 0xB5625DBF, 0x68561BE6, 0x83CA6B94, 0x2D6ED23B,
109 0xECCF01DB, 0xA6D3D0BA, 0xB6803D5C, 0xAF77A709,
110 0x33B4A34C, 0x397BC8D6, 0x5EE22B95, 0x5F0E5304,
111 0x81ED6F61, 0x20E74364, 0xB45E1378, 0xDE18639B,
112 0x881CA122, 0xB96726D1, 0x8049A7E8, 0x22B7DA7B,
113 0x5E552D25, 0x5272D237, 0x79D2951C, 0xC60D894C,
114 0x488CB402, 0x1BA4FE5B, 0xA4B09F6B, 0x1CA815CF,
115 0xA20C3005, 0x8871DF63, 0xB9DE2FCB, 0x0CC6C9E9,
116 0x0BEEFF53, 0xE3214517, 0xB4542835, 0x9F63293C,
117 0xEE41E729, 0x6E1D2D7C, 0x50045286, 0x1E6685F3,
118 0xF33401C6, 0x30A22C95, 0x31A70850, 0x60930F13,
119 0x73F98417, 0xA1269859, 0xEC645C44, 0x52C877A9,
120 0xCDFF33A6, 0xA02B1741, 0x7CBAD9A2, 0x2180036F,
121 0x50D99C08, 0xCB3F4861, 0xC26BD765, 0x64A3F6AB,
122 0x80342676, 0x25A75E7B, 0xE4E6D1FC, 0x20C710E6,
123 0xCDF0B680, 0x17844D3B, 0x31EEF84D, 0x7E0824E4,
124 0x2CCB49EB, 0x846A3BAE, 0x8FF77888, 0xEE5D60F6,
125 0x7AF75673, 0x2FDD5CDB, 0xA11631C1, 0x30F66F43,
126 0xB3FAEC54, 0x157FD7FA, 0xEF8579CC, 0xD152DE58,
127 0xDB2FFD5E, 0x8F32CE19, 0x306AF97A, 0x02F03EF8,
128 0x99319AD5, 0xC242FA0F, 0xA7E3EBB0, 0xC68E4906,
129 0xB8DA230C, 0x80823028, 0xDCDEF3C8, 0xD35FB171,
130 0x088A1BC8, 0xBEC0C560, 0x61A3C9E8, 0xBCA8F54D,
131 0xC72FEFFA, 0x22822E99, 0x82C570B4, 0xD8D94E89,
132 0x8B1C34BC, 0x301E16E6, 0x273BE979, 0xB0FFEAA6,
133 0x61D9B8C6, 0x00B24869, 0xB7FFCE3F, 0x08DC283B,
134 0x43DAF65A, 0xF7E19798, 0x7619B72F, 0x8F1C9BA4,
135 0xDC8637A0, 0x16A7D3B1, 0x9FC393B7, 0xA7136EEB,
136 0xC6BCC63E, 0x1A513742, 0xEF6828BC, 0x520365D6,
137 0x2D6A77AB, 0x3527ED4B, 0x821FD216, 0x095C6E2E,
138 0xDB92F2FB, 0x5EEA29CB, 0x145892F5, 0x91584F7F,
139 0x5483697B, 0x2667A8CC, 0x85196048, 0x8C4BACEA,
140 0x833860D4, 0x0D23E0F9, 0x6C387E8A, 0x0AE6D249,
141 0xB284600C, 0xD835731D, 0xDCB1C647, 0xAC4C56EA,
142 0x3EBD81B3, 0x230EABB0, 0x6438BC87, 0xF0B5B1FA,
143 0x8F5EA2B3, 0xFC184642, 0x0A036B7A, 0x4FB089BD,
144 0x649DA589, 0xA345415E, 0x5C038323, 0x3E5D3BB9,
145 0x43D79572, 0x7E6DD07C, 0x06DFDF1E, 0x6C6CC4EF,
146 0x7160A539, 0x73BFBE70, 0x83877605, 0x4523ECF1
147};
148
149static const u_int32_t cast_sbox3[256] = {
150 0x8DEFC240, 0x25FA5D9F, 0xEB903DBF, 0xE810C907,
151 0x47607FFF, 0x369FE44B, 0x8C1FC644, 0xAECECA90,
152 0xBEB1F9BF, 0xEEFBCAEA, 0xE8CF1950, 0x51DF07AE,
153 0x920E8806, 0xF0AD0548, 0xE13C8D83, 0x927010D5,
154 0x11107D9F, 0x07647DB9, 0xB2E3E4D4, 0x3D4F285E,
155 0xB9AFA820, 0xFADE82E0, 0xA067268B, 0x8272792E,
156 0x553FB2C0, 0x489AE22B, 0xD4EF9794, 0x125E3FBC,
157 0x21FFFCEE, 0x825B1BFD, 0x9255C5ED, 0x1257A240,
158 0x4E1A8302, 0xBAE07FFF, 0x528246E7, 0x8E57140E,
159 0x3373F7BF, 0x8C9F8188, 0xA6FC4EE8, 0xC982B5A5,
160 0xA8C01DB7, 0x579FC264, 0x67094F31, 0xF2BD3F5F,
161 0x40FFF7C1, 0x1FB78DFC, 0x8E6BD2C1, 0x437BE59B,
162 0x99B03DBF, 0xB5DBC64B, 0x638DC0E6, 0x55819D99,
163 0xA197C81C, 0x4A012D6E, 0xC5884A28, 0xCCC36F71,
164 0xB843C213, 0x6C0743F1, 0x8309893C, 0x0FEDDD5F,
165 0x2F7FE850, 0xD7C07F7E, 0x02507FBF, 0x5AFB9A04,
166 0xA747D2D0, 0x1651192E, 0xAF70BF3E, 0x58C31380,
167 0x5F98302E, 0x727CC3C4, 0x0A0FB402, 0x0F7FEF82,
168 0x8C96FDAD, 0x5D2C2AAE, 0x8EE99A49, 0x50DA88B8,
169 0x8427F4A0, 0x1EAC5790, 0x796FB449, 0x8252DC15,
170 0xEFBD7D9B, 0xA672597D, 0xADA840D8, 0x45F54504,
171 0xFA5D7403, 0xE83EC305, 0x4F91751A, 0x925669C2,
172 0x23EFE941, 0xA903F12E, 0x60270DF2, 0x0276E4B6,
173 0x94FD6574, 0x927985B2, 0x8276DBCB, 0x02778176,
174 0xF8AF918D, 0x4E48F79E, 0x8F616DDF, 0xE29D840E,
175 0x842F7D83, 0x340CE5C8, 0x96BBB682, 0x93B4B148,
176 0xEF303CAB, 0x984FAF28, 0x779FAF9B, 0x92DC560D,
177 0x224D1E20, 0x8437AA88, 0x7D29DC96, 0x2756D3DC,
178 0x8B907CEE, 0xB51FD240, 0xE7C07CE3, 0xE566B4A1,
179 0xC3E9615E, 0x3CF8209D, 0x6094D1E3, 0xCD9CA341,
180 0x5C76460E, 0x00EA983B, 0xD4D67881, 0xFD47572C,
181 0xF76CEDD9, 0xBDA8229C, 0x127DADAA, 0x438A074E,
182 0x1F97C090, 0x081BDB8A, 0x93A07EBE, 0xB938CA15,
183 0x97B03CFF, 0x3DC2C0F8, 0x8D1AB2EC, 0x64380E51,
184 0x68CC7BFB, 0xD90F2788, 0x12490181, 0x5DE5FFD4,
185 0xDD7EF86A, 0x76A2E214, 0xB9A40368, 0x925D958F,
186 0x4B39FFFA, 0xBA39AEE9, 0xA4FFD30B, 0xFAF7933B,
187 0x6D498623, 0x193CBCFA, 0x27627545, 0x825CF47A,
188 0x61BD8BA0, 0xD11E42D1, 0xCEAD04F4, 0x127EA392,
189 0x10428DB7, 0x8272A972, 0x9270C4A8, 0x127DE50B,
190 0x285BA1C8, 0x3C62F44F, 0x35C0EAA5, 0xE805D231,
191 0x428929FB, 0xB4FCDF82, 0x4FB66A53, 0x0E7DC15B,
192 0x1F081FAB, 0x108618AE, 0xFCFD086D, 0xF9FF2889,
193 0x694BCC11, 0x236A5CAE, 0x12DECA4D, 0x2C3F8CC5,
194 0xD2D02DFE, 0xF8EF5896, 0xE4CF52DA, 0x95155B67,
195 0x494A488C, 0xB9B6A80C, 0x5C8F82BC, 0x89D36B45,
196 0x3A609437, 0xEC00C9A9, 0x44715253, 0x0A874B49,
197 0xD773BC40, 0x7C34671C, 0x02717EF6, 0x4FEB5536,
198 0xA2D02FFF, 0xD2BF60C4, 0xD43F03C0, 0x50B4EF6D,
199 0x07478CD1, 0x006E1888, 0xA2E53F55, 0xB9E6D4BC,
200 0xA2048016, 0x97573833, 0xD7207D67, 0xDE0F8F3D,
201 0x72F87B33, 0xABCC4F33, 0x7688C55D, 0x7B00A6B0,
202 0x947B0001, 0x570075D2, 0xF9BB88F8, 0x8942019E,
203 0x4264A5FF, 0x856302E0, 0x72DBD92B, 0xEE971B69,
204 0x6EA22FDE, 0x5F08AE2B, 0xAF7A616D, 0xE5C98767,
205 0xCF1FEBD2, 0x61EFC8C2, 0xF1AC2571, 0xCC8239C2,
206 0x67214CB8, 0xB1E583D1, 0xB7DC3E62, 0x7F10BDCE,
207 0xF90A5C38, 0x0FF0443D, 0x606E6DC6, 0x60543A49,
208 0x5727C148, 0x2BE98A1D, 0x8AB41738, 0x20E1BE24,
209 0xAF96DA0F, 0x68458425, 0x99833BE5, 0x600D457D,
210 0x282F9350, 0x8334B362, 0xD91D1120, 0x2B6D8DA0,
211 0x642B1E31, 0x9C305A00, 0x52BCE688, 0x1B03588A,
212 0xF7BAEFD5, 0x4142ED9C, 0xA4315C11, 0x83323EC5,
213 0xDFEF4636, 0xA133C501, 0xE9D3531C, 0xEE353783
214};
215
216static const u_int32_t cast_sbox4[256] = {
217 0x9DB30420, 0x1FB6E9DE, 0xA7BE7BEF, 0xD273A298,
218 0x4A4F7BDB, 0x64AD8C57, 0x85510443, 0xFA020ED1,
219 0x7E287AFF, 0xE60FB663, 0x095F35A1, 0x79EBF120,
220 0xFD059D43, 0x6497B7B1, 0xF3641F63, 0x241E4ADF,
221 0x28147F5F, 0x4FA2B8CD, 0xC9430040, 0x0CC32220,
222 0xFDD30B30, 0xC0A5374F, 0x1D2D00D9, 0x24147B15,
223 0xEE4D111A, 0x0FCA5167, 0x71FF904C, 0x2D195FFE,
224 0x1A05645F, 0x0C13FEFE, 0x081B08CA, 0x05170121,
225 0x80530100, 0xE83E5EFE, 0xAC9AF4F8, 0x7FE72701,
226 0xD2B8EE5F, 0x06DF4261, 0xBB9E9B8A, 0x7293EA25,
227 0xCE84FFDF, 0xF5718801, 0x3DD64B04, 0xA26F263B,
228 0x7ED48400, 0x547EEBE6, 0x446D4CA0, 0x6CF3D6F5,
229 0x2649ABDF, 0xAEA0C7F5, 0x36338CC1, 0x503F7E93,
230 0xD3772061, 0x11B638E1, 0x72500E03, 0xF80EB2BB,
231 0xABE0502E, 0xEC8D77DE, 0x57971E81, 0xE14F6746,
232 0xC9335400, 0x6920318F, 0x081DBB99, 0xFFC304A5,
233 0x4D351805, 0x7F3D5CE3, 0xA6C866C6, 0x5D5BCCA9,
234 0xDAEC6FEA, 0x9F926F91, 0x9F46222F, 0x3991467D,
235 0xA5BF6D8E, 0x1143C44F, 0x43958302, 0xD0214EEB,
236 0x022083B8, 0x3FB6180C, 0x18F8931E, 0x281658E6,
237 0x26486E3E, 0x8BD78A70, 0x7477E4C1, 0xB506E07C,
238 0xF32D0A25, 0x79098B02, 0xE4EABB81, 0x28123B23,
239 0x69DEAD38, 0x1574CA16, 0xDF871B62, 0x211C40B7,
240 0xA51A9EF9, 0x0014377B, 0x041E8AC8, 0x09114003,
241 0xBD59E4D2, 0xE3D156D5, 0x4FE876D5, 0x2F91A340,
242 0x557BE8DE, 0x00EAE4A7, 0x0CE5C2EC, 0x4DB4BBA6,
243 0xE756BDFF, 0xDD3369AC, 0xEC17B035, 0x06572327,
244 0x99AFC8B0, 0x56C8C391, 0x6B65811C, 0x5E146119,
245 0x6E85CB75, 0xBE07C002, 0xC2325577, 0x893FF4EC,
246 0x5BBFC92D, 0xD0EC3B25, 0xB7801AB7, 0x8D6D3B24,
247 0x20C763EF, 0xC366A5FC, 0x9C382880, 0x0ACE3205,
248 0xAAC9548A, 0xECA1D7C7, 0x041AFA32, 0x1D16625A,
249 0x6701902C, 0x9B757A54, 0x31D477F7, 0x9126B031,
250 0x36CC6FDB, 0xC70B8B46, 0xD9E66A48, 0x56E55A79,
251 0x026A4CEB, 0x52437EFF, 0x2F8F76B4, 0x0DF980A5,
252 0x8674CDE3, 0xEDDA04EB, 0x17A9BE04, 0x2C18F4DF,
253 0xB7747F9D, 0xAB2AF7B4, 0xEFC34D20, 0x2E096B7C,
254 0x1741A254, 0xE5B6A035, 0x213D42F6, 0x2C1C7C26,
255 0x61C2F50F, 0x6552DAF9, 0xD2C231F8, 0x25130F69,
256 0xD8167FA2, 0x0418F2C8, 0x001A96A6, 0x0D1526AB,
257 0x63315C21, 0x5E0A72EC, 0x49BAFEFD, 0x187908D9,
258 0x8D0DBD86, 0x311170A7, 0x3E9B640C, 0xCC3E10D7,
259 0xD5CAD3B6, 0x0CAEC388, 0xF73001E1, 0x6C728AFF,
260 0x71EAE2A1, 0x1F9AF36E, 0xCFCBD12F, 0xC1DE8417,
261 0xAC07BE6B, 0xCB44A1D8, 0x8B9B0F56, 0x013988C3,
262 0xB1C52FCA, 0xB4BE31CD, 0xD8782806, 0x12A3A4E2,
263 0x6F7DE532, 0x58FD7EB6, 0xD01EE900, 0x24ADFFC2,
264 0xF4990FC5, 0x9711AAC5, 0x001D7B95, 0x82E5E7D2,
265 0x109873F6, 0x00613096, 0xC32D9521, 0xADA121FF,
266 0x29908415, 0x7FBB977F, 0xAF9EB3DB, 0x29C9ED2A,
267 0x5CE2A465, 0xA730F32C, 0xD0AA3FE8, 0x8A5CC091,
268 0xD49E2CE7, 0x0CE454A9, 0xD60ACD86, 0x015F1919,
269 0x77079103, 0xDEA03AF6, 0x78A8565E, 0xDEE356DF,
270 0x21F05CBE, 0x8B75E387, 0xB3C50651, 0xB8A5C3EF,
271 0xD8EEB6D2, 0xE523BE77, 0xC2154529, 0x2F69EFDF,
272 0xAFE67AFB, 0xF470C4B2, 0xF3E0EB5B, 0xD6CC9876,
273 0x39E4460C, 0x1FDA8538, 0x1987832F, 0xCA007367,
274 0xA99144F8, 0x296B299E, 0x492FC295, 0x9266BEAB,
275 0xB5676E69, 0x9BD3DDDA, 0xDF7E052F, 0xDB25701C,
276 0x1B5E51EE, 0xF65324E6, 0x6AFCE36C, 0x0316CC04,
277 0x8644213E, 0xB7DC59D0, 0x7965291F, 0xCCD6FD43,
278 0x41823979, 0x932BCDF6, 0xB657C34D, 0x4EDFD282,
279 0x7AE5290C, 0x3CB9536B, 0x851E20FE, 0x9833557E,
280 0x13ECF0B0, 0xD3FFB372, 0x3F85C5C1, 0x0AEF7ED2
281};
282
283static const u_int32_t cast_sbox5[256] = {
284 0x7EC90C04, 0x2C6E74B9, 0x9B0E66DF, 0xA6337911,
285 0xB86A7FFF, 0x1DD358F5, 0x44DD9D44, 0x1731167F,
286 0x08FBF1FA, 0xE7F511CC, 0xD2051B00, 0x735ABA00,
287 0x2AB722D8, 0x386381CB, 0xACF6243A, 0x69BEFD7A,
288 0xE6A2E77F, 0xF0C720CD, 0xC4494816, 0xCCF5C180,
289 0x38851640, 0x15B0A848, 0xE68B18CB, 0x4CAADEFF,
290 0x5F480A01, 0x0412B2AA, 0x259814FC, 0x41D0EFE2,
291 0x4E40B48D, 0x248EB6FB, 0x8DBA1CFE, 0x41A99B02,
292 0x1A550A04, 0xBA8F65CB, 0x7251F4E7, 0x95A51725,
293 0xC106ECD7, 0x97A5980A, 0xC539B9AA, 0x4D79FE6A,
294 0xF2F3F763, 0x68AF8040, 0xED0C9E56, 0x11B4958B,
295 0xE1EB5A88, 0x8709E6B0, 0xD7E07156, 0x4E29FEA7,
296 0x6366E52D, 0x02D1C000, 0xC4AC8E05, 0x9377F571,
297 0x0C05372A, 0x578535F2, 0x2261BE02, 0xD642A0C9,
298 0xDF13A280, 0x74B55BD2, 0x682199C0, 0xD421E5EC,
299 0x53FB3CE8, 0xC8ADEDB3, 0x28A87FC9, 0x3D959981,
300 0x5C1FF900, 0xFE38D399, 0x0C4EFF0B, 0x062407EA,
301 0xAA2F4FB1, 0x4FB96976, 0x90C79505, 0xB0A8A774,
302 0xEF55A1FF, 0xE59CA2C2, 0xA6B62D27, 0xE66A4263,
303 0xDF65001F, 0x0EC50966, 0xDFDD55BC, 0x29DE0655,
304 0x911E739A, 0x17AF8975, 0x32C7911C, 0x89F89468,
305 0x0D01E980, 0x524755F4, 0x03B63CC9, 0x0CC844B2,
306 0xBCF3F0AA, 0x87AC36E9, 0xE53A7426, 0x01B3D82B,
307 0x1A9E7449, 0x64EE2D7E, 0xCDDBB1DA, 0x01C94910,
308 0xB868BF80, 0x0D26F3FD, 0x9342EDE7, 0x04A5C284,
309 0x636737B6, 0x50F5B616, 0xF24766E3, 0x8ECA36C1,
310 0x136E05DB, 0xFEF18391, 0xFB887A37, 0xD6E7F7D4,
311 0xC7FB7DC9, 0x3063FCDF, 0xB6F589DE, 0xEC2941DA,
312 0x26E46695, 0xB7566419, 0xF654EFC5, 0xD08D58B7,
313 0x48925401, 0xC1BACB7F, 0xE5FF550F, 0xB6083049,
314 0x5BB5D0E8, 0x87D72E5A, 0xAB6A6EE1, 0x223A66CE,
315 0xC62BF3CD, 0x9E0885F9, 0x68CB3E47, 0x086C010F,
316 0xA21DE820, 0xD18B69DE, 0xF3F65777, 0xFA02C3F6,
317 0x407EDAC3, 0xCBB3D550, 0x1793084D, 0xB0D70EBA,
318 0x0AB378D5, 0xD951FB0C, 0xDED7DA56, 0x4124BBE4,
319 0x94CA0B56, 0x0F5755D1, 0xE0E1E56E, 0x6184B5BE,
320 0x580A249F, 0x94F74BC0, 0xE327888E, 0x9F7B5561,
321 0xC3DC0280, 0x05687715, 0x646C6BD7, 0x44904DB3,
322 0x66B4F0A3, 0xC0F1648A, 0x697ED5AF, 0x49E92FF6,
323 0x309E374F, 0x2CB6356A, 0x85808573, 0x4991F840,
324 0x76F0AE02, 0x083BE84D, 0x28421C9A, 0x44489406,
325 0x736E4CB8, 0xC1092910, 0x8BC95FC6, 0x7D869CF4,
326 0x134F616F, 0x2E77118D, 0xB31B2BE1, 0xAA90B472,
327 0x3CA5D717, 0x7D161BBA, 0x9CAD9010, 0xAF462BA2,
328 0x9FE459D2, 0x45D34559, 0xD9F2DA13, 0xDBC65487,
329 0xF3E4F94E, 0x176D486F, 0x097C13EA, 0x631DA5C7,
330 0x445F7382, 0x175683F4, 0xCDC66A97, 0x70BE0288,
331 0xB3CDCF72, 0x6E5DD2F3, 0x20936079, 0x459B80A5,
332 0xBE60E2DB, 0xA9C23101, 0xEBA5315C, 0x224E42F2,
333 0x1C5C1572, 0xF6721B2C, 0x1AD2FFF3, 0x8C25404E,
334 0x324ED72F, 0x4067B7FD, 0x0523138E, 0x5CA3BC78,
335 0xDC0FD66E, 0x75922283, 0x784D6B17, 0x58EBB16E,
336 0x44094F85, 0x3F481D87, 0xFCFEAE7B, 0x77B5FF76,
337 0x8C2302BF, 0xAAF47556, 0x5F46B02A, 0x2B092801,
338 0x3D38F5F7, 0x0CA81F36, 0x52AF4A8A, 0x66D5E7C0,
339 0xDF3B0874, 0x95055110, 0x1B5AD7A8, 0xF61ED5AD,
340 0x6CF6E479, 0x20758184, 0xD0CEFA65, 0x88F7BE58,
341 0x4A046826, 0x0FF6F8F3, 0xA09C7F70, 0x5346ABA0,
342 0x5CE96C28, 0xE176EDA3, 0x6BAC307F, 0x376829D2,
343 0x85360FA9, 0x17E3FE2A, 0x24B79767, 0xF5A96B20,
344 0xD6CD2595, 0x68FF1EBF, 0x7555442C, 0xF19F06BE,
345 0xF9E0659A, 0xEEB9491D, 0x34010718, 0xBB30CAB8,
346 0xE822FE15, 0x88570983, 0x750E6249, 0xDA627E55,
347 0x5E76FFA8, 0xB1534546, 0x6D47DE08, 0xEFE9E7D4
348};
349
350static const u_int32_t cast_sbox6[256] = {
351 0xF6FA8F9D, 0x2CAC6CE1, 0x4CA34867, 0xE2337F7C,
352 0x95DB08E7, 0x016843B4, 0xECED5CBC, 0x325553AC,
353 0xBF9F0960, 0xDFA1E2ED, 0x83F0579D, 0x63ED86B9,
354 0x1AB6A6B8, 0xDE5EBE39, 0xF38FF732, 0x8989B138,
355 0x33F14961, 0xC01937BD, 0xF506C6DA, 0xE4625E7E,
356 0xA308EA99, 0x4E23E33C, 0x79CBD7CC, 0x48A14367,
357 0xA3149619, 0xFEC94BD5, 0xA114174A, 0xEAA01866,
358 0xA084DB2D, 0x09A8486F, 0xA888614A, 0x2900AF98,
359 0x01665991, 0xE1992863, 0xC8F30C60, 0x2E78EF3C,
360 0xD0D51932, 0xCF0FEC14, 0xF7CA07D2, 0xD0A82072,
361 0xFD41197E, 0x9305A6B0, 0xE86BE3DA, 0x74BED3CD,
362 0x372DA53C, 0x4C7F4448, 0xDAB5D440, 0x6DBA0EC3,
363 0x083919A7, 0x9FBAEED9, 0x49DBCFB0, 0x4E670C53,
364 0x5C3D9C01, 0x64BDB941, 0x2C0E636A, 0xBA7DD9CD,
365 0xEA6F7388, 0xE70BC762, 0x35F29ADB, 0x5C4CDD8D,
366 0xF0D48D8C, 0xB88153E2, 0x08A19866, 0x1AE2EAC8,
367 0x284CAF89, 0xAA928223, 0x9334BE53, 0x3B3A21BF,
368 0x16434BE3, 0x9AEA3906, 0xEFE8C36E, 0xF890CDD9,
369 0x80226DAE, 0xC340A4A3, 0xDF7E9C09, 0xA694A807,
370 0x5B7C5ECC, 0x221DB3A6, 0x9A69A02F, 0x68818A54,
371 0xCEB2296F, 0x53C0843A, 0xFE893655, 0x25BFE68A,
372 0xB4628ABC, 0xCF222EBF, 0x25AC6F48, 0xA9A99387,
373 0x53BDDB65, 0xE76FFBE7, 0xE967FD78, 0x0BA93563,
374 0x8E342BC1, 0xE8A11BE9, 0x4980740D, 0xC8087DFC,
375 0x8DE4BF99, 0xA11101A0, 0x7FD37975, 0xDA5A26C0,
376 0xE81F994F, 0x9528CD89, 0xFD339FED, 0xB87834BF,
377 0x5F04456D, 0x22258698, 0xC9C4C83B, 0x2DC156BE,
378 0x4F628DAA, 0x57F55EC5, 0xE2220ABE, 0xD2916EBF,
379 0x4EC75B95, 0x24F2C3C0, 0x42D15D99, 0xCD0D7FA0,
380 0x7B6E27FF, 0xA8DC8AF0, 0x7345C106, 0xF41E232F,
381 0x35162386, 0xE6EA8926, 0x3333B094, 0x157EC6F2,
382 0x372B74AF, 0x692573E4, 0xE9A9D848, 0xF3160289,
383 0x3A62EF1D, 0xA787E238, 0xF3A5F676, 0x74364853,
384 0x20951063, 0x4576698D, 0xB6FAD407, 0x592AF950,
385 0x36F73523, 0x4CFB6E87, 0x7DA4CEC0, 0x6C152DAA,
386 0xCB0396A8, 0xC50DFE5D, 0xFCD707AB, 0x0921C42F,
387 0x89DFF0BB, 0x5FE2BE78, 0x448F4F33, 0x754613C9,
388 0x2B05D08D, 0x48B9D585, 0xDC049441, 0xC8098F9B,
389 0x7DEDE786, 0xC39A3373, 0x42410005, 0x6A091751,
390 0x0EF3C8A6, 0x890072D6, 0x28207682, 0xA9A9F7BE,
391 0xBF32679D, 0xD45B5B75, 0xB353FD00, 0xCBB0E358,
392 0x830F220A, 0x1F8FB214, 0xD372CF08, 0xCC3C4A13,
393 0x8CF63166, 0x061C87BE, 0x88C98F88, 0x6062E397,
394 0x47CF8E7A, 0xB6C85283, 0x3CC2ACFB, 0x3FC06976,
395 0x4E8F0252, 0x64D8314D, 0xDA3870E3, 0x1E665459,
396 0xC10908F0, 0x513021A5, 0x6C5B68B7, 0x822F8AA0,
397 0x3007CD3E, 0x74719EEF, 0xDC872681, 0x073340D4,
398 0x7E432FD9, 0x0C5EC241, 0x8809286C, 0xF592D891,
399 0x08A930F6, 0x957EF305, 0xB7FBFFBD, 0xC266E96F,
400 0x6FE4AC98, 0xB173ECC0, 0xBC60B42A, 0x953498DA,
401 0xFBA1AE12, 0x2D4BD736, 0x0F25FAAB, 0xA4F3FCEB,
402 0xE2969123, 0x257F0C3D, 0x9348AF49, 0x361400BC,
403 0xE8816F4A, 0x3814F200, 0xA3F94043, 0x9C7A54C2,
404 0xBC704F57, 0xDA41E7F9, 0xC25AD33A, 0x54F4A084,
405 0xB17F5505, 0x59357CBE, 0xEDBD15C8, 0x7F97C5AB,
406 0xBA5AC7B5, 0xB6F6DEAF, 0x3A479C3A, 0x5302DA25,
407 0x653D7E6A, 0x54268D49, 0x51A477EA, 0x5017D55B,
408 0xD7D25D88, 0x44136C76, 0x0404A8C8, 0xB8E5A121,
409 0xB81A928A, 0x60ED5869, 0x97C55B96, 0xEAEC991B,
410 0x29935913, 0x01FDB7F1, 0x088E8DFA, 0x9AB6F6F5,
411 0x3B4CBF9F, 0x4A5DE3AB, 0xE6051D35, 0xA0E1D855,
412 0xD36B4CF1, 0xF544EDEB, 0xB0E93524, 0xBEBB8FBD,
413 0xA2D762CF, 0x49C92F54, 0x38B5F331, 0x7128A454,
414 0x48392905, 0xA65B1DB8, 0x851C97BD, 0xD675CF2F
415};
416
417static const u_int32_t cast_sbox7[256] = {
418 0x85E04019, 0x332BF567, 0x662DBFFF, 0xCFC65693,
419 0x2A8D7F6F, 0xAB9BC912, 0xDE6008A1, 0x2028DA1F,
420 0x0227BCE7, 0x4D642916, 0x18FAC300, 0x50F18B82,
421 0x2CB2CB11, 0xB232E75C, 0x4B3695F2, 0xB28707DE,
422 0xA05FBCF6, 0xCD4181E9, 0xE150210C, 0xE24EF1BD,
423 0xB168C381, 0xFDE4E789, 0x5C79B0D8, 0x1E8BFD43,
424 0x4D495001, 0x38BE4341, 0x913CEE1D, 0x92A79C3F,
425 0x089766BE, 0xBAEEADF4, 0x1286BECF, 0xB6EACB19,
426 0x2660C200, 0x7565BDE4, 0x64241F7A, 0x8248DCA9,
427 0xC3B3AD66, 0x28136086, 0x0BD8DFA8, 0x356D1CF2,
428 0x107789BE, 0xB3B2E9CE, 0x0502AA8F, 0x0BC0351E,
429 0x166BF52A, 0xEB12FF82, 0xE3486911, 0xD34D7516,
430 0x4E7B3AFF, 0x5F43671B, 0x9CF6E037, 0x4981AC83,
431 0x334266CE, 0x8C9341B7, 0xD0D854C0, 0xCB3A6C88,
432 0x47BC2829, 0x4725BA37, 0xA66AD22B, 0x7AD61F1E,
433 0x0C5CBAFA, 0x4437F107, 0xB6E79962, 0x42D2D816,
434 0x0A961288, 0xE1A5C06E, 0x13749E67, 0x72FC081A,
435 0xB1D139F7, 0xF9583745, 0xCF19DF58, 0xBEC3F756,
436 0xC06EBA30, 0x07211B24, 0x45C28829, 0xC95E317F,
437 0xBC8EC511, 0x38BC46E9, 0xC6E6FA14, 0xBAE8584A,
438 0xAD4EBC46, 0x468F508B, 0x7829435F, 0xF124183B,
439 0x821DBA9F, 0xAFF60FF4, 0xEA2C4E6D, 0x16E39264,
440 0x92544A8B, 0x009B4FC3, 0xABA68CED, 0x9AC96F78,
441 0x06A5B79A, 0xB2856E6E, 0x1AEC3CA9, 0xBE838688,
442 0x0E0804E9, 0x55F1BE56, 0xE7E5363B, 0xB3A1F25D,
443 0xF7DEBB85, 0x61FE033C, 0x16746233, 0x3C034C28,
444 0xDA6D0C74, 0x79AAC56C, 0x3CE4E1AD, 0x51F0C802,
445 0x98F8F35A, 0x1626A49F, 0xEED82B29, 0x1D382FE3,
446 0x0C4FB99A, 0xBB325778, 0x3EC6D97B, 0x6E77A6A9,
447 0xCB658B5C, 0xD45230C7, 0x2BD1408B, 0x60C03EB7,
448 0xB9068D78, 0xA33754F4, 0xF430C87D, 0xC8A71302,
449 0xB96D8C32, 0xEBD4E7BE, 0xBE8B9D2D, 0x7979FB06,
450 0xE7225308, 0x8B75CF77, 0x11EF8DA4, 0xE083C858,
451 0x8D6B786F, 0x5A6317A6, 0xFA5CF7A0, 0x5DDA0033,
452 0xF28EBFB0, 0xF5B9C310, 0xA0EAC280, 0x08B9767A,
453 0xA3D9D2B0, 0x79D34217, 0x021A718D, 0x9AC6336A,
454 0x2711FD60, 0x438050E3, 0x069908A8, 0x3D7FEDC4,
455 0x826D2BEF, 0x4EEB8476, 0x488DCF25, 0x36C9D566,
456 0x28E74E41, 0xC2610ACA, 0x3D49A9CF, 0xBAE3B9DF,
457 0xB65F8DE6, 0x92AEAF64, 0x3AC7D5E6, 0x9EA80509,
458 0xF22B017D, 0xA4173F70, 0xDD1E16C3, 0x15E0D7F9,
459 0x50B1B887, 0x2B9F4FD5, 0x625ABA82, 0x6A017962,
460 0x2EC01B9C, 0x15488AA9, 0xD716E740, 0x40055A2C,
461 0x93D29A22, 0xE32DBF9A, 0x058745B9, 0x3453DC1E,
462 0xD699296E, 0x496CFF6F, 0x1C9F4986, 0xDFE2ED07,
463 0xB87242D1, 0x19DE7EAE, 0x053E561A, 0x15AD6F8C,
464 0x66626C1C, 0x7154C24C, 0xEA082B2A, 0x93EB2939,
465 0x17DCB0F0, 0x58D4F2AE, 0x9EA294FB, 0x52CF564C,
466 0x9883FE66, 0x2EC40581, 0x763953C3, 0x01D6692E,
467 0xD3A0C108, 0xA1E7160E, 0xE4F2DFA6, 0x693ED285,
468 0x74904698, 0x4C2B0EDD, 0x4F757656, 0x5D393378,
469 0xA132234F, 0x3D321C5D, 0xC3F5E194, 0x4B269301,
470 0xC79F022F, 0x3C997E7E, 0x5E4F9504, 0x3FFAFBBD,
471 0x76F7AD0E, 0x296693F4, 0x3D1FCE6F, 0xC61E45BE,
472 0xD3B5AB34, 0xF72BF9B7, 0x1B0434C0, 0x4E72B567,
473 0x5592A33D, 0xB5229301, 0xCFD2A87F, 0x60AEB767,
474 0x1814386B, 0x30BCC33D, 0x38A0C07D, 0xFD1606F2,
475 0xC363519B, 0x589DD390, 0x5479F8E6, 0x1CB8D647,
476 0x97FD61A9, 0xEA7759F4, 0x2D57539D, 0x569A58CF,
477 0xE84E63AD, 0x462E1B78, 0x6580F87E, 0xF3817914,
478 0x91DA55F4, 0x40A230F3, 0xD1988F35, 0xB6E318D2,
479 0x3FFA50BC, 0x3D40F021, 0xC3C0BDAE, 0x4958C24C,
480 0x518F36B2, 0x84B1D370, 0x0FEDCE83, 0x878DDADA,
481 0xF2A279C7, 0x94E01BE8, 0x90716F4B, 0x954B8AA3
482};
483
484static const u_int32_t cast_sbox8[256] = {
485 0xE216300D, 0xBBDDFFFC, 0xA7EBDABD, 0x35648095,
486 0x7789F8B7, 0xE6C1121B, 0x0E241600, 0x052CE8B5,
487 0x11A9CFB0, 0xE5952F11, 0xECE7990A, 0x9386D174,
488 0x2A42931C, 0x76E38111, 0xB12DEF3A, 0x37DDDDFC,
489 0xDE9ADEB1, 0x0A0CC32C, 0xBE197029, 0x84A00940,
490 0xBB243A0F, 0xB4D137CF, 0xB44E79F0, 0x049EEDFD,
491 0x0B15A15D, 0x480D3168, 0x8BBBDE5A, 0x669DED42,
492 0xC7ECE831, 0x3F8F95E7, 0x72DF191B, 0x7580330D,
493 0x94074251, 0x5C7DCDFA, 0xABBE6D63, 0xAA402164,
494 0xB301D40A, 0x02E7D1CA, 0x53571DAE, 0x7A3182A2,
495 0x12A8DDEC, 0xFDAA335D, 0x176F43E8, 0x71FB46D4,
496 0x38129022, 0xCE949AD4, 0xB84769AD, 0x965BD862,
497 0x82F3D055, 0x66FB9767, 0x15B80B4E, 0x1D5B47A0,
498 0x4CFDE06F, 0xC28EC4B8, 0x57E8726E, 0x647A78FC,
499 0x99865D44, 0x608BD593, 0x6C200E03, 0x39DC5FF6,
500 0x5D0B00A3, 0xAE63AFF2, 0x7E8BD632, 0x70108C0C,
501 0xBBD35049, 0x2998DF04, 0x980CF42A, 0x9B6DF491,
502 0x9E7EDD53, 0x06918548, 0x58CB7E07, 0x3B74EF2E,
503 0x522FFFB1, 0xD24708CC, 0x1C7E27CD, 0xA4EB215B,
504 0x3CF1D2E2, 0x19B47A38, 0x424F7618, 0x35856039,
505 0x9D17DEE7, 0x27EB35E6, 0xC9AFF67B, 0x36BAF5B8,
506 0x09C467CD, 0xC18910B1, 0xE11DBF7B, 0x06CD1AF8,
507 0x7170C608, 0x2D5E3354, 0xD4DE495A, 0x64C6D006,
508 0xBCC0C62C, 0x3DD00DB3, 0x708F8F34, 0x77D51B42,
509 0x264F620F, 0x24B8D2BF, 0x15C1B79E, 0x46A52564,
510 0xF8D7E54E, 0x3E378160, 0x7895CDA5, 0x859C15A5,
511 0xE6459788, 0xC37BC75F, 0xDB07BA0C, 0x0676A3AB,
512 0x7F229B1E, 0x31842E7B, 0x24259FD7, 0xF8BEF472,
513 0x835FFCB8, 0x6DF4C1F2, 0x96F5B195, 0xFD0AF0FC,
514 0xB0FE134C, 0xE2506D3D, 0x4F9B12EA, 0xF215F225,
515 0xA223736F, 0x9FB4C428, 0x25D04979, 0x34C713F8,
516 0xC4618187, 0xEA7A6E98, 0x7CD16EFC, 0x1436876C,
517 0xF1544107, 0xBEDEEE14, 0x56E9AF27, 0xA04AA441,
518 0x3CF7C899, 0x92ECBAE6, 0xDD67016D, 0x151682EB,
519 0xA842EEDF, 0xFDBA60B4, 0xF1907B75, 0x20E3030F,
520 0x24D8C29E, 0xE139673B, 0xEFA63FB8, 0x71873054,
521 0xB6F2CF3B, 0x9F326442, 0xCB15A4CC, 0xB01A4504,
522 0xF1E47D8D, 0x844A1BE5, 0xBAE7DFDC, 0x42CBDA70,
523 0xCD7DAE0A, 0x57E85B7A, 0xD53F5AF6, 0x20CF4D8C,
524 0xCEA4D428, 0x79D130A4, 0x3486EBFB, 0x33D3CDDC,
525 0x77853B53, 0x37EFFCB5, 0xC5068778, 0xE580B3E6,
526 0x4E68B8F4, 0xC5C8B37E, 0x0D809EA2, 0x398FEB7C,
527 0x132A4F94, 0x43B7950E, 0x2FEE7D1C, 0x223613BD,
528 0xDD06CAA2, 0x37DF932B, 0xC4248289, 0xACF3EBC3,
529 0x5715F6B7, 0xEF3478DD, 0xF267616F, 0xC148CBE4,
530 0x9052815E, 0x5E410FAB, 0xB48A2465, 0x2EDA7FA4,
531 0xE87B40E4, 0xE98EA084, 0x5889E9E1, 0xEFD390FC,
532 0xDD07D35B, 0xDB485694, 0x38D7E5B2, 0x57720101,
533 0x730EDEBC, 0x5B643113, 0x94917E4F, 0x503C2FBA,
534 0x646F1282, 0x7523D24A, 0xE0779695, 0xF9C17A8F,
535 0x7A5B2121, 0xD187B896, 0x29263A4D, 0xBA510CDF,
536 0x81F47C9F, 0xAD1163ED, 0xEA7B5965, 0x1A00726E,
537 0x11403092, 0x00DA6D77, 0x4A0CDD61, 0xAD1F4603,
538 0x605BDFB0, 0x9EEDC364, 0x22EBE6A8, 0xCEE7D28A,
539 0xA0E736A0, 0x5564A6B9, 0x10853209, 0xC7EB8F37,
540 0x2DE705CA, 0x8951570F, 0xDF09822B, 0xBD691A6C,
541 0xAA12E4F2, 0x87451C0F, 0xE0F6A27A, 0x3ADA4819,
542 0x4CF1764F, 0x0D771C2B, 0x67CDB156, 0x350D8384,
543 0x5938FA0F, 0x42399EF3, 0x36997B07, 0x0E84093D,
544 0x4AA93E61, 0x8360D87B, 0x1FA98B0C, 0x1149382C,
545 0xE97625A5, 0x0614D1B7, 0x0E25244B, 0x0C768347,
546 0x589E8D82, 0x0D2059D1, 0xA466BB1E, 0xF8DA0A82,
547 0x04F19130, 0xBA6E4EC0, 0x99265164, 0x1EE7230D,
548 0x50B2AD80, 0xEAEE6801, 0x8DB2A283, 0xEA8BF59E
549};
550
551/* Macros to access 8-bit bytes out of a 32-bit word */
552#define U8a(x) ( (u_int8_t) (x>>24) )
553#define U8b(x) ( (u_int8_t) ((x>>16)&255) )
554#define U8c(x) ( (u_int8_t) ((x>>8)&255) )
555#define U8d(x) ( (u_int8_t) ((x)&255) )
556
557/* Circular left shift */
558#define ROL(x, n) ( ((x)<<(n)) | ((x)>>(32-(n))) )
559
560/* CAST-128 uses three different round functions */
561#define F1(l, r, i) \
562 t = ROL(key->xkey[i] + r, key->xkey[i+16]); \
563 l ^= ((cast_sbox1[U8a(t)] ^ cast_sbox2[U8b(t)]) - \
564 cast_sbox3[U8c(t)]) + cast_sbox4[U8d(t)];
565#define F2(l, r, i) \
566 t = ROL(key->xkey[i] ^ r, key->xkey[i+16]); \
567 l ^= ((cast_sbox1[U8a(t)] - cast_sbox2[U8b(t)]) + \
568 cast_sbox3[U8c(t)]) ^ cast_sbox4[U8d(t)];
569#define F3(l, r, i) \
570 t = ROL(key->xkey[i] - r, key->xkey[i+16]); \
571 l ^= ((cast_sbox1[U8a(t)] + cast_sbox2[U8b(t)]) ^ \
572 cast_sbox3[U8c(t)]) - cast_sbox4[U8d(t)];
573
574
575/***** Encryption Function *****/
576
577void cast_encrypt(cast_key* key, u_int8_t* inblock, u_int8_t* outblock)
578{
579u_int32_t t, l, r;
580
581 /* Get inblock into l,r */
582 l = ((u_int32_t)inblock[0] << 24) | ((u_int32_t)inblock[1] << 16) |
583 ((u_int32_t)inblock[2] << 8) | (u_int32_t)inblock[3];
584 r = ((u_int32_t)inblock[4] << 24) | ((u_int32_t)inblock[5] << 16) |
585 ((u_int32_t)inblock[6] << 8) | (u_int32_t)inblock[7];
586 /* Do the work */
587 F1(l, r, 0);
588 F2(r, l, 1);
589 F3(l, r, 2);
590 F1(r, l, 3);
591 F2(l, r, 4);
592 F3(r, l, 5);
593 F1(l, r, 6);
594 F2(r, l, 7);
595 F3(l, r, 8);
596 F1(r, l, 9);
597 F2(l, r, 10);
598 F3(r, l, 11);
599 /* Only do full 16 rounds if key length > 80 bits */
600 if (key->rounds > 12) {
601 F1(l, r, 12);
602 F2(r, l, 13);
603 F3(l, r, 14);
604 F1(r, l, 15);
605 }
606 /* Put l,r into outblock */
607 outblock[0] = U8a(r);
608 outblock[1] = U8b(r);
609 outblock[2] = U8c(r);
610 outblock[3] = U8d(r);
611 outblock[4] = U8a(l);
612 outblock[5] = U8b(l);
613 outblock[6] = U8c(l);
614 outblock[7] = U8d(l);
615 /* Wipe clean */
616 t = l = r = 0;
617}
618
619
620/***** Decryption Function *****/
621
622void cast_decrypt(cast_key* key, u_int8_t* inblock, u_int8_t* outblock)
623{
624u_int32_t t, l, r;
625
626 /* Get inblock into l,r */
627 r = ((u_int32_t)inblock[0] << 24) | ((u_int32_t)inblock[1] << 16) |
628 ((u_int32_t)inblock[2] << 8) | (u_int32_t)inblock[3];
629 l = ((u_int32_t)inblock[4] << 24) | ((u_int32_t)inblock[5] << 16) |
630 ((u_int32_t)inblock[6] << 8) | (u_int32_t)inblock[7];
631 /* Do the work */
632 /* Only do full 16 rounds if key length > 80 bits */
633 if (key->rounds > 12) {
634 F1(r, l, 15);
635 F3(l, r, 14);
636 F2(r, l, 13);
637 F1(l, r, 12);
638 }
639 F3(r, l, 11);
640 F2(l, r, 10);
641 F1(r, l, 9);
642 F3(l, r, 8);
643 F2(r, l, 7);
644 F1(l, r, 6);
645 F3(r, l, 5);
646 F2(l, r, 4);
647 F1(r, l, 3);
648 F3(l, r, 2);
649 F2(r, l, 1);
650 F1(l, r, 0);
651 /* Put l,r into outblock */
652 outblock[0] = U8a(l);
653 outblock[1] = U8b(l);
654 outblock[2] = U8c(l);
655 outblock[3] = U8d(l);
656 outblock[4] = U8a(r);
657 outblock[5] = U8b(r);
658 outblock[6] = U8c(r);
659 outblock[7] = U8d(r);
660 /* Wipe clean */
661 t = l = r = 0;
662}
663
664
665/***** Key Schedual *****/
666
667void cast_setkey(cast_key* key, u_int8_t* rawkey, int keybytes)
668{
669u_int32_t t[4], z[4], x[4];
670int i;
671
672 /* Set number of rounds to 12 or 16, depending on key length */
673 key->rounds = (keybytes <= 10 ? 12 : 16);
674
675 /* Copy key to workspace x */
676 for (i = 0; i < 4; i++) {
677 x[i] = 0;
678 if ((i*4+0) < keybytes) x[i] = (u_int32_t)rawkey[i*4+0] << 24;
679 if ((i*4+1) < keybytes) x[i] |= (u_int32_t)rawkey[i*4+1] << 16;
680 if ((i*4+2) < keybytes) x[i] |= (u_int32_t)rawkey[i*4+2] << 8;
681 if ((i*4+3) < keybytes) x[i] |= (u_int32_t)rawkey[i*4+3];
682 }
683 /* Generate 32 subkeys, four at a time */
684 for (i = 0; i < 32; i+=4) {
685 switch (i & 4) {
686 case 0:
687 t[0] = z[0] = x[0] ^ cast_sbox5[U8b(x[3])] ^
688 cast_sbox6[U8d(x[3])] ^ cast_sbox7[U8a(x[3])] ^
689 cast_sbox8[U8c(x[3])] ^ cast_sbox7[U8a(x[2])];
690 t[1] = z[1] = x[2] ^ cast_sbox5[U8a(z[0])] ^
691 cast_sbox6[U8c(z[0])] ^ cast_sbox7[U8b(z[0])] ^
692 cast_sbox8[U8d(z[0])] ^ cast_sbox8[U8c(x[2])];
693 t[2] = z[2] = x[3] ^ cast_sbox5[U8d(z[1])] ^
694 cast_sbox6[U8c(z[1])] ^ cast_sbox7[U8b(z[1])] ^
695 cast_sbox8[U8a(z[1])] ^ cast_sbox5[U8b(x[2])];
696 t[3] = z[3] = x[1] ^ cast_sbox5[U8c(z[2])] ^
697 cast_sbox6[U8b(z[2])] ^ cast_sbox7[U8d(z[2])] ^
698 cast_sbox8[U8a(z[2])] ^ cast_sbox6[U8d(x[2])];
699 break;
700 case 4:
701 t[0] = x[0] = z[2] ^ cast_sbox5[U8b(z[1])] ^
702 cast_sbox6[U8d(z[1])] ^ cast_sbox7[U8a(z[1])] ^
703 cast_sbox8[U8c(z[1])] ^ cast_sbox7[U8a(z[0])];
704 t[1] = x[1] = z[0] ^ cast_sbox5[U8a(x[0])] ^
705 cast_sbox6[U8c(x[0])] ^ cast_sbox7[U8b(x[0])] ^
706 cast_sbox8[U8d(x[0])] ^ cast_sbox8[U8c(z[0])];
707 t[2] = x[2] = z[1] ^ cast_sbox5[U8d(x[1])] ^
708 cast_sbox6[U8c(x[1])] ^ cast_sbox7[U8b(x[1])] ^
709 cast_sbox8[U8a(x[1])] ^ cast_sbox5[U8b(z[0])];
710 t[3] = x[3] = z[3] ^ cast_sbox5[U8c(x[2])] ^
711 cast_sbox6[U8b(x[2])] ^ cast_sbox7[U8d(x[2])] ^
712 cast_sbox8[U8a(x[2])] ^ cast_sbox6[U8d(z[0])];
713 break;
714 }
715 switch (i & 12) {
716 case 0:
717 case 12:
718 key->xkey[i+0] = cast_sbox5[U8a(t[2])] ^ cast_sbox6[U8b(t[2])] ^
719 cast_sbox7[U8d(t[1])] ^ cast_sbox8[U8c(t[1])];
720 key->xkey[i+1] = cast_sbox5[U8c(t[2])] ^ cast_sbox6[U8d(t[2])] ^
721 cast_sbox7[U8b(t[1])] ^ cast_sbox8[U8a(t[1])];
722 key->xkey[i+2] = cast_sbox5[U8a(t[3])] ^ cast_sbox6[U8b(t[3])] ^
723 cast_sbox7[U8d(t[0])] ^ cast_sbox8[U8c(t[0])];
724 key->xkey[i+3] = cast_sbox5[U8c(t[3])] ^ cast_sbox6[U8d(t[3])] ^
725 cast_sbox7[U8b(t[0])] ^ cast_sbox8[U8a(t[0])];
726 break;
727 case 4:
728 case 8:
729 key->xkey[i+0] = cast_sbox5[U8d(t[0])] ^ cast_sbox6[U8c(t[0])] ^
730 cast_sbox7[U8a(t[3])] ^ cast_sbox8[U8b(t[3])];
731 key->xkey[i+1] = cast_sbox5[U8b(t[0])] ^ cast_sbox6[U8a(t[0])] ^
732 cast_sbox7[U8c(t[3])] ^ cast_sbox8[U8d(t[3])];
733 key->xkey[i+2] = cast_sbox5[U8d(t[1])] ^ cast_sbox6[U8c(t[1])] ^
734 cast_sbox7[U8a(t[2])] ^ cast_sbox8[U8b(t[2])];
735 key->xkey[i+3] = cast_sbox5[U8b(t[1])] ^ cast_sbox6[U8a(t[1])] ^
736 cast_sbox7[U8c(t[2])] ^ cast_sbox8[U8d(t[2])];
737 break;
738 }
739 switch (i & 12) {
740 case 0:
741 key->xkey[i+0] ^= cast_sbox5[U8c(z[0])];
742 key->xkey[i+1] ^= cast_sbox6[U8c(z[1])];
743 key->xkey[i+2] ^= cast_sbox7[U8b(z[2])];
744 key->xkey[i+3] ^= cast_sbox8[U8a(z[3])];
745 break;
746 case 4:
747 key->xkey[i+0] ^= cast_sbox5[U8a(x[2])];
748 key->xkey[i+1] ^= cast_sbox6[U8b(x[3])];
749 key->xkey[i+2] ^= cast_sbox7[U8d(x[0])];
750 key->xkey[i+3] ^= cast_sbox8[U8d(x[1])];
751 break;
752 case 8:
753 key->xkey[i+0] ^= cast_sbox5[U8b(z[2])];
754 key->xkey[i+1] ^= cast_sbox6[U8a(z[3])];
755 key->xkey[i+2] ^= cast_sbox7[U8c(z[0])];
756 key->xkey[i+3] ^= cast_sbox8[U8c(z[1])];
757 break;
758 case 12:
759 key->xkey[i+0] ^= cast_sbox5[U8d(x[0])];
760 key->xkey[i+1] ^= cast_sbox6[U8d(x[1])];
761 key->xkey[i+2] ^= cast_sbox7[U8a(x[2])];
762 key->xkey[i+3] ^= cast_sbox8[U8b(x[3])];
763 break;
764 }
765 if (i >= 16) {
766 key->xkey[i+0] &= 31;
767 key->xkey[i+1] &= 31;
768 key->xkey[i+2] &= 31;
769 key->xkey[i+3] &= 31;
770 }
771 }
772 /* Wipe clean */
773 for (i = 0; i < 4; i++) {
774 t[i] = x[i] = z[i] = 0;
775 }
776}
777
778/* Made in Canada */
779
diff --git a/src/lib/libc/crypt/crypt.3 b/src/lib/libc/crypt/crypt.3
new file mode 100644
index 0000000000..5f0f1cdba8
--- /dev/null
+++ b/src/lib/libc/crypt/crypt.3
@@ -0,0 +1,314 @@
1.\" $OpenBSD: crypt.3,v 1.19 2002/01/24 20:33:45 mickey Exp $
2.\"
3.\" FreeSec: libcrypt
4.\"
5.\" Copyright (c) 1994 David Burren
6.\" All rights reserved.
7.\"
8.\" Redistribution and use in source and binary forms, with or without
9.\" modification, are permitted provided that the following conditions
10.\" are met:
11.\" 1. Redistributions of source code must retain the above copyright
12.\" notice, this list of conditions and the following disclaimer.
13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution.
16.\" 4. Neither the name of the author nor the names of other contributors
17.\" may be used to endorse or promote products derived from this software
18.\" without specific prior written permission.
19.\"
20.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE.
31.\"
32.\" Manual page, using -mandoc macros
33.\"
34.Dd March 9, 1994
35.Dt CRYPT 3
36.Os
37.Sh NAME
38.Nm crypt ,
39.Nm setkey ,
40.Nm encrypt ,
41.Nm des_setkey ,
42.Nm des_cipher
43.Nd DES encryption
44.Sh SYNOPSIS
45.Fd #include <unistd.h>
46.Ft char *
47.Fn crypt "const char *key" "const char *setting"
48.Ft int
49.Fn setkey "char *key"
50.Ft int
51.Fn encrypt "char *block" "int flag"
52.Ft int
53.Fn des_setkey "const char *key"
54.Ft int
55.Fn des_cipher "const char *in" "char *out" "int32_t salt" "int count"
56.Sh DESCRIPTION
57The
58.Fn crypt
59function performs password encryption based on the
60.Tn NBS
61Data Encryption Standard (DES).
62Additional code has been added to deter key search attempts and to use
63stronger hashing algorithms.
64.Pp
65The first argument to
66.Fn crypt
67is a
68.Dv null Ns -terminated
69string, typically a user's typed password.
70The second is in one of three forms:
71if it begins with an underscore
72.Pq Ql _
73then an extended format is used
74in interpreting both the key and the setting, as outlined below.
75If it begins
76with a string character
77.Pq Ql $
78and a number then a different algorithm is used depending on the number.
79At the moment a
80.Ql $1
81chooses MD5 hashing and a
82.Ql $2
83chooses Blowfish hashing; see below for more information.
84.Ss Extended crypt
85The
86.Ar key
87is divided into groups of 8 characters (the last group is null-padded)
88and the low-order 7 bits of each character (56 bits per group) are
89used to form the DES key as follows:
90the first group of 56 bits becomes the initial DES key.
91For each additional group, the XOR of the encryption of the current DES
92key with itself and the group bits becomes the next DES key.
93.Pp
94The setting is a 9-character array consisting of an underscore followed
95by 4 bytes of iteration count and 4 bytes of salt.
96These are encoded as printable characters, 6 bits per character,
97least significant character first.
98The values 0 to 63 are encoded as
99.Dq \&./0-9A-Za-z .
100This allows 24 bits for both
101.Fa count
102and
103.Fa salt .
104.Ss "MD5" crypt
105For
106.Tn MD5
107crypt the version number,
108.Fa salt
109and the hashed password are separated by the
110.Ql $
111character.
112The maximum length of a password is limited by
113the length counter of the MD5 context, which is about
1142**64.
115A valid MD5 password entry looks like this:
116.Pp
117.Dq $1$caeiHQwX$hsKqOjrFRRN6K32OWkCBf1 .
118.Pp
119The whole MD5 password string is passed as
120.Fa setting
121for interpretation.
122.Ss "Blowfish" crypt
123The
124.Tn Blowfish
125version of crypt has 128 bits of
126.Fa salt
127in order to make building dictionaries of common passwords space consuming.
128The initial state of the
129.Tn Blowfish
130cipher is expanded using the
131.Fa salt
132and the
133.Fa password
134repeating the process a variable number of rounds, which is encoded in
135the password string.
136The maximum password length is 72.
137The final Blowfish password entry is created by encrypting the string
138.Pp
139.Dq OrpheanBeholderScryDoubt
140.Pp
141with the
142.Tn Blowfish
143state 64 times.
144.Pp
145The version number, the logarithm of the number of rounds and
146the concatenation of salt and hashed password are separated by the
147.Ql $
148character.
149An encoded
150.Sq 8
151would specify 256 rounds.
152A valid Blowfish password looks like this:
153.Pp
154.Dq $2a$12$eIAq8PR8sIUnJ1HaohxX2O9x9Qlm2vK97LJ5dsXdmB.eXF42qjchC .
155.Pp
156The whole Blowfish password string is passed as
157.Fa setting
158for interpretation.
159.Ss "Traditional" crypt
160The first 8 bytes of the key are null-padded, and the low-order 7 bits of
161each character is used to form the 56-bit
162.Tn DES
163key.
164.Pp
165The setting is a 2-character array of the ASCII-encoded salt.
166Thus only 12 bits of
167.Fa salt
168are used.
169.Fa count
170is set to 25.
171.Ss DES Algorithm
172The
173.Fa salt
174introduces disorder in the
175.Tn DES
176algorithm in one of 16777216 or 4096 possible ways
177(i.e., with 24 or 12 bits: if bit
178.Em i
179of the
180.Ar salt
181is set, then bits
182.Em i
183and
184.Em i+24
185are swapped in the
186.Tn DES
187E-box output).
188.Pp
189The DES key is used to encrypt a 64-bit constant using
190.Ar count
191iterations of
192.Tn DES .
193The value returned is a
194.Dv null Ns -terminated
195string, 20 or 13 bytes (plus null) in length, consisting of the
196.Ar setting
197followed by the encoded 64-bit encryption.
198.Pp
199The functions
200.Fn encrypt ,
201.Fn setkey ,
202.Fn des_setkey ,
203and
204.Fn des_cipher
205provide access to the
206.Tn DES
207algorithm itself.
208.Fn setkey
209is passed a 64-byte array of binary values (numeric 0 or 1).
210A 56-bit key is extracted from this array by dividing the
211array into groups of 8, and ignoring the last bit in each group.
212That bit is reserved for a byte parity check by DES, but is ignored
213by these functions.
214.Pp
215The
216.Fa block
217argument to
218.Fn encrypt
219is also a 64-byte array of binary values.
220If the value of
221.Fa flag
222is 0,
223.Fa block
224is encrypted otherwise it is decrypted.
225The result is returned in the original array
226.Fa block
227after using the key specified by
228.Fn setkey
229to process it.
230.Pp
231The argument to
232.Fn des_setkey
233is a character array of length 8.
234The least significant bit (the parity bit) in each character is ignored,
235and the remaining bits are concatenated to form a 56-bit key.
236The function
237.Fn des_cipher
238encrypts (or decrypts if
239.Fa count
240is negative) the 64-bits stored in the 8 characters at
241.Fa in
242using
243.Xr abs 3
244of
245.Fa count
246iterations of
247.Tn DES
248and stores the 64-bit result in the 8 characters at
249.Fa out
250(which may be the same as
251.Fa in ) .
252The
253.Fa salt
254specifies perturbations to the
255.Tn DES
256E-box output as described above.
257.Pp
258The function
259.Fn crypt
260returns a pointer to the encrypted value on success, and
261.Dv NULL
262on failure.
263The functions
264.Fn setkey ,
265.Fn encrypt ,
266.Fn des_setkey ,
267and
268.Fn des_cipher
269return 0 on success and 1 on failure.
270.Pp
271The
272.Fn crypt ,
273.Fn setkey ,
274and
275.Fn des_setkey
276functions all manipulate the same key space.
277.Sh SEE ALSO
278.Xr login 1 ,
279.Xr passwd 1 ,
280.Xr blowfish 3 ,
281.Xr getpass 3 ,
282.Xr md5 3 ,
283.Xr passwd 5
284.Sh AUTHORS
285David Burren <davidb@werj.com.au>
286.Sh HISTORY
287A rotor-based
288.Fn crypt
289function appeared in
290.At v3 .
291The current style
292.Fn crypt
293first appeared in
294.At v7 .
295.Pp
296This library (FreeSec 1.0) was developed outside the United States of America
297as an unencumbered replacement for the U.S.-only libcrypt encryption
298library.
299Programs linked against the
300.Fn crypt
301interface may be exported from the U.S.A. only if they use
302.Fn crypt
303solely for authentication purposes and avoid use of
304the other programmer interfaces listed above.
305Special care has been taken
306in the library so that programs which only use the
307.Fn crypt
308interface do not pull in the other components.
309.Sh BUGS
310The
311.Fn crypt
312function returns a pointer to static data, and subsequent calls to
313.Fn crypt
314will modify the same object.
diff --git a/src/lib/libc/crypt/crypt.c b/src/lib/libc/crypt/crypt.c
new file mode 100644
index 0000000000..17b50b7f52
--- /dev/null
+++ b/src/lib/libc/crypt/crypt.c
@@ -0,0 +1,713 @@
1/* $OpenBSD: crypt.c,v 1.16 2002/04/29 06:26:50 pvalchev Exp $ */
2
3/*
4 * FreeSec: libcrypt
5 *
6 * Copyright (c) 1994 David Burren
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 4. Neither the name of the author nor the names of other contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 *
34 * This is an original implementation of the DES and the crypt(3) interfaces
35 * by David Burren <davidb@werj.com.au>.
36 *
37 * An excellent reference on the underlying algorithm (and related
38 * algorithms) is:
39 *
40 * B. Schneier, Applied Cryptography: protocols, algorithms,
41 * and source code in C, John Wiley & Sons, 1994.
42 *
43 * Note that in that book's description of DES the lookups for the initial,
44 * pbox, and final permutations are inverted (this has been brought to the
45 * attention of the author). A list of errata for this book has been
46 * posted to the sci.crypt newsgroup by the author and is available for FTP.
47 *
48 * NOTE:
49 * This file has a static version of des_setkey() so that crypt.o exports
50 * only the crypt() interface. This is required to make binaries linked
51 * against crypt.o exportable or re-exportable from the USA.
52 */
53
54#if defined(LIBC_SCCS) && !defined(lint)
55static char rcsid[] = "$OpenBSD: crypt.c,v 1.16 2002/04/29 06:26:50 pvalchev Exp $";
56#endif /* LIBC_SCCS and not lint */
57
58#include <sys/types.h>
59#include <sys/param.h>
60#include <pwd.h>
61#include <string.h>
62
63#ifdef DEBUG
64# include <stdio.h>
65#endif
66
67static u_char IP[64] = {
68 58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4,
69 62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8,
70 57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11, 3,
71 61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7
72};
73
74static u_char inv_key_perm[64];
75static u_char u_key_perm[56];
76static u_char key_perm[56] = {
77 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18,
78 10, 2, 59, 51, 43, 35, 27, 19, 11, 3, 60, 52, 44, 36,
79 63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46, 38, 30, 22,
80 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 28, 20, 12, 4
81};
82
83static u_char key_shifts[16] = {
84 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
85};
86
87static u_char inv_comp_perm[56];
88static u_char comp_perm[48] = {
89 14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10,
90 23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2,
91 41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48,
92 44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32
93};
94
95/*
96 * No E box is used, as it's replaced by some ANDs, shifts, and ORs.
97 */
98
99static u_char u_sbox[8][64];
100static u_char sbox[8][64] = {
101 {
102 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
103 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
104 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
105 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13
106 },
107 {
108 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
109 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
110 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
111 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9
112 },
113 {
114 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
115 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
116 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
117 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12
118 },
119 {
120 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
121 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
122 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
123 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14
124 },
125 {
126 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
127 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
128 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
129 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3
130 },
131 {
132 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
133 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
134 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
135 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13
136 },
137 {
138 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
139 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
140 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
141 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12
142 },
143 {
144 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
145 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
146 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
147 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11
148 }
149};
150
151static u_char un_pbox[32];
152static u_char pbox[32] = {
153 16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10,
154 2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25
155};
156
157static u_int32_t bits32[32] =
158{
159 0x80000000, 0x40000000, 0x20000000, 0x10000000,
160 0x08000000, 0x04000000, 0x02000000, 0x01000000,
161 0x00800000, 0x00400000, 0x00200000, 0x00100000,
162 0x00080000, 0x00040000, 0x00020000, 0x00010000,
163 0x00008000, 0x00004000, 0x00002000, 0x00001000,
164 0x00000800, 0x00000400, 0x00000200, 0x00000100,
165 0x00000080, 0x00000040, 0x00000020, 0x00000010,
166 0x00000008, 0x00000004, 0x00000002, 0x00000001
167};
168
169static u_char bits8[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
170
171static u_int32_t saltbits;
172static int32_t old_salt;
173static u_int32_t *bits28, *bits24;
174static u_char init_perm[64], final_perm[64];
175static u_int32_t en_keysl[16], en_keysr[16];
176static u_int32_t de_keysl[16], de_keysr[16];
177static int des_initialised = 0;
178static u_char m_sbox[4][4096];
179static u_int32_t psbox[4][256];
180static u_int32_t ip_maskl[8][256], ip_maskr[8][256];
181static u_int32_t fp_maskl[8][256], fp_maskr[8][256];
182static u_int32_t key_perm_maskl[8][128], key_perm_maskr[8][128];
183static u_int32_t comp_maskl[8][128], comp_maskr[8][128];
184static u_int32_t old_rawkey0, old_rawkey1;
185
186static u_char ascii64[] =
187 "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
188/* 0000000000111111111122222222223333333333444444444455555555556666 */
189/* 0123456789012345678901234567890123456789012345678901234567890123 */
190
191static __inline int
192ascii_to_bin(ch)
193 char ch;
194{
195 if (ch > 'z')
196 return(0);
197 if (ch >= 'a')
198 return(ch - 'a' + 38);
199 if (ch > 'Z')
200 return(0);
201 if (ch >= 'A')
202 return(ch - 'A' + 12);
203 if (ch > '9')
204 return(0);
205 if (ch >= '.')
206 return(ch - '.');
207 return(0);
208}
209
210static void
211des_init()
212{
213 int i, j, b, k, inbit, obit;
214 u_int32_t *p, *il, *ir, *fl, *fr;
215
216 old_rawkey0 = old_rawkey1 = 0;
217 saltbits = 0;
218 old_salt = 0;
219 bits24 = (bits28 = bits32 + 4) + 4;
220
221 /*
222 * Invert the S-boxes, reordering the input bits.
223 */
224 for (i = 0; i < 8; i++)
225 for (j = 0; j < 64; j++) {
226 b = (j & 0x20) | ((j & 1) << 4) | ((j >> 1) & 0xf);
227 u_sbox[i][j] = sbox[i][b];
228 }
229
230 /*
231 * Convert the inverted S-boxes into 4 arrays of 8 bits.
232 * Each will handle 12 bits of the S-box input.
233 */
234 for (b = 0; b < 4; b++)
235 for (i = 0; i < 64; i++)
236 for (j = 0; j < 64; j++)
237 m_sbox[b][(i << 6) | j] =
238 (u_sbox[(b << 1)][i] << 4) |
239 u_sbox[(b << 1) + 1][j];
240
241 /*
242 * Set up the initial & final permutations into a useful form, and
243 * initialise the inverted key permutation.
244 */
245 for (i = 0; i < 64; i++) {
246 init_perm[final_perm[i] = IP[i] - 1] = i;
247 inv_key_perm[i] = 255;
248 }
249
250 /*
251 * Invert the key permutation and initialise the inverted key
252 * compression permutation.
253 */
254 for (i = 0; i < 56; i++) {
255 u_key_perm[i] = key_perm[i] - 1;
256 inv_key_perm[key_perm[i] - 1] = i;
257 inv_comp_perm[i] = 255;
258 }
259
260 /*
261 * Invert the key compression permutation.
262 */
263 for (i = 0; i < 48; i++) {
264 inv_comp_perm[comp_perm[i] - 1] = i;
265 }
266
267 /*
268 * Set up the OR-mask arrays for the initial and final permutations,
269 * and for the key initial and compression permutations.
270 */
271 for (k = 0; k < 8; k++) {
272 for (i = 0; i < 256; i++) {
273 *(il = &ip_maskl[k][i]) = 0;
274 *(ir = &ip_maskr[k][i]) = 0;
275 *(fl = &fp_maskl[k][i]) = 0;
276 *(fr = &fp_maskr[k][i]) = 0;
277 for (j = 0; j < 8; j++) {
278 inbit = 8 * k + j;
279 if (i & bits8[j]) {
280 if ((obit = init_perm[inbit]) < 32)
281 *il |= bits32[obit];
282 else
283 *ir |= bits32[obit-32];
284 if ((obit = final_perm[inbit]) < 32)
285 *fl |= bits32[obit];
286 else
287 *fr |= bits32[obit - 32];
288 }
289 }
290 }
291 for (i = 0; i < 128; i++) {
292 *(il = &key_perm_maskl[k][i]) = 0;
293 *(ir = &key_perm_maskr[k][i]) = 0;
294 for (j = 0; j < 7; j++) {
295 inbit = 8 * k + j;
296 if (i & bits8[j + 1]) {
297 if ((obit = inv_key_perm[inbit]) == 255)
298 continue;
299 if (obit < 28)
300 *il |= bits28[obit];
301 else
302 *ir |= bits28[obit - 28];
303 }
304 }
305 *(il = &comp_maskl[k][i]) = 0;
306 *(ir = &comp_maskr[k][i]) = 0;
307 for (j = 0; j < 7; j++) {
308 inbit = 7 * k + j;
309 if (i & bits8[j + 1]) {
310 if ((obit=inv_comp_perm[inbit]) == 255)
311 continue;
312 if (obit < 24)
313 *il |= bits24[obit];
314 else
315 *ir |= bits24[obit - 24];
316 }
317 }
318 }
319 }
320
321 /*
322 * Invert the P-box permutation, and convert into OR-masks for
323 * handling the output of the S-box arrays setup above.
324 */
325 for (i = 0; i < 32; i++)
326 un_pbox[pbox[i] - 1] = i;
327
328 for (b = 0; b < 4; b++)
329 for (i = 0; i < 256; i++) {
330 *(p = &psbox[b][i]) = 0;
331 for (j = 0; j < 8; j++) {
332 if (i & bits8[j])
333 *p |= bits32[un_pbox[8 * b + j]];
334 }
335 }
336
337 des_initialised = 1;
338}
339
340static void
341setup_salt(salt)
342 int32_t salt;
343{
344 u_int32_t obit, saltbit;
345 int i;
346
347 if (salt == old_salt)
348 return;
349 old_salt = salt;
350
351 saltbits = 0;
352 saltbit = 1;
353 obit = 0x800000;
354 for (i = 0; i < 24; i++) {
355 if (salt & saltbit)
356 saltbits |= obit;
357 saltbit <<= 1;
358 obit >>= 1;
359 }
360}
361
362static int
363des_setkey(key)
364 const char *key;
365{
366 u_int32_t k0, k1, rawkey0, rawkey1;
367 int shifts, round;
368
369 if (!des_initialised)
370 des_init();
371
372 rawkey0 = ntohl(*(u_int32_t *) key);
373 rawkey1 = ntohl(*(u_int32_t *) (key + 4));
374
375 if ((rawkey0 | rawkey1)
376 && rawkey0 == old_rawkey0
377 && rawkey1 == old_rawkey1) {
378 /*
379 * Already setup for this key.
380 * This optimisation fails on a zero key (which is weak and
381 * has bad parity anyway) in order to simplify the starting
382 * conditions.
383 */
384 return(0);
385 }
386 old_rawkey0 = rawkey0;
387 old_rawkey1 = rawkey1;
388
389 /*
390 * Do key permutation and split into two 28-bit subkeys.
391 */
392 k0 = key_perm_maskl[0][rawkey0 >> 25]
393 | key_perm_maskl[1][(rawkey0 >> 17) & 0x7f]
394 | key_perm_maskl[2][(rawkey0 >> 9) & 0x7f]
395 | key_perm_maskl[3][(rawkey0 >> 1) & 0x7f]
396 | key_perm_maskl[4][rawkey1 >> 25]
397 | key_perm_maskl[5][(rawkey1 >> 17) & 0x7f]
398 | key_perm_maskl[6][(rawkey1 >> 9) & 0x7f]
399 | key_perm_maskl[7][(rawkey1 >> 1) & 0x7f];
400 k1 = key_perm_maskr[0][rawkey0 >> 25]
401 | key_perm_maskr[1][(rawkey0 >> 17) & 0x7f]
402 | key_perm_maskr[2][(rawkey0 >> 9) & 0x7f]
403 | key_perm_maskr[3][(rawkey0 >> 1) & 0x7f]
404 | key_perm_maskr[4][rawkey1 >> 25]
405 | key_perm_maskr[5][(rawkey1 >> 17) & 0x7f]
406 | key_perm_maskr[6][(rawkey1 >> 9) & 0x7f]
407 | key_perm_maskr[7][(rawkey1 >> 1) & 0x7f];
408 /*
409 * Rotate subkeys and do compression permutation.
410 */
411 shifts = 0;
412 for (round = 0; round < 16; round++) {
413 u_int32_t t0, t1;
414
415 shifts += key_shifts[round];
416
417 t0 = (k0 << shifts) | (k0 >> (28 - shifts));
418 t1 = (k1 << shifts) | (k1 >> (28 - shifts));
419
420 de_keysl[15 - round] =
421 en_keysl[round] = comp_maskl[0][(t0 >> 21) & 0x7f]
422 | comp_maskl[1][(t0 >> 14) & 0x7f]
423 | comp_maskl[2][(t0 >> 7) & 0x7f]
424 | comp_maskl[3][t0 & 0x7f]
425 | comp_maskl[4][(t1 >> 21) & 0x7f]
426 | comp_maskl[5][(t1 >> 14) & 0x7f]
427 | comp_maskl[6][(t1 >> 7) & 0x7f]
428 | comp_maskl[7][t1 & 0x7f];
429
430 de_keysr[15 - round] =
431 en_keysr[round] = comp_maskr[0][(t0 >> 21) & 0x7f]
432 | comp_maskr[1][(t0 >> 14) & 0x7f]
433 | comp_maskr[2][(t0 >> 7) & 0x7f]
434 | comp_maskr[3][t0 & 0x7f]
435 | comp_maskr[4][(t1 >> 21) & 0x7f]
436 | comp_maskr[5][(t1 >> 14) & 0x7f]
437 | comp_maskr[6][(t1 >> 7) & 0x7f]
438 | comp_maskr[7][t1 & 0x7f];
439 }
440 return(0);
441}
442
443static int
444do_des(l_in, r_in, l_out, r_out, count)
445 u_int32_t l_in, r_in, *l_out, *r_out;
446 int count;
447{
448 /*
449 * l_in, r_in, l_out, and r_out are in pseudo-"big-endian" format.
450 */
451 u_int32_t l, r, *kl, *kr, *kl1, *kr1;
452 u_int32_t f, r48l, r48r;
453 int round;
454
455 if (count == 0) {
456 return(1);
457 } else if (count > 0) {
458 /*
459 * Encrypting
460 */
461 kl1 = en_keysl;
462 kr1 = en_keysr;
463 } else {
464 /*
465 * Decrypting
466 */
467 count = -count;
468 kl1 = de_keysl;
469 kr1 = de_keysr;
470 }
471
472 /*
473 * Do initial permutation (IP).
474 */
475 l = ip_maskl[0][l_in >> 24]
476 | ip_maskl[1][(l_in >> 16) & 0xff]
477 | ip_maskl[2][(l_in >> 8) & 0xff]
478 | ip_maskl[3][l_in & 0xff]
479 | ip_maskl[4][r_in >> 24]
480 | ip_maskl[5][(r_in >> 16) & 0xff]
481 | ip_maskl[6][(r_in >> 8) & 0xff]
482 | ip_maskl[7][r_in & 0xff];
483 r = ip_maskr[0][l_in >> 24]
484 | ip_maskr[1][(l_in >> 16) & 0xff]
485 | ip_maskr[2][(l_in >> 8) & 0xff]
486 | ip_maskr[3][l_in & 0xff]
487 | ip_maskr[4][r_in >> 24]
488 | ip_maskr[5][(r_in >> 16) & 0xff]
489 | ip_maskr[6][(r_in >> 8) & 0xff]
490 | ip_maskr[7][r_in & 0xff];
491
492 while (count--) {
493 /*
494 * Do each round.
495 */
496 kl = kl1;
497 kr = kr1;
498 round = 16;
499 while (round--) {
500 /*
501 * Expand R to 48 bits (simulate the E-box).
502 */
503 r48l = ((r & 0x00000001) << 23)
504 | ((r & 0xf8000000) >> 9)
505 | ((r & 0x1f800000) >> 11)
506 | ((r & 0x01f80000) >> 13)
507 | ((r & 0x001f8000) >> 15);
508
509 r48r = ((r & 0x0001f800) << 7)
510 | ((r & 0x00001f80) << 5)
511 | ((r & 0x000001f8) << 3)
512 | ((r & 0x0000001f) << 1)
513 | ((r & 0x80000000) >> 31);
514 /*
515 * Do salting for crypt() and friends, and
516 * XOR with the permuted key.
517 */
518 f = (r48l ^ r48r) & saltbits;
519 r48l ^= f ^ *kl++;
520 r48r ^= f ^ *kr++;
521 /*
522 * Do sbox lookups (which shrink it back to 32 bits)
523 * and do the pbox permutation at the same time.
524 */
525 f = psbox[0][m_sbox[0][r48l >> 12]]
526 | psbox[1][m_sbox[1][r48l & 0xfff]]
527 | psbox[2][m_sbox[2][r48r >> 12]]
528 | psbox[3][m_sbox[3][r48r & 0xfff]];
529 /*
530 * Now that we've permuted things, complete f().
531 */
532 f ^= l;
533 l = r;
534 r = f;
535 }
536 r = l;
537 l = f;
538 }
539 /*
540 * Do final permutation (inverse of IP).
541 */
542 *l_out = fp_maskl[0][l >> 24]
543 | fp_maskl[1][(l >> 16) & 0xff]
544 | fp_maskl[2][(l >> 8) & 0xff]
545 | fp_maskl[3][l & 0xff]
546 | fp_maskl[4][r >> 24]
547 | fp_maskl[5][(r >> 16) & 0xff]
548 | fp_maskl[6][(r >> 8) & 0xff]
549 | fp_maskl[7][r & 0xff];
550 *r_out = fp_maskr[0][l >> 24]
551 | fp_maskr[1][(l >> 16) & 0xff]
552 | fp_maskr[2][(l >> 8) & 0xff]
553 | fp_maskr[3][l & 0xff]
554 | fp_maskr[4][r >> 24]
555 | fp_maskr[5][(r >> 16) & 0xff]
556 | fp_maskr[6][(r >> 8) & 0xff]
557 | fp_maskr[7][r & 0xff];
558 return(0);
559}
560
561static int
562des_cipher(in, out, salt, count)
563 const char *in;
564 char *out;
565 int32_t salt;
566 int count;
567{
568 u_int32_t l_out, r_out, rawl, rawr;
569 u_int32_t x[2];
570 int retval;
571
572 if (!des_initialised)
573 des_init();
574
575 setup_salt(salt);
576
577 memcpy(x, in, sizeof x);
578 rawl = ntohl(x[0]);
579 rawr = ntohl(x[1]);
580 retval = do_des(rawl, rawr, &l_out, &r_out, count);
581
582 x[0] = htonl(l_out);
583 x[1] = htonl(r_out);
584 memcpy(out, x, sizeof x);
585 return(retval);
586}
587
588char *
589crypt(key, setting)
590 const char *key;
591 const char *setting;
592{
593 int i;
594 u_int32_t count, salt, l, r0, r1, keybuf[2];
595 u_char *p, *q;
596 static u_char output[21];
597 extern char *md5crypt(const char *, const char *);
598 extern char *bcrypt(const char *, const char *);
599
600 if (setting[0] == '$') {
601 switch (setting[1]) {
602 case '1':
603 return (md5crypt(key, setting));
604 default:
605 return bcrypt(key, setting);
606 }
607 }
608
609 if (!des_initialised)
610 des_init();
611
612 /*
613 * Copy the key, shifting each character up by one bit
614 * and padding with zeros.
615 */
616 q = (u_char *) keybuf;
617 while ((q - (u_char *) keybuf) < sizeof(keybuf)) {
618 if ((*q++ = *key << 1))
619 key++;
620 }
621 if (des_setkey((u_char *) keybuf))
622 return(NULL);
623
624 if (*setting == _PASSWORD_EFMT1) {
625 /*
626 * "new"-style:
627 * setting - underscore, 4 bytes of count, 4 bytes of salt
628 * key - unlimited characters
629 */
630 for (i = 1, count = 0; i < 5; i++)
631 count |= ascii_to_bin(setting[i]) << (i - 1) * 6;
632
633 for (i = 5, salt = 0; i < 9; i++)
634 salt |= ascii_to_bin(setting[i]) << (i - 5) * 6;
635
636 while (*key) {
637 /*
638 * Encrypt the key with itself.
639 */
640 if (des_cipher((u_char*)keybuf, (u_char*)keybuf, 0, 1))
641 return(NULL);
642 /*
643 * And XOR with the next 8 characters of the key.
644 */
645 q = (u_char *) keybuf;
646 while (((q - (u_char *) keybuf) < sizeof(keybuf)) &&
647 *key)
648 *q++ ^= *key++ << 1;
649
650 if (des_setkey((u_char *) keybuf))
651 return(NULL);
652 }
653 strlcpy((char *)output, setting, 10);
654
655 /*
656 * Double check that we weren't given a short setting.
657 * If we were, the above code will probably have created
658 * weird values for count and salt, but we don't really care.
659 * Just make sure the output string doesn't have an extra
660 * NUL in it.
661 */
662 p = output + strlen((const char *)output);
663 } else {
664 /*
665 * "old"-style:
666 * setting - 2 bytes of salt
667 * key - up to 8 characters
668 */
669 count = 25;
670
671 salt = (ascii_to_bin(setting[1]) << 6)
672 | ascii_to_bin(setting[0]);
673
674 output[0] = setting[0];
675 /*
676 * If the encrypted password that the salt was extracted from
677 * is only 1 character long, the salt will be corrupted. We
678 * need to ensure that the output string doesn't have an extra
679 * NUL in it!
680 */
681 output[1] = setting[1] ? setting[1] : output[0];
682
683 p = output + 2;
684 }
685 setup_salt(salt);
686 /*
687 * Do it.
688 */
689 if (do_des(0, 0, &r0, &r1, count))
690 return(NULL);
691 /*
692 * Now encode the result...
693 */
694 l = (r0 >> 8);
695 *p++ = ascii64[(l >> 18) & 0x3f];
696 *p++ = ascii64[(l >> 12) & 0x3f];
697 *p++ = ascii64[(l >> 6) & 0x3f];
698 *p++ = ascii64[l & 0x3f];
699
700 l = (r0 << 16) | ((r1 >> 16) & 0xffff);
701 *p++ = ascii64[(l >> 18) & 0x3f];
702 *p++ = ascii64[(l >> 12) & 0x3f];
703 *p++ = ascii64[(l >> 6) & 0x3f];
704 *p++ = ascii64[l & 0x3f];
705
706 l = r1 << 2;
707 *p++ = ascii64[(l >> 12) & 0x3f];
708 *p++ = ascii64[(l >> 6) & 0x3f];
709 *p++ = ascii64[l & 0x3f];
710 *p = 0;
711
712 return((char *)output);
713}
diff --git a/src/lib/libc/crypt/md5crypt.c b/src/lib/libc/crypt/md5crypt.c
new file mode 100644
index 0000000000..048858494c
--- /dev/null
+++ b/src/lib/libc/crypt/md5crypt.c
@@ -0,0 +1,156 @@
1/* $OpenBSD: md5crypt.c,v 1.11 2003/04/02 20:35:29 millert Exp $ */
2
3/*
4 * ----------------------------------------------------------------------------
5 * "THE BEER-WARE LICENSE" (Revision 42):
6 * <phk@login.dknet.dk> wrote this file. As long as you retain this notice you
7 * can do whatever you want with this stuff. If we meet some day, and you think
8 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
9 * ----------------------------------------------------------------------------
10 *
11 * $FreeBSD: crypt.c,v 1.5 1996/10/14 08:34:02 phk Exp $
12 *
13 */
14
15#if defined(LIBC_SCCS) && !defined(lint)
16static char rcsid[] = "$OpenBSD: md5crypt.c,v 1.11 2003/04/02 20:35:29 millert Exp $";
17#endif /* LIBC_SCCS and not lint */
18
19#include <unistd.h>
20#include <stdio.h>
21#include <string.h>
22#include <md5.h>
23#include <string.h>
24
25static unsigned char itoa64[] = /* 0 ... 63 => ascii - 64 */
26 "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
27
28static void to64(char *, u_int32_t, int);
29
30static void
31to64(s, v, n)
32 char *s;
33 u_int32_t v;
34 int n;
35{
36 while (--n >= 0) {
37 *s++ = itoa64[v&0x3f];
38 v >>= 6;
39 }
40}
41
42/*
43 * UNIX password
44 *
45 * Use MD5 for what it is best at...
46 */
47
48char *
49md5crypt(pw, salt)
50 register const char *pw;
51 register const char *salt;
52{
53 /*
54 * This string is magic for this algorithm. Having
55 * it this way, we can get get better later on
56 */
57 static unsigned char *magic = (unsigned char *)"$1$";
58
59 static char passwd[120], *p;
60 static const unsigned char *sp,*ep;
61 unsigned char final[16];
62 int sl,pl,i;
63 MD5_CTX ctx,ctx1;
64 u_int32_t l;
65
66 /* Refine the Salt first */
67 sp = (const unsigned char *)salt;
68
69 /* If it starts with the magic string, then skip that */
70 if(!strncmp((const char *)sp,(const char *)magic,strlen((const char *)magic)))
71 sp += strlen((const char *)magic);
72
73 /* It stops at the first '$', max 8 chars */
74 for(ep=sp;*ep && *ep != '$' && ep < (sp+8);ep++)
75 continue;
76
77 /* get the length of the true salt */
78 sl = ep - sp;
79
80 MD5Init(&ctx);
81
82 /* The password first, since that is what is most unknown */
83 MD5Update(&ctx,(const unsigned char *)pw,strlen(pw));
84
85 /* Then our magic string */
86 MD5Update(&ctx,magic,strlen((const char *)magic));
87
88 /* Then the raw salt */
89 MD5Update(&ctx,sp,sl);
90
91 /* Then just as many characters of the MD5(pw,salt,pw) */
92 MD5Init(&ctx1);
93 MD5Update(&ctx1,(const unsigned char *)pw,strlen(pw));
94 MD5Update(&ctx1,sp,sl);
95 MD5Update(&ctx1,(const unsigned char *)pw,strlen(pw));
96 MD5Final(final,&ctx1);
97 for(pl = strlen(pw); pl > 0; pl -= 16)
98 MD5Update(&ctx,final,pl>16 ? 16 : pl);
99
100 /* Don't leave anything around in vm they could use. */
101 memset(final,0,sizeof final);
102
103 /* Then something really weird... */
104 for (i = strlen(pw); i ; i >>= 1)
105 if(i&1)
106 MD5Update(&ctx, final, 1);
107 else
108 MD5Update(&ctx, (const unsigned char *)pw, 1);
109
110 /* Now make the output string */
111 snprintf(passwd, sizeof(passwd), "%s%.*s$", (char *)magic,
112 sl, (const char *)sp);
113
114 MD5Final(final,&ctx);
115
116 /*
117 * and now, just to make sure things don't run too fast
118 * On a 60 Mhz Pentium this takes 34 msec, so you would
119 * need 30 seconds to build a 1000 entry dictionary...
120 */
121 for(i=0;i<1000;i++) {
122 MD5Init(&ctx1);
123 if(i & 1)
124 MD5Update(&ctx1,(const unsigned char *)pw,strlen(pw));
125 else
126 MD5Update(&ctx1,final,16);
127
128 if(i % 3)
129 MD5Update(&ctx1,sp,sl);
130
131 if(i % 7)
132 MD5Update(&ctx1,(const unsigned char *)pw,strlen(pw));
133
134 if(i & 1)
135 MD5Update(&ctx1,final,16);
136 else
137 MD5Update(&ctx1,(const unsigned char *)pw,strlen(pw));
138 MD5Final(final,&ctx1);
139 }
140
141 p = passwd + strlen(passwd);
142
143 l = (final[ 0]<<16) | (final[ 6]<<8) | final[12]; to64(p,l,4); p += 4;
144 l = (final[ 1]<<16) | (final[ 7]<<8) | final[13]; to64(p,l,4); p += 4;
145 l = (final[ 2]<<16) | (final[ 8]<<8) | final[14]; to64(p,l,4); p += 4;
146 l = (final[ 3]<<16) | (final[ 9]<<8) | final[15]; to64(p,l,4); p += 4;
147 l = (final[ 4]<<16) | (final[10]<<8) | final[ 5]; to64(p,l,4); p += 4;
148 l = final[11] ; to64(p,l,2); p += 2;
149 *p = '\0';
150
151 /* Don't leave anything around in vm they could use. */
152 memset(final,0,sizeof final);
153
154 return passwd;
155}
156
diff --git a/src/lib/libc/crypt/morecrypt.c b/src/lib/libc/crypt/morecrypt.c
new file mode 100644
index 0000000000..e9e0ced4c1
--- /dev/null
+++ b/src/lib/libc/crypt/morecrypt.c
@@ -0,0 +1,628 @@
1/* $OpenBSD: morecrypt.c,v 1.9 1998/03/22 19:01:20 niklas Exp $ */
2
3/*
4 * FreeSec: libcrypt
5 *
6 * Copyright (c) 1994 David Burren
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 4. Neither the name of the author nor the names of other contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 *
34 * This is an original implementation of the DES and the crypt(3) interfaces
35 * by David Burren <davidb@werj.com.au>.
36 *
37 * An excellent reference on the underlying algorithm (and related
38 * algorithms) is:
39 *
40 * B. Schneier, Applied Cryptography: protocols, algorithms,
41 * and source code in C, John Wiley & Sons, 1994.
42 *
43 * Note that in that book's description of DES the lookups for the initial,
44 * pbox, and final permutations are inverted (this has been brought to the
45 * attention of the author). A list of errata for this book has been
46 * posted to the sci.crypt newsgroup by the author and is available for FTP.
47 *
48 * NOTE:
49 * This file must copy certain chunks of crypt.c for legal reasons.
50 * crypt.c can only export the interface crypt(), to make binaries
51 * exportable from the USA. Hence, to also have the other crypto interfaces
52 * available we have to copy pieces...
53 */
54
55#if defined(LIBC_SCCS) && !defined(lint)
56static char rcsid[] = "$OpenBSD: morecrypt.c,v 1.9 1998/03/22 19:01:20 niklas Exp $";
57#endif /* LIBC_SCCS and not lint */
58
59#include <sys/types.h>
60#include <sys/param.h>
61#include <pwd.h>
62#include <string.h>
63
64#ifdef DEBUG
65# include <stdio.h>
66#endif
67
68static u_char IP[64] = {
69 58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4,
70 62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8,
71 57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11, 3,
72 61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7
73};
74
75static u_char inv_key_perm[64];
76static u_char u_key_perm[56];
77static u_char key_perm[56] = {
78 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18,
79 10, 2, 59, 51, 43, 35, 27, 19, 11, 3, 60, 52, 44, 36,
80 63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46, 38, 30, 22,
81 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 28, 20, 12, 4
82};
83
84static u_char key_shifts[16] = {
85 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
86};
87
88static u_char inv_comp_perm[56];
89static u_char comp_perm[48] = {
90 14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10,
91 23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2,
92 41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48,
93 44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32
94};
95
96/*
97 * No E box is used, as it's replaced by some ANDs, shifts, and ORs.
98 */
99
100static u_char u_sbox[8][64];
101static u_char sbox[8][64] = {
102 {
103 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
104 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
105 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
106 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13
107 },
108 {
109 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
110 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
111 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
112 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9
113 },
114 {
115 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
116 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
117 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
118 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12
119 },
120 {
121 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
122 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
123 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
124 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14
125 },
126 {
127 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
128 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
129 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
130 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3
131 },
132 {
133 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
134 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
135 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
136 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13
137 },
138 {
139 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
140 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
141 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
142 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12
143 },
144 {
145 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
146 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
147 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
148 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11
149 }
150};
151
152static u_char un_pbox[32];
153static u_char pbox[32] = {
154 16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10,
155 2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25
156};
157
158static u_int32_t bits32[32] =
159{
160 0x80000000, 0x40000000, 0x20000000, 0x10000000,
161 0x08000000, 0x04000000, 0x02000000, 0x01000000,
162 0x00800000, 0x00400000, 0x00200000, 0x00100000,
163 0x00080000, 0x00040000, 0x00020000, 0x00010000,
164 0x00008000, 0x00004000, 0x00002000, 0x00001000,
165 0x00000800, 0x00000400, 0x00000200, 0x00000100,
166 0x00000080, 0x00000040, 0x00000020, 0x00000010,
167 0x00000008, 0x00000004, 0x00000002, 0x00000001
168};
169
170static u_char bits8[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
171
172static u_int32_t saltbits;
173static int32_t old_salt;
174static u_int32_t *bits28, *bits24;
175static u_char init_perm[64], final_perm[64];
176static u_int32_t en_keysl[16], en_keysr[16];
177static u_int32_t de_keysl[16], de_keysr[16];
178static int des_initialised = 0;
179static u_char m_sbox[4][4096];
180static u_int32_t psbox[4][256];
181static u_int32_t ip_maskl[8][256], ip_maskr[8][256];
182static u_int32_t fp_maskl[8][256], fp_maskr[8][256];
183static u_int32_t key_perm_maskl[8][128], key_perm_maskr[8][128];
184static u_int32_t comp_maskl[8][128], comp_maskr[8][128];
185static u_int32_t old_rawkey0, old_rawkey1;
186
187static __inline int
188ascii_to_bin(ch)
189 char ch;
190{
191 if (ch > 'z')
192 return(0);
193 if (ch >= 'a')
194 return(ch - 'a' + 38);
195 if (ch > 'Z')
196 return(0);
197 if (ch >= 'A')
198 return(ch - 'A' + 12);
199 if (ch > '9')
200 return(0);
201 if (ch >= '.')
202 return(ch - '.');
203 return(0);
204}
205
206void
207des_init()
208{
209 int i, j, b, k, inbit, obit;
210 u_int32_t *p, *il, *ir, *fl, *fr;
211
212 old_rawkey0 = old_rawkey1 = 0;
213 saltbits = 0;
214 old_salt = 0;
215 bits24 = (bits28 = bits32 + 4) + 4;
216
217 /*
218 * Invert the S-boxes, reordering the input bits.
219 */
220 for (i = 0; i < 8; i++)
221 for (j = 0; j < 64; j++) {
222 b = (j & 0x20) | ((j & 1) << 4) | ((j >> 1) & 0xf);
223 u_sbox[i][j] = sbox[i][b];
224 }
225
226 /*
227 * Convert the inverted S-boxes into 4 arrays of 8 bits.
228 * Each will handle 12 bits of the S-box input.
229 */
230 for (b = 0; b < 4; b++)
231 for (i = 0; i < 64; i++)
232 for (j = 0; j < 64; j++)
233 m_sbox[b][(i << 6) | j] =
234 (u_sbox[(b << 1)][i] << 4) |
235 u_sbox[(b << 1) + 1][j];
236
237 /*
238 * Set up the initial & final permutations into a useful form, and
239 * initialise the inverted key permutation.
240 */
241 for (i = 0; i < 64; i++) {
242 init_perm[final_perm[i] = IP[i] - 1] = i;
243 inv_key_perm[i] = 255;
244 }
245
246 /*
247 * Invert the key permutation and initialise the inverted key
248 * compression permutation.
249 */
250 for (i = 0; i < 56; i++) {
251 u_key_perm[i] = key_perm[i] - 1;
252 inv_key_perm[key_perm[i] - 1] = i;
253 inv_comp_perm[i] = 255;
254 }
255
256 /*
257 * Invert the key compression permutation.
258 */
259 for (i = 0; i < 48; i++) {
260 inv_comp_perm[comp_perm[i] - 1] = i;
261 }
262
263 /*
264 * Set up the OR-mask arrays for the initial and final permutations,
265 * and for the key initial and compression permutations.
266 */
267 for (k = 0; k < 8; k++) {
268 for (i = 0; i < 256; i++) {
269 *(il = &ip_maskl[k][i]) = 0;
270 *(ir = &ip_maskr[k][i]) = 0;
271 *(fl = &fp_maskl[k][i]) = 0;
272 *(fr = &fp_maskr[k][i]) = 0;
273 for (j = 0; j < 8; j++) {
274 inbit = 8 * k + j;
275 if (i & bits8[j]) {
276 if ((obit = init_perm[inbit]) < 32)
277 *il |= bits32[obit];
278 else
279 *ir |= bits32[obit-32];
280 if ((obit = final_perm[inbit]) < 32)
281 *fl |= bits32[obit];
282 else
283 *fr |= bits32[obit - 32];
284 }
285 }
286 }
287 for (i = 0; i < 128; i++) {
288 *(il = &key_perm_maskl[k][i]) = 0;
289 *(ir = &key_perm_maskr[k][i]) = 0;
290 for (j = 0; j < 7; j++) {
291 inbit = 8 * k + j;
292 if (i & bits8[j + 1]) {
293 if ((obit = inv_key_perm[inbit]) == 255)
294 continue;
295 if (obit < 28)
296 *il |= bits28[obit];
297 else
298 *ir |= bits28[obit - 28];
299 }
300 }
301 *(il = &comp_maskl[k][i]) = 0;
302 *(ir = &comp_maskr[k][i]) = 0;
303 for (j = 0; j < 7; j++) {
304 inbit = 7 * k + j;
305 if (i & bits8[j + 1]) {
306 if ((obit=inv_comp_perm[inbit]) == 255)
307 continue;
308 if (obit < 24)
309 *il |= bits24[obit];
310 else
311 *ir |= bits24[obit - 24];
312 }
313 }
314 }
315 }
316
317 /*
318 * Invert the P-box permutation, and convert into OR-masks for
319 * handling the output of the S-box arrays setup above.
320 */
321 for (i = 0; i < 32; i++)
322 un_pbox[pbox[i] - 1] = i;
323
324 for (b = 0; b < 4; b++)
325 for (i = 0; i < 256; i++) {
326 *(p = &psbox[b][i]) = 0;
327 for (j = 0; j < 8; j++) {
328 if (i & bits8[j])
329 *p |= bits32[un_pbox[8 * b + j]];
330 }
331 }
332
333 des_initialised = 1;
334}
335
336void
337setup_salt(salt)
338 int32_t salt;
339{
340 u_int32_t obit, saltbit;
341 int i;
342
343 if (salt == old_salt)
344 return;
345 old_salt = salt;
346
347 saltbits = 0;
348 saltbit = 1;
349 obit = 0x800000;
350 for (i = 0; i < 24; i++) {
351 if (salt & saltbit)
352 saltbits |= obit;
353 saltbit <<= 1;
354 obit >>= 1;
355 }
356}
357
358int
359do_des(l_in, r_in, l_out, r_out, count)
360 u_int32_t l_in, r_in, *l_out, *r_out;
361 int count;
362{
363 /*
364 * l_in, r_in, l_out, and r_out are in pseudo-"big-endian" format.
365 */
366 u_int32_t l, r, *kl, *kr, *kl1, *kr1;
367 u_int32_t f, r48l, r48r;
368 int round;
369
370 if (count == 0) {
371 return(1);
372 } else if (count > 0) {
373 /*
374 * Encrypting
375 */
376 kl1 = en_keysl;
377 kr1 = en_keysr;
378 } else {
379 /*
380 * Decrypting
381 */
382 count = -count;
383 kl1 = de_keysl;
384 kr1 = de_keysr;
385 }
386
387 /*
388 * Do initial permutation (IP).
389 */
390 l = ip_maskl[0][l_in >> 24]
391 | ip_maskl[1][(l_in >> 16) & 0xff]
392 | ip_maskl[2][(l_in >> 8) & 0xff]
393 | ip_maskl[3][l_in & 0xff]
394 | ip_maskl[4][r_in >> 24]
395 | ip_maskl[5][(r_in >> 16) & 0xff]
396 | ip_maskl[6][(r_in >> 8) & 0xff]
397 | ip_maskl[7][r_in & 0xff];
398 r = ip_maskr[0][l_in >> 24]
399 | ip_maskr[1][(l_in >> 16) & 0xff]
400 | ip_maskr[2][(l_in >> 8) & 0xff]
401 | ip_maskr[3][l_in & 0xff]
402 | ip_maskr[4][r_in >> 24]
403 | ip_maskr[5][(r_in >> 16) & 0xff]
404 | ip_maskr[6][(r_in >> 8) & 0xff]
405 | ip_maskr[7][r_in & 0xff];
406
407 while (count--) {
408 /*
409 * Do each round.
410 */
411 kl = kl1;
412 kr = kr1;
413 round = 16;
414 while (round--) {
415 /*
416 * Expand R to 48 bits (simulate the E-box).
417 */
418 r48l = ((r & 0x00000001) << 23)
419 | ((r & 0xf8000000) >> 9)
420 | ((r & 0x1f800000) >> 11)
421 | ((r & 0x01f80000) >> 13)
422 | ((r & 0x001f8000) >> 15);
423
424 r48r = ((r & 0x0001f800) << 7)
425 | ((r & 0x00001f80) << 5)
426 | ((r & 0x000001f8) << 3)
427 | ((r & 0x0000001f) << 1)
428 | ((r & 0x80000000) >> 31);
429 /*
430 * Do salting for crypt() and friends, and
431 * XOR with the permuted key.
432 */
433 f = (r48l ^ r48r) & saltbits;
434 r48l ^= f ^ *kl++;
435 r48r ^= f ^ *kr++;
436 /*
437 * Do sbox lookups (which shrink it back to 32 bits)
438 * and do the pbox permutation at the same time.
439 */
440 f = psbox[0][m_sbox[0][r48l >> 12]]
441 | psbox[1][m_sbox[1][r48l & 0xfff]]
442 | psbox[2][m_sbox[2][r48r >> 12]]
443 | psbox[3][m_sbox[3][r48r & 0xfff]];
444 /*
445 * Now that we've permuted things, complete f().
446 */
447 f ^= l;
448 l = r;
449 r = f;
450 }
451 r = l;
452 l = f;
453 }
454 /*
455 * Do final permutation (inverse of IP).
456 */
457 *l_out = fp_maskl[0][l >> 24]
458 | fp_maskl[1][(l >> 16) & 0xff]
459 | fp_maskl[2][(l >> 8) & 0xff]
460 | fp_maskl[3][l & 0xff]
461 | fp_maskl[4][r >> 24]
462 | fp_maskl[5][(r >> 16) & 0xff]
463 | fp_maskl[6][(r >> 8) & 0xff]
464 | fp_maskl[7][r & 0xff];
465 *r_out = fp_maskr[0][l >> 24]
466 | fp_maskr[1][(l >> 16) & 0xff]
467 | fp_maskr[2][(l >> 8) & 0xff]
468 | fp_maskr[3][l & 0xff]
469 | fp_maskr[4][r >> 24]
470 | fp_maskr[5][(r >> 16) & 0xff]
471 | fp_maskr[6][(r >> 8) & 0xff]
472 | fp_maskr[7][r & 0xff];
473 return(0);
474}
475
476int
477des_cipher(in, out, salt, count)
478 const char *in;
479 char *out;
480 long salt;
481 int count;
482{
483 u_int32_t l_out, r_out, rawl, rawr;
484 u_int32_t x[2];
485 int retval;
486
487 if (!des_initialised)
488 des_init();
489
490 setup_salt((int32_t)salt);
491
492 memcpy(x, in, sizeof x);
493 rawl = ntohl(x[0]);
494 rawr = ntohl(x[1]);
495 retval = do_des(rawl, rawr, &l_out, &r_out, count);
496
497 x[0] = htonl(l_out);
498 x[1] = htonl(r_out);
499 memcpy(out, x, sizeof x);
500 return(retval);
501}
502
503int
504des_setkey(key)
505 const char *key;
506{
507 u_int32_t k0, k1, rawkey0, rawkey1;
508 int shifts, round;
509
510 if (!des_initialised)
511 des_init();
512
513 rawkey0 = ntohl(*(u_int32_t *) key);
514 rawkey1 = ntohl(*(u_int32_t *) (key + 4));
515
516 if ((rawkey0 | rawkey1)
517 && rawkey0 == old_rawkey0
518 && rawkey1 == old_rawkey1) {
519 /*
520 * Already setup for this key.
521 * This optimisation fails on a zero key (which is weak and
522 * has bad parity anyway) in order to simplify the starting
523 * conditions.
524 */
525 return(0);
526 }
527 old_rawkey0 = rawkey0;
528 old_rawkey1 = rawkey1;
529
530 /*
531 * Do key permutation and split into two 28-bit subkeys.
532 */
533 k0 = key_perm_maskl[0][rawkey0 >> 25]
534 | key_perm_maskl[1][(rawkey0 >> 17) & 0x7f]
535 | key_perm_maskl[2][(rawkey0 >> 9) & 0x7f]
536 | key_perm_maskl[3][(rawkey0 >> 1) & 0x7f]
537 | key_perm_maskl[4][rawkey1 >> 25]
538 | key_perm_maskl[5][(rawkey1 >> 17) & 0x7f]
539 | key_perm_maskl[6][(rawkey1 >> 9) & 0x7f]
540 | key_perm_maskl[7][(rawkey1 >> 1) & 0x7f];
541 k1 = key_perm_maskr[0][rawkey0 >> 25]
542 | key_perm_maskr[1][(rawkey0 >> 17) & 0x7f]
543 | key_perm_maskr[2][(rawkey0 >> 9) & 0x7f]
544 | key_perm_maskr[3][(rawkey0 >> 1) & 0x7f]
545 | key_perm_maskr[4][rawkey1 >> 25]
546 | key_perm_maskr[5][(rawkey1 >> 17) & 0x7f]
547 | key_perm_maskr[6][(rawkey1 >> 9) & 0x7f]
548 | key_perm_maskr[7][(rawkey1 >> 1) & 0x7f];
549 /*
550 * Rotate subkeys and do compression permutation.
551 */
552 shifts = 0;
553 for (round = 0; round < 16; round++) {
554 u_int32_t t0, t1;
555
556 shifts += key_shifts[round];
557
558 t0 = (k0 << shifts) | (k0 >> (28 - shifts));
559 t1 = (k1 << shifts) | (k1 >> (28 - shifts));
560
561 de_keysl[15 - round] =
562 en_keysl[round] = comp_maskl[0][(t0 >> 21) & 0x7f]
563 | comp_maskl[1][(t0 >> 14) & 0x7f]
564 | comp_maskl[2][(t0 >> 7) & 0x7f]
565 | comp_maskl[3][t0 & 0x7f]
566 | comp_maskl[4][(t1 >> 21) & 0x7f]
567 | comp_maskl[5][(t1 >> 14) & 0x7f]
568 | comp_maskl[6][(t1 >> 7) & 0x7f]
569 | comp_maskl[7][t1 & 0x7f];
570
571 de_keysr[15 - round] =
572 en_keysr[round] = comp_maskr[0][(t0 >> 21) & 0x7f]
573 | comp_maskr[1][(t0 >> 14) & 0x7f]
574 | comp_maskr[2][(t0 >> 7) & 0x7f]
575 | comp_maskr[3][t0 & 0x7f]
576 | comp_maskr[4][(t1 >> 21) & 0x7f]
577 | comp_maskr[5][(t1 >> 14) & 0x7f]
578 | comp_maskr[6][(t1 >> 7) & 0x7f]
579 | comp_maskr[7][t1 & 0x7f];
580 }
581 return(0);
582}
583
584int
585setkey(key)
586 const char *key;
587{
588 int i, j;
589 u_int32_t packed_keys[2];
590 u_char *p;
591
592 p = (u_char *) packed_keys;
593
594 for (i = 0; i < 8; i++) {
595 p[i] = 0;
596 for (j = 0; j < 8; j++)
597 if (*key++ & 1)
598 p[i] |= bits8[j];
599 }
600 return(des_setkey(p));
601}
602
603int
604encrypt(block, flag)
605 char *block;
606 int flag;
607{
608 u_int32_t io[2];
609 u_char *p;
610 int i, j, retval;
611
612 if (!des_initialised)
613 des_init();
614
615 setup_salt((int32_t)0);
616 p = (u_char *)block;
617 for (i = 0; i < 2; i++) {
618 io[i] = 0L;
619 for (j = 0; j < 32; j++)
620 if (*p++ & 1)
621 io[i] |= bits32[j];
622 }
623 retval = do_des(io[0], io[1], io, io + 1, flag ? -1 : 1);
624 for (i = 0; i < 2; i++)
625 for (j = 0; j < 32; j++)
626 block[(i << 5) | j] = (io[i] & bits32[j]) ? 1 : 0;
627 return(retval);
628}
diff --git a/src/lib/libc/crypt/skipjack.c b/src/lib/libc/crypt/skipjack.c
new file mode 100644
index 0000000000..e700f40c39
--- /dev/null
+++ b/src/lib/libc/crypt/skipjack.c
@@ -0,0 +1,258 @@
1/*
2 * Further optimized test implementation of SKIPJACK algorithm
3 * Mark Tillotson <markt@chaos.org.uk>, 25 June 98
4 * Optimizations suit RISC (lots of registers) machine best.
5 *
6 * based on unoptimized implementation of
7 * Panu Rissanen <bande@lut.fi> 960624
8 *
9 * SKIPJACK and KEA Algorithm Specifications
10 * Version 2.0
11 * 29 May 1998
12*/
13
14#include <sys/param.h>
15#include <skipjack.h>
16#include <stdlib.h>
17
18static const u_int8_t ftable[0x100] =
19{
20 0xa3, 0xd7, 0x09, 0x83, 0xf8, 0x48, 0xf6, 0xf4,
21 0xb3, 0x21, 0x15, 0x78, 0x99, 0xb1, 0xaf, 0xf9,
22 0xe7, 0x2d, 0x4d, 0x8a, 0xce, 0x4c, 0xca, 0x2e,
23 0x52, 0x95, 0xd9, 0x1e, 0x4e, 0x38, 0x44, 0x28,
24 0x0a, 0xdf, 0x02, 0xa0, 0x17, 0xf1, 0x60, 0x68,
25 0x12, 0xb7, 0x7a, 0xc3, 0xe9, 0xfa, 0x3d, 0x53,
26 0x96, 0x84, 0x6b, 0xba, 0xf2, 0x63, 0x9a, 0x19,
27 0x7c, 0xae, 0xe5, 0xf5, 0xf7, 0x16, 0x6a, 0xa2,
28 0x39, 0xb6, 0x7b, 0x0f, 0xc1, 0x93, 0x81, 0x1b,
29 0xee, 0xb4, 0x1a, 0xea, 0xd0, 0x91, 0x2f, 0xb8,
30 0x55, 0xb9, 0xda, 0x85, 0x3f, 0x41, 0xbf, 0xe0,
31 0x5a, 0x58, 0x80, 0x5f, 0x66, 0x0b, 0xd8, 0x90,
32 0x35, 0xd5, 0xc0, 0xa7, 0x33, 0x06, 0x65, 0x69,
33 0x45, 0x00, 0x94, 0x56, 0x6d, 0x98, 0x9b, 0x76,
34 0x97, 0xfc, 0xb2, 0xc2, 0xb0, 0xfe, 0xdb, 0x20,
35 0xe1, 0xeb, 0xd6, 0xe4, 0xdd, 0x47, 0x4a, 0x1d,
36 0x42, 0xed, 0x9e, 0x6e, 0x49, 0x3c, 0xcd, 0x43,
37 0x27, 0xd2, 0x07, 0xd4, 0xde, 0xc7, 0x67, 0x18,
38 0x89, 0xcb, 0x30, 0x1f, 0x8d, 0xc6, 0x8f, 0xaa,
39 0xc8, 0x74, 0xdc, 0xc9, 0x5d, 0x5c, 0x31, 0xa4,
40 0x70, 0x88, 0x61, 0x2c, 0x9f, 0x0d, 0x2b, 0x87,
41 0x50, 0x82, 0x54, 0x64, 0x26, 0x7d, 0x03, 0x40,
42 0x34, 0x4b, 0x1c, 0x73, 0xd1, 0xc4, 0xfd, 0x3b,
43 0xcc, 0xfb, 0x7f, 0xab, 0xe6, 0x3e, 0x5b, 0xa5,
44 0xad, 0x04, 0x23, 0x9c, 0x14, 0x51, 0x22, 0xf0,
45 0x29, 0x79, 0x71, 0x7e, 0xff, 0x8c, 0x0e, 0xe2,
46 0x0c, 0xef, 0xbc, 0x72, 0x75, 0x6f, 0x37, 0xa1,
47 0xec, 0xd3, 0x8e, 0x62, 0x8b, 0x86, 0x10, 0xe8,
48 0x08, 0x77, 0x11, 0xbe, 0x92, 0x4f, 0x24, 0xc5,
49 0x32, 0x36, 0x9d, 0xcf, 0xf3, 0xa6, 0xbb, 0xac,
50 0x5e, 0x6c, 0xa9, 0x13, 0x57, 0x25, 0xb5, 0xe3,
51 0xbd, 0xa8, 0x3a, 0x01, 0x05, 0x59, 0x2a, 0x46
52};
53
54/*
55 * For each key byte generate a table to represent the function
56 * ftable [in ^ keybyte]
57 *
58 * These tables used to save an XOR in each stage of the G-function
59 * the tables are hopefully pointed to by register allocated variables
60 * k0, k1..k9
61 */
62void
63subkey_table_gen (u_int8_t *key, u_int8_t **key_tables)
64{
65 int i, k;
66
67 for (k = 0; k < 10; k++) {
68 u_int8_t key_byte = key[k];
69 u_int8_t * table = (u_int8_t *) malloc(0x100);
70 /* XXX */
71
72 key_tables[k] = table;
73 for (i = 0; i < 0x100; i++)
74 table[i] = ftable[i ^ key_byte];
75 }
76}
77
78
79#define g(k0, k1, k2, k3, ih, il, oh, ol) \
80{ \
81 oh = k##k0 [il] ^ ih; \
82 ol = k##k1 [oh] ^ il; \
83 oh = k##k2 [ol] ^ oh; \
84 ol = k##k3 [oh] ^ ol; \
85}
86
87#define g0(ih, il, oh, ol) g(0, 1, 2, 3, ih, il, oh, ol)
88#define g4(ih, il, oh, ol) g(4, 5, 6, 7, ih, il, oh, ol)
89#define g8(ih, il, oh, ol) g(8, 9, 0, 1, ih, il, oh, ol)
90#define g2(ih, il, oh, ol) g(2, 3, 4, 5, ih, il, oh, ol)
91#define g6(ih, il, oh, ol) g(6, 7, 8, 9, ih, il, oh, ol)
92
93
94#define g_inv(k0, k1, k2, k3, ih, il, oh, ol) \
95{ \
96 ol = k##k3 [ih] ^ il; \
97 oh = k##k2 [ol] ^ ih; \
98 ol = k##k1 [oh] ^ ol; \
99 oh = k##k0 [ol] ^ oh; \
100}
101
102
103#define g0_inv(ih, il, oh, ol) g_inv(0, 1, 2, 3, ih, il, oh, ol)
104#define g4_inv(ih, il, oh, ol) g_inv(4, 5, 6, 7, ih, il, oh, ol)
105#define g8_inv(ih, il, oh, ol) g_inv(8, 9, 0, 1, ih, il, oh, ol)
106#define g2_inv(ih, il, oh, ol) g_inv(2, 3, 4, 5, ih, il, oh, ol)
107#define g6_inv(ih, il, oh, ol) g_inv(6, 7, 8, 9, ih, il, oh, ol)
108
109/* optimized version of Skipjack algorithm
110 *
111 * the appropriate g-function is inlined for each round
112 *
113 * the data movement is minimized by rotating the names of the
114 * variables w1..w4, not their contents (saves 3 moves per round)
115 *
116 * the loops are completely unrolled (needed to staticize choice of g)
117 *
118 * compiles to about 470 instructions on a Sparc (gcc -O)
119 * which is about 58 instructions per byte, 14 per round.
120 * gcc seems to leave in some unnecessary and with 0xFF operations
121 * but only in the latter part of the functions. Perhaps it
122 * runs out of resources to properly optimize long inlined function?
123 * in theory should get about 11 instructions per round, not 14
124 */
125
126void
127skipjack_forwards(u_int8_t *plain, u_int8_t *cipher, u_int8_t **key_tables)
128{
129 u_int8_t wh1 = plain[0]; u_int8_t wl1 = plain[1];
130 u_int8_t wh2 = plain[2]; u_int8_t wl2 = plain[3];
131 u_int8_t wh3 = plain[4]; u_int8_t wl3 = plain[5];
132 u_int8_t wh4 = plain[6]; u_int8_t wl4 = plain[7];
133
134 u_int8_t * k0 = key_tables [0];
135 u_int8_t * k1 = key_tables [1];
136 u_int8_t * k2 = key_tables [2];
137 u_int8_t * k3 = key_tables [3];
138 u_int8_t * k4 = key_tables [4];
139 u_int8_t * k5 = key_tables [5];
140 u_int8_t * k6 = key_tables [6];
141 u_int8_t * k7 = key_tables [7];
142 u_int8_t * k8 = key_tables [8];
143 u_int8_t * k9 = key_tables [9];
144
145 /* first 8 rounds */
146 g0 (wh1,wl1, wh1,wl1); wl4 ^= wl1 ^ 1; wh4 ^= wh1;
147 g4 (wh4,wl4, wh4,wl4); wl3 ^= wl4 ^ 2; wh3 ^= wh4;
148 g8 (wh3,wl3, wh3,wl3); wl2 ^= wl3 ^ 3; wh2 ^= wh3;
149 g2 (wh2,wl2, wh2,wl2); wl1 ^= wl2 ^ 4; wh1 ^= wh2;
150 g6 (wh1,wl1, wh1,wl1); wl4 ^= wl1 ^ 5; wh4 ^= wh1;
151 g0 (wh4,wl4, wh4,wl4); wl3 ^= wl4 ^ 6; wh3 ^= wh4;
152 g4 (wh3,wl3, wh3,wl3); wl2 ^= wl3 ^ 7; wh2 ^= wh3;
153 g8 (wh2,wl2, wh2,wl2); wl1 ^= wl2 ^ 8; wh1 ^= wh2;
154
155 /* second 8 rounds */
156 wh2 ^= wh1; wl2 ^= wl1 ^ 9 ; g2 (wh1,wl1, wh1,wl1);
157 wh1 ^= wh4; wl1 ^= wl4 ^ 10; g6 (wh4,wl4, wh4,wl4);
158 wh4 ^= wh3; wl4 ^= wl3 ^ 11; g0 (wh3,wl3, wh3,wl3);
159 wh3 ^= wh2; wl3 ^= wl2 ^ 12; g4 (wh2,wl2, wh2,wl2);
160 wh2 ^= wh1; wl2 ^= wl1 ^ 13; g8 (wh1,wl1, wh1,wl1);
161 wh1 ^= wh4; wl1 ^= wl4 ^ 14; g2 (wh4,wl4, wh4,wl4);
162 wh4 ^= wh3; wl4 ^= wl3 ^ 15; g6 (wh3,wl3, wh3,wl3);
163 wh3 ^= wh2; wl3 ^= wl2 ^ 16; g0 (wh2,wl2, wh2,wl2);
164
165 /* third 8 rounds */
166 g4 (wh1,wl1, wh1,wl1); wl4 ^= wl1 ^ 17; wh4 ^= wh1;
167 g8 (wh4,wl4, wh4,wl4); wl3 ^= wl4 ^ 18; wh3 ^= wh4;
168 g2 (wh3,wl3, wh3,wl3); wl2 ^= wl3 ^ 19; wh2 ^= wh3;
169 g6 (wh2,wl2, wh2,wl2); wl1 ^= wl2 ^ 20; wh1 ^= wh2;
170 g0 (wh1,wl1, wh1,wl1); wl4 ^= wl1 ^ 21; wh4 ^= wh1;
171 g4 (wh4,wl4, wh4,wl4); wl3 ^= wl4 ^ 22; wh3 ^= wh4;
172 g8 (wh3,wl3, wh3,wl3); wl2 ^= wl3 ^ 23; wh2 ^= wh3;
173 g2 (wh2,wl2, wh2,wl2); wl1 ^= wl2 ^ 24; wh1 ^= wh2;
174
175 /* last 8 rounds */
176 wh2 ^= wh1; wl2 ^= wl1 ^ 25; g6 (wh1,wl1, wh1,wl1);
177 wh1 ^= wh4; wl1 ^= wl4 ^ 26; g0 (wh4,wl4, wh4,wl4);
178 wh4 ^= wh3; wl4 ^= wl3 ^ 27; g4 (wh3,wl3, wh3,wl3);
179 wh3 ^= wh2; wl3 ^= wl2 ^ 28; g8 (wh2,wl2, wh2,wl2);
180 wh2 ^= wh1; wl2 ^= wl1 ^ 29; g2 (wh1,wl1, wh1,wl1);
181 wh1 ^= wh4; wl1 ^= wl4 ^ 30; g6 (wh4,wl4, wh4,wl4);
182 wh4 ^= wh3; wl4 ^= wl3 ^ 31; g0 (wh3,wl3, wh3,wl3);
183 wh3 ^= wh2; wl3 ^= wl2 ^ 32; g4 (wh2,wl2, wh2,wl2);
184
185 /* pack into byte vector */
186 cipher [0] = wh1; cipher [1] = wl1;
187 cipher [2] = wh2; cipher [3] = wl2;
188 cipher [4] = wh3; cipher [5] = wl3;
189 cipher [6] = wh4; cipher [7] = wl4;
190}
191
192
193void
194skipjack_backwards (u_int8_t *cipher, u_int8_t *plain, u_int8_t **key_tables)
195{
196 /* setup 4 16-bit portions */
197 u_int8_t wh1 = cipher[0]; u_int8_t wl1 = cipher[1];
198 u_int8_t wh2 = cipher[2]; u_int8_t wl2 = cipher[3];
199 u_int8_t wh3 = cipher[4]; u_int8_t wl3 = cipher[5];
200 u_int8_t wh4 = cipher[6]; u_int8_t wl4 = cipher[7];
201
202 u_int8_t * k0 = key_tables [0];
203 u_int8_t * k1 = key_tables [1];
204 u_int8_t * k2 = key_tables [2];
205 u_int8_t * k3 = key_tables [3];
206 u_int8_t * k4 = key_tables [4];
207 u_int8_t * k5 = key_tables [5];
208 u_int8_t * k6 = key_tables [6];
209 u_int8_t * k7 = key_tables [7];
210 u_int8_t * k8 = key_tables [8];
211 u_int8_t * k9 = key_tables [9];
212
213 /* first 8 rounds */
214 g4_inv (wh2,wl2, wh2,wl2); wl3 ^= wl2 ^ 32; wh3 ^= wh2;
215 g0_inv (wh3,wl3, wh3,wl3); wl4 ^= wl3 ^ 31; wh4 ^= wh3;
216 g6_inv (wh4,wl4, wh4,wl4); wl1 ^= wl4 ^ 30; wh1 ^= wh4;
217 g2_inv (wh1,wl1, wh1,wl1); wl2 ^= wl1 ^ 29; wh2 ^= wh1;
218 g8_inv (wh2,wl2, wh2,wl2); wl3 ^= wl2 ^ 28; wh3 ^= wh2;
219 g4_inv (wh3,wl3, wh3,wl3); wl4 ^= wl3 ^ 27; wh4 ^= wh3;
220 g0_inv (wh4,wl4, wh4,wl4); wl1 ^= wl4 ^ 26; wh1 ^= wh4;
221 g6_inv (wh1,wl1, wh1,wl1); wl2 ^= wl1 ^ 25; wh2 ^= wh1;
222
223 /* second 8 rounds */
224 wh1 ^= wh2; wl1 ^= wl2 ^ 24; g2_inv (wh2,wl2, wh2,wl2);
225 wh2 ^= wh3; wl2 ^= wl3 ^ 23; g8_inv (wh3,wl3, wh3,wl3);
226 wh3 ^= wh4; wl3 ^= wl4 ^ 22; g4_inv (wh4,wl4, wh4,wl4);
227 wh4 ^= wh1; wl4 ^= wl1 ^ 21; g0_inv (wh1,wl1, wh1,wl1);
228 wh1 ^= wh2; wl1 ^= wl2 ^ 20; g6_inv (wh2,wl2, wh2,wl2);
229 wh2 ^= wh3; wl2 ^= wl3 ^ 19; g2_inv (wh3,wl3, wh3,wl3);
230 wh3 ^= wh4; wl3 ^= wl4 ^ 18; g8_inv (wh4,wl4, wh4,wl4);
231 wh4 ^= wh1; wl4 ^= wl1 ^ 17; g4_inv (wh1,wl1, wh1,wl1);
232
233 /* third 8 rounds */
234 g0_inv (wh2,wl2, wh2,wl2); wl3 ^= wl2 ^ 16; wh3 ^= wh2;
235 g6_inv (wh3,wl3, wh3,wl3); wl4 ^= wl3 ^ 15; wh4 ^= wh3;
236 g2_inv (wh4,wl4, wh4,wl4); wl1 ^= wl4 ^ 14; wh1 ^= wh4;
237 g8_inv (wh1,wl1, wh1,wl1); wl2 ^= wl1 ^ 13; wh2 ^= wh1;
238 g4_inv (wh2,wl2, wh2,wl2); wl3 ^= wl2 ^ 12; wh3 ^= wh2;
239 g0_inv (wh3,wl3, wh3,wl3); wl4 ^= wl3 ^ 11; wh4 ^= wh3;
240 g6_inv (wh4,wl4, wh4,wl4); wl1 ^= wl4 ^ 10; wh1 ^= wh4;
241 g2_inv (wh1,wl1, wh1,wl1); wl2 ^= wl1 ^ 9; wh2 ^= wh1;
242
243 /* last 8 rounds */
244 wh1 ^= wh2; wl1 ^= wl2 ^ 8; g8_inv (wh2,wl2, wh2,wl2);
245 wh2 ^= wh3; wl2 ^= wl3 ^ 7; g4_inv (wh3,wl3, wh3,wl3);
246 wh3 ^= wh4; wl3 ^= wl4 ^ 6; g0_inv (wh4,wl4, wh4,wl4);
247 wh4 ^= wh1; wl4 ^= wl1 ^ 5; g6_inv (wh1,wl1, wh1,wl1);
248 wh1 ^= wh2; wl1 ^= wl2 ^ 4; g2_inv (wh2,wl2, wh2,wl2);
249 wh2 ^= wh3; wl2 ^= wl3 ^ 3; g8_inv (wh3,wl3, wh3,wl3);
250 wh3 ^= wh4; wl3 ^= wl4 ^ 2; g4_inv (wh4,wl4, wh4,wl4);
251 wh4 ^= wh1; wl4 ^= wl1 ^ 1; g0_inv (wh1,wl1, wh1,wl1);
252
253 /* pack into byte vector */
254 plain [0] = wh1; plain [1] = wl1;
255 plain [2] = wh2; plain [3] = wl2;
256 plain [4] = wh3; plain [5] = wl3;
257 plain [6] = wh4; plain [7] = wl4;
258}
diff --git a/src/lib/libc/include/namespace.h b/src/lib/libc/include/namespace.h
index 803657e006..4a51f15ddf 100644
--- a/src/lib/libc/include/namespace.h
+++ b/src/lib/libc/include/namespace.h
@@ -1,4 +1,4 @@
1/* $NetBSD: namespace.h,v 1.2 1995/02/27 13:02:12 cgd Exp $ */ 1/* $OpenBSD: namespace.h,v 1.2 1996/08/19 08:28:08 tholo Exp $ */
2 2
3#define catclose _catclose 3#define catclose _catclose
4#define catgets _catgets 4#define catgets _catgets
diff --git a/src/lib/libc/include/thread_private.h b/src/lib/libc/include/thread_private.h
new file mode 100644
index 0000000000..4212e7dcb2
--- /dev/null
+++ b/src/lib/libc/include/thread_private.h
@@ -0,0 +1,134 @@
1/* $OpenBSD: thread_private.h,v 1.15 2003/01/28 04:58:00 marc Exp $ */
2
3#ifndef _THREAD_PRIVATE_H_
4#define _THREAD_PRIVATE_H_
5
6#include <pthread.h>
7
8/*
9 * This variable is initially 0 when there is exactly one thread.
10 * It should never decrease.
11 */
12extern int __isthreaded;
13
14/*
15 * Weak symbols are used in libc so that the thread library can
16 * efficiently wrap libc functions.
17 *
18 * Use WEAK_NAME(n) to get a libc-private name for n (_weak_n),
19 * WEAK_ALIAS(n) to generate the weak symbol n pointing to _weak_n,
20 * WEAK_PROTOTYPE(n) to generate a prototype for _weak_n (based on n).
21 */
22#define WEAK_NAME(name) __CONCAT(_weak_,name)
23#define WEAK_ALIAS(name) __weak_alias(name, WEAK_NAME(name))
24#ifdef __GNUC__
25#define WEAK_PROTOTYPE(name) __typeof__(name) WEAK_NAME(name)
26#else
27#define WEAK_PROTOTYPE(name) /* typeof() only in gcc */
28#endif
29
30/*
31 * These macros help in making persistent storage thread-specific.
32 * Libc makes extensive use of private static data structures
33 * that hold state across function invocation, and these macros
34 * are no-ops when running single-threaded.
35 *
36 * Linking against the user-thread library causes these macros to
37 * allocate storage on a per-thread basis.
38 */
39
40#define __THREAD_MUTEX_NAME(name) __CONCAT(_libc_storage_mutex_,name)
41#define __THREAD_KEY_NAME(name) __CONCAT(_libc_storage_key_,name)
42
43struct _thread_private_key_struct {
44 pthread_once_t once;
45 void (*cleanfn)(void *);
46 pthread_key_t key;
47};
48
49void _libc_private_storage_lock(pthread_mutex_t *);
50void _libc_private_storage_unlock(pthread_mutex_t *);
51void * _libc_private_storage(volatile struct _thread_private_key_struct *,
52 void *, size_t, void *);
53
54/* Declare a module mutex. */
55#define _THREAD_PRIVATE_MUTEX(name) \
56 static pthread_mutex_t __THREAD_MUTEX_NAME(name) = \
57 PTHREAD_MUTEX_INITIALIZER
58
59/* Lock a module mutex against use by any other threads. */
60#define _THREAD_PRIVATE_MUTEX_LOCK(name) \
61 _libc_private_storage_lock(&__THREAD_MUTEX_NAME(name))
62
63/* Unlock a module mutex. */
64#define _THREAD_PRIVATE_MUTEX_UNLOCK(name) \
65 _libc_private_storage_unlock(&__THREAD_MUTEX_NAME(name))
66
67/* Declare a thread-private storage key. */
68#define _THREAD_PRIVATE_KEY(name) \
69 static volatile struct _thread_private_key_struct \
70 __THREAD_KEY_NAME(name) = { \
71 PTHREAD_ONCE_INIT, \
72 0 \
73 }
74
75/*
76 * In threaded mode, return a pointer to thread-private memory of
77 * the same size as, and (initially) with the same contents as 'storage'. If
78 * an error occurs, the 'error' parameter is returned.
79 * In single-threaded mode, no storage is allocated. Instead, a pointer
80 * to storage is always returned.
81 * The 'cleanfn' function of the key structure is called to free the storage.
82 * If 'cleanfn' is NULL, then free() is used. This hook can be useful for
83 * getting rid of memory leaks.
84 */
85#define _THREAD_PRIVATE(keyname, storage, error) \
86 _libc_private_storage(&__THREAD_KEY_NAME(keyname), \
87 &(storage), sizeof (storage), error)
88
89/*
90 * Keys used to access the per thread instances of resolver global data.
91 * These are not static as they are referenced in several places.
92 */
93extern volatile struct _thread_private_key_struct __THREAD_KEY_NAME(_res);
94#ifdef INET6
95extern volatile struct _thread_private_key_struct __THREAD_KEY_NAME(_res_ext);
96#endif
97
98/*
99 * File descriptor locking definitions.
100 */
101#define FD_READ 0x1
102#define FD_WRITE 0x2
103#define FD_RDWR (FD_READ | FD_WRITE)
104
105#define _FD_LOCK(_fd,_type,_ts) \
106 _thread_fd_lock(_fd, _type, _ts, __FILE__, __LINE__)
107#define _FD_UNLOCK(_fd,_type) \
108 _thread_fd_unlock(_fd, _type, __FILE__, __LINE__)
109
110int _thread_fd_lock(int, int, struct timespec *, const char *, int);
111void _thread_fd_unlock(int, int, const char *, int);
112
113/*
114 * malloc lock/unlock definitions
115 */
116# define _MALLOC_LOCK() do { \
117 if (__isthreaded) \
118 _thread_malloc_lock(); \
119 } while (0)
120# define _MALLOC_UNLOCK() do { \
121 if (__isthreaded) \
122 _thread_malloc_unlock();\
123 } while (0)
124# define _MALLOC_LOCK_INIT()do { \
125 if (__isthreaded) \
126 _thread_malloc_init();\
127 } while (0)
128
129
130void _thread_malloc_init(void);
131void _thread_malloc_lock(void);
132void _thread_malloc_unlock(void);
133
134#endif /* _THREAD_PRIVATE_H_ */
diff --git a/src/lib/libc/net/Makefile.inc b/src/lib/libc/net/Makefile.inc
index 2d220067e4..805ae5d224 100644
--- a/src/lib/libc/net/Makefile.inc
+++ b/src/lib/libc/net/Makefile.inc
@@ -1,46 +1,85 @@
1# $NetBSD: Makefile.inc,v 1.23 1995/03/02 09:09:07 chopps Exp $ 1# $OpenBSD: Makefile.inc,v 1.31 2001/08/06 14:40:47 jakob Exp $
2# @(#)Makefile.inc 8.2 (Berkeley) 9/5/93
3 2
4# net sources 3# net sources
5.PATH: ${.CURDIR}/arch/${MACHINE_ARCH}/net ${.CURDIR}/net 4.PATH: ${LIBCSRCDIR}/arch/${MACHINE_ARCH}/net ${LIBCSRCDIR}/net
6 5
7SRCS+= gethostnamadr.c getnetbyaddr.c getnetbyname.c getnetent.c \ 6CFLAGS+=-DRESOLVSORT
8 getproto.c getprotoent.c getprotoname.c getservbyname.c \ 7
9 getservbyport.c getservent.c herror.c inet_addr.c inet_lnaof.c \ 8SRCS+= base64.c freeaddrinfo.c gai_strerror.c getaddrinfo.c gethostnamadr.c \
10 inet_makeaddr.c inet_netof.c inet_network.c inet_ntoa.c \ 9 getifaddrs.c getnameinfo.c getnetbyaddr.c getnetbyname.c getnetent.c \
11 iso_addr.c linkaddr.c ns_addr.c ns_ntoa.c rcmd.c recv.c res_comp.c \ 10 getnetnamadr.c getproto.c getprotoent.c getprotoname.c \
12 res_debug.c res_init.c res_mkquery.c res_query.c res_send.c \ 11 getservbyname.c getservbyport.c getservent.c getrrsetbyname.c \
13 send.c sethostent.c ethers.c 12 herror.c if_indextoname.c if_nameindex.c if_nametoindex.c inet_addr.c \
13 inet_lnaof.c inet_makeaddr.c inet_neta.c inet_netof.c inet_network.c \
14 inet_net_ntop.c inet_net_pton.c inet_ntoa.c inet_ntop.c inet_pton.c \
15 ipx_addr.c ipx_ntoa.c iso_addr.c linkaddr.c ns_addr.c ns_ntoa.c \
16 nsap_addr.c \
17 net_addrcmp.c \
18 rcmd.c rresvport.c recv.c res_comp.c res_data.c res_debug.c \
19 res_init.c res_mkquery.c res_query.c res_random.c res_send.c send.c \
20 sethostent.c ethers.c rcmdsh.c
21
22# IPv6
23SRCS+= ip6opt.c rthdr.c vars6.c
14 24
15# machine-dependent net sources 25# machine-dependent net sources
16# m-d Makefile.inc must include sources for: 26# m-d Makefile.inc must include sources for:
17# htonl() htons() ntohl() ntohs() 27# htonl() htons() ntohl() ntohs()
18 28
19.include "${.CURDIR}/arch/${MACHINE_ARCH}/net/Makefile.inc" 29.include "${LIBCSRCDIR}/arch/${MACHINE_ARCH}/net/Makefile.inc"
20 30
21MAN+= byteorder.3 gethostbyname.3 getnetent.3 getprotoent.3 getservent.3 \ 31MAN+= byteorder.3 ethers.3 getaddrinfo.3 gethostbyname.3 getifaddrs.3 \
22 inet.3 linkaddr.3 ns.3 rcmd.3 resolver.3 ethers.3 32 getnameinfo.3 getnetent.3 getprotoent.3 getservent.3 inet.3 \
33 if_indextoname.3 inet_net.3 iso_addr.3 link_addr.3 ns.3 ipx.3 \
34 rcmd.3 rcmdsh.3 resolver.3 net_addrcmp.3 \
35 inet6_option_space.3 inet6_rthdr_space.3 \
36 getrrsetbyname.3
23 37
24MLINKS+=byteorder.3 htonl.3 byteorder.3 htons.3 byteorder.3 ntohl.3 \ 38MLINKS+=byteorder.3 htonl.3 byteorder.3 htons.3 byteorder.3 ntohl.3 \
25 byteorder.3 ntohs.3 39 byteorder.3 ntohs.3 byteorder.3 htobe16.3 byteorder.3 htobe32.3 \
40 byteorder.3 betoh16.3 byteorder.3 betoh32.3 byteorder.3 htole16.3 \
41 byteorder.3 htole32.3 byteorder.3 letoh16.3 byteorder.3 letoh32.3 \
42 byteorder.3 swap16.3 byteorder.3 swap32.3
26MLINKS+=ethers.3 ether_aton.3 ethers.3 ether_hostton.3 ethers.3 ether_line.3 \ 43MLINKS+=ethers.3 ether_aton.3 ethers.3 ether_hostton.3 ethers.3 ether_line.3 \
27 ethers.3 ether_ntoa.3 ethers.3 ether_ntohost.3 44 ethers.3 ether_ntoa.3 ethers.3 ether_ntohost.3 ethers.3 ether_addr.3
45MLINKS+= getaddrinfo.3 freeaddrinfo.3 getaddrinfo.3 gai_strerror.3
28MLINKS+=gethostbyname.3 endhostent.3 gethostbyname.3 gethostbyaddr.3 \ 46MLINKS+=gethostbyname.3 endhostent.3 gethostbyname.3 gethostbyaddr.3 \
29 gethostbyname.3 sethostent.3 gethostbyname.3 gethostent.3 \ 47 gethostbyname.3 sethostent.3 gethostbyname.3 gethostent.3 \
30 gethostbyname.3 herror.3 48 gethostbyname.3 herror.3 gethostbyname.3 gethostbyname2.3 \
49 gethostbyname.3 hstrerror.3
50MLINKS+=getifaddrs.3 freeifaddrs.3
31MLINKS+=getnetent.3 endnetent.3 getnetent.3 getnetbyaddr.3 \ 51MLINKS+=getnetent.3 endnetent.3 getnetent.3 getnetbyaddr.3 \
32 getnetent.3 getnetbyname.3 getnetent.3 setnetent.3 52 getnetent.3 getnetbyname.3 getnetent.3 setnetent.3
33MLINKS+=getprotoent.3 endprotoent.3 getprotoent.3 getprotobyname.3 \ 53MLINKS+=getprotoent.3 endprotoent.3 getprotoent.3 getprotobyname.3 \
34 getprotoent.3 getprotobynumber.3 getprotoent.3 setprotoent.3 54 getprotoent.3 getprotobynumber.3 getprotoent.3 setprotoent.3
35MLINKS+=getservent.3 endservent.3 getservent.3 getservbyname.3 \ 55MLINKS+=getservent.3 endservent.3 getservent.3 getservbyname.3 \
36 getservent.3 getservbyport.3 getservent.3 setservent.3 56 getservent.3 getservbyport.3 getservent.3 setservent.3
57MLINKS+= if_indextoname.3 if_nametoindex.3 if_indextoname.3 if_nameindex.3 \
58 if_indextoname.3 if_freenameindex.3
37MLINKS+=inet.3 addr.3 inet.3 inet_addr.3 inet.3 inet_aton.3 \ 59MLINKS+=inet.3 addr.3 inet.3 inet_addr.3 inet.3 inet_aton.3 \
38 inet.3 inet_lnaof.3 inet.3 inet_makeaddr.3 inet.3 inet_netof.3 \ 60 inet.3 inet_lnaof.3 inet.3 inet_makeaddr.3 inet.3 inet_netof.3 \
39 inet.3 inet_network.3 inet.3 inet_ntoa.3 inet.3 network.3 \ 61 inet.3 inet_network.3 inet.3 inet_ntoa.3 inet.3 network.3 \
40 inet.3 ntoa.3 62 inet.3 ntoa.3 inet.3 inet_ntop.3 inet.3 inet_pton.3
41MLINKS+=linkaddr.3 linkntoa.3 63MLINKS+=inet_net.3 inet_net_ntop.3 inet_net.3 inet_net_pton.3
64MLINKS+=iso_addr.3 iso_ntoa.3
65MLINKS+=link_addr.3 link_ntoa.3
66MLINKS+=ipx.3 ipx_addr.3 ipx.3 ipx_ntoa.3
42MLINKS+=ns.3 ns_addr.3 ns.3 ns_ntoa.3 67MLINKS+=ns.3 ns_addr.3 ns.3 ns_ntoa.3
43MLINKS+=rcmd.3 iruserok.3 rcmd.3 rresvport.3 rcmd.3 ruserok.3 68MLINKS+=rcmd.3 iruserok.3 rcmd.3 rresvport.3 rcmd.3 ruserok.3 \
69 rcmd.3 rresvport_af.3 rcmd.3 rcmd_af.3 rcmd.3 iruserok_sa.3
44MLINKS+=resolver.3 dn_comp.3 resolver.3 dn_expand.3 resolver.3 res_init.3 \ 70MLINKS+=resolver.3 dn_comp.3 resolver.3 dn_expand.3 resolver.3 res_init.3 \
45 resolver.3 res_mkquery.3 resolver.3 res_send.3 resolver.3 res_query.3 \ 71 resolver.3 res_mkquery.3 resolver.3 res_send.3 resolver.3 res_query.3 \
46 resolver.3 res_search.3 72 resolver.3 res_search.3
73MLINKS+=inet6_option_space.3 inet6_option_init.3 \
74 inet6_option_space.3 inet6_option_append.3 \
75 inet6_option_space.3 inet6_option_alloc.3 \
76 inet6_option_space.3 inet6_option_next.3 \
77 inet6_option_space.3 inet6_option_find.3
78MLINKS+=inet6_rthdr_space.3 inet6_rthdr_init.3 \
79 inet6_rthdr_space.3 inet6_rthdr_add.3 \
80 inet6_rthdr_space.3 inet6_rthdr_lasthop.3 \
81 inet6_rthdr_space.3 inet6_rthdr_reverse.3 \
82 inet6_rthdr_space.3 inet6_rthdr_segments.3 \
83 inet6_rthdr_space.3 inet6_rthdr_getaddr.3 \
84 inet6_rthdr_space.3 inet6_rthdr_getflags.3
85MLINKS+=getrrsetbyname.3 freerrset.3
diff --git a/src/lib/libc/net/base64.c b/src/lib/libc/net/base64.c
new file mode 100644
index 0000000000..33b6ffdc41
--- /dev/null
+++ b/src/lib/libc/net/base64.c
@@ -0,0 +1,318 @@
1/* $OpenBSD: base64.c,v 1.4 2002/01/02 23:00:10 deraadt Exp $ */
2
3/*
4 * Copyright (c) 1996 by Internet Software Consortium.
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
11 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
12 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
13 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
16 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
17 * SOFTWARE.
18 */
19
20/*
21 * Portions Copyright (c) 1995 by International Business Machines, Inc.
22 *
23 * International Business Machines, Inc. (hereinafter called IBM) grants
24 * permission under its copyrights to use, copy, modify, and distribute this
25 * Software with or without fee, provided that the above copyright notice and
26 * all paragraphs of this notice appear in all copies, and that the name of IBM
27 * not be used in connection with the marketing of any product incorporating
28 * the Software or modifications thereof, without specific, written prior
29 * permission.
30 *
31 * To the extent it has a right to do so, IBM grants an immunity from suit
32 * under its patents, if any, for the use, sale or manufacture of products to
33 * the extent that such products are used for performing Domain Name System
34 * dynamic updates in TCP/IP networks by means of the Software. No immunity is
35 * granted for any product per se or for any other function of any product.
36 *
37 * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
38 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
39 * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
40 * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
41 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
42 * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
43 */
44
45#include <sys/types.h>
46#include <sys/param.h>
47#include <sys/socket.h>
48#include <netinet/in.h>
49#include <arpa/inet.h>
50#include <arpa/nameser.h>
51
52#include <ctype.h>
53#include <resolv.h>
54#include <stdio.h>
55
56#include <stdlib.h>
57#include <string.h>
58
59/* XXX abort illegal in library */
60#define Assert(Cond) if (!(Cond)) abort()
61
62static const char Base64[] =
63 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
64static const char Pad64 = '=';
65
66/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
67 The following encoding technique is taken from RFC 1521 by Borenstein
68 and Freed. It is reproduced here in a slightly edited form for
69 convenience.
70
71 A 65-character subset of US-ASCII is used, enabling 6 bits to be
72 represented per printable character. (The extra 65th character, "=",
73 is used to signify a special processing function.)
74
75 The encoding process represents 24-bit groups of input bits as output
76 strings of 4 encoded characters. Proceeding from left to right, a
77 24-bit input group is formed by concatenating 3 8-bit input groups.
78 These 24 bits are then treated as 4 concatenated 6-bit groups, each
79 of which is translated into a single digit in the base64 alphabet.
80
81 Each 6-bit group is used as an index into an array of 64 printable
82 characters. The character referenced by the index is placed in the
83 output string.
84
85 Table 1: The Base64 Alphabet
86
87 Value Encoding Value Encoding Value Encoding Value Encoding
88 0 A 17 R 34 i 51 z
89 1 B 18 S 35 j 52 0
90 2 C 19 T 36 k 53 1
91 3 D 20 U 37 l 54 2
92 4 E 21 V 38 m 55 3
93 5 F 22 W 39 n 56 4
94 6 G 23 X 40 o 57 5
95 7 H 24 Y 41 p 58 6
96 8 I 25 Z 42 q 59 7
97 9 J 26 a 43 r 60 8
98 10 K 27 b 44 s 61 9
99 11 L 28 c 45 t 62 +
100 12 M 29 d 46 u 63 /
101 13 N 30 e 47 v
102 14 O 31 f 48 w (pad) =
103 15 P 32 g 49 x
104 16 Q 33 h 50 y
105
106 Special processing is performed if fewer than 24 bits are available
107 at the end of the data being encoded. A full encoding quantum is
108 always completed at the end of a quantity. When fewer than 24 input
109 bits are available in an input group, zero bits are added (on the
110 right) to form an integral number of 6-bit groups. Padding at the
111 end of the data is performed using the '=' character.
112
113 Since all base64 input is an integral number of octets, only the
114 -------------------------------------------------
115 following cases can arise:
116
117 (1) the final quantum of encoding input is an integral
118 multiple of 24 bits; here, the final unit of encoded
119 output will be an integral multiple of 4 characters
120 with no "=" padding,
121 (2) the final quantum of encoding input is exactly 8 bits;
122 here, the final unit of encoded output will be two
123 characters followed by two "=" padding characters, or
124 (3) the final quantum of encoding input is exactly 16 bits;
125 here, the final unit of encoded output will be three
126 characters followed by one "=" padding character.
127 */
128
129int
130b64_ntop(src, srclength, target, targsize)
131 u_char const *src;
132 size_t srclength;
133 char *target;
134 size_t targsize;
135{
136 size_t datalength = 0;
137 u_char input[3];
138 u_char output[4];
139 int i;
140
141 while (2 < srclength) {
142 input[0] = *src++;
143 input[1] = *src++;
144 input[2] = *src++;
145 srclength -= 3;
146
147 output[0] = input[0] >> 2;
148 output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
149 output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
150 output[3] = input[2] & 0x3f;
151 Assert(output[0] < 64);
152 Assert(output[1] < 64);
153 Assert(output[2] < 64);
154 Assert(output[3] < 64);
155
156 if (datalength + 4 > targsize)
157 return (-1);
158 target[datalength++] = Base64[output[0]];
159 target[datalength++] = Base64[output[1]];
160 target[datalength++] = Base64[output[2]];
161 target[datalength++] = Base64[output[3]];
162 }
163
164 /* Now we worry about padding. */
165 if (0 != srclength) {
166 /* Get what's left. */
167 input[0] = input[1] = input[2] = '\0';
168 for (i = 0; i < srclength; i++)
169 input[i] = *src++;
170
171 output[0] = input[0] >> 2;
172 output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
173 output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
174 Assert(output[0] < 64);
175 Assert(output[1] < 64);
176 Assert(output[2] < 64);
177
178 if (datalength + 4 > targsize)
179 return (-1);
180 target[datalength++] = Base64[output[0]];
181 target[datalength++] = Base64[output[1]];
182 if (srclength == 1)
183 target[datalength++] = Pad64;
184 else
185 target[datalength++] = Base64[output[2]];
186 target[datalength++] = Pad64;
187 }
188 if (datalength >= targsize)
189 return (-1);
190 target[datalength] = '\0'; /* Returned value doesn't count \0. */
191 return (datalength);
192}
193
194/* skips all whitespace anywhere.
195 converts characters, four at a time, starting at (or after)
196 src from base - 64 numbers into three 8 bit bytes in the target area.
197 it returns the number of data bytes stored at the target, or -1 on error.
198 */
199
200int
201b64_pton(src, target, targsize)
202 char const *src;
203 u_char *target;
204 size_t targsize;
205{
206 int tarindex, state, ch;
207 char *pos;
208
209 state = 0;
210 tarindex = 0;
211
212 while ((ch = *src++) != '\0') {
213 if (isspace(ch)) /* Skip whitespace anywhere. */
214 continue;
215
216 if (ch == Pad64)
217 break;
218
219 pos = strchr(Base64, ch);
220 if (pos == 0) /* A non-base64 character. */
221 return (-1);
222
223 switch (state) {
224 case 0:
225 if (target) {
226 if (tarindex >= targsize)
227 return (-1);
228 target[tarindex] = (pos - Base64) << 2;
229 }
230 state = 1;
231 break;
232 case 1:
233 if (target) {
234 if (tarindex + 1 >= targsize)
235 return (-1);
236 target[tarindex] |= (pos - Base64) >> 4;
237 target[tarindex+1] = ((pos - Base64) & 0x0f)
238 << 4 ;
239 }
240 tarindex++;
241 state = 2;
242 break;
243 case 2:
244 if (target) {
245 if (tarindex + 1 >= targsize)
246 return (-1);
247 target[tarindex] |= (pos - Base64) >> 2;
248 target[tarindex+1] = ((pos - Base64) & 0x03)
249 << 6;
250 }
251 tarindex++;
252 state = 3;
253 break;
254 case 3:
255 if (target) {
256 if (tarindex >= targsize)
257 return (-1);
258 target[tarindex] |= (pos - Base64);
259 }
260 tarindex++;
261 state = 0;
262 break;
263 }
264 }
265
266 /*
267 * We are done decoding Base-64 chars. Let's see if we ended
268 * on a byte boundary, and/or with erroneous trailing characters.
269 */
270
271 if (ch == Pad64) { /* We got a pad char. */
272 ch = *src++; /* Skip it, get next. */
273 switch (state) {
274 case 0: /* Invalid = in first position */
275 case 1: /* Invalid = in second position */
276 return (-1);
277
278 case 2: /* Valid, means one byte of info */
279 /* Skip any number of spaces. */
280 for (; ch != '\0'; ch = *src++)
281 if (!isspace(ch))
282 break;
283 /* Make sure there is another trailing = sign. */
284 if (ch != Pad64)
285 return (-1);
286 ch = *src++; /* Skip the = */
287 /* Fall through to "single trailing =" case. */
288 /* FALLTHROUGH */
289
290 case 3: /* Valid, means two bytes of info */
291 /*
292 * We know this char is an =. Is there anything but
293 * whitespace after it?
294 */
295 for (; ch != '\0'; ch = *src++)
296 if (!isspace(ch))
297 return (-1);
298
299 /*
300 * Now make sure for cases 2 and 3 that the "extra"
301 * bits that slopped past the last full byte were
302 * zeros. If we don't check them, they become a
303 * subliminal channel.
304 */
305 if (target && target[tarindex] != 0)
306 return (-1);
307 }
308 } else {
309 /*
310 * We ended by seeing the end of the string. Make sure we
311 * have no partial bytes lying around.
312 */
313 if (state != 0)
314 return (-1);
315 }
316
317 return (tarindex);
318}
diff --git a/src/lib/libc/net/byteorder.3 b/src/lib/libc/net/byteorder.3
index 701a69f688..9d8fa7221f 100644
--- a/src/lib/libc/net/byteorder.3
+++ b/src/lib/libc/net/byteorder.3
@@ -1,4 +1,4 @@
1.\" $NetBSD: byteorder.3,v 1.3 1995/02/25 06:20:27 cgd Exp $ 1.\" $OpenBSD: byteorder.3,v 1.8 2000/04/18 03:01:30 aaron Exp $
2.\" 2.\"
3.\" Copyright (c) 1983, 1991, 1993 3.\" Copyright (c) 1983, 1991, 1993
4.\" The Regents of the University of California. All rights reserved. 4.\" The Regents of the University of California. All rights reserved.
@@ -31,35 +31,141 @@
31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32.\" SUCH DAMAGE. 32.\" SUCH DAMAGE.
33.\" 33.\"
34.\" @(#)byteorder.3 8.1 (Berkeley) 6/4/93
35.\"
36.Dd June 4, 1993 34.Dd June 4, 1993
37.Dt BYTEORDER 3 35.Dt BYTEORDER 3
38.Os BSD 4.2 36.Os
39.Sh NAME 37.Sh NAME
40.Nm htonl , 38.Nm htonl ,
41.Nm htons , 39.Nm htons ,
42.Nm ntohl , 40.Nm ntohl ,
43.Nm ntohs 41.Nm ntohs ,
44.Nd convert values between host and network byte order 42.Nm htobe32 ,
43.Nm htobe16 ,
44.Nm betoh32 ,
45.Nm betoh16 ,
46.Nm htole32 ,
47.Nm htole16 ,
48.Nm letoh32 ,
49.Nm letoh16 ,
50.Nm swap32 ,
51.Nm swap16
52.Nd convert values between different byte orderings
45.Sh SYNOPSIS 53.Sh SYNOPSIS
46.Fd #include <sys/param.h> 54.Fd #include <sys/types.h>
47.Ft u_long 55.Fd #include <machine/endian.h>
48.Fn htonl "u_long hostlong" 56.Ft u_int32_t
49.Ft u_short 57.Fn htonl "u_int32_t host32"
50.Fn htons "u_short hostshort" 58.Ft u_int16_t
51.Ft u_long 59.Fn htons "u_int16_t host16"
52.Fn ntohl "u_long netlong" 60.Ft u_int32_t
53.Ft u_short 61.Fn ntohl "u_int32_t net32"
54.Fn ntohs "u_short netshort" 62.Ft u_int16_t
63.Fn ntohs "u_int16_t net16"
64.Ft u_int32_t
65.Fn htobe32 "u_int32_t host32"
66.Ft u_int16_t
67.Fn htobe16 "u_int16_t host16"
68.Ft u_int32_t
69.Fn betoh32 "u_int32_t big32"
70.Ft u_int16_t
71.Fn betoh16 "u_int16_t big16"
72.Ft u_int32_t
73.Fn htole32 "u_int32_t host32"
74.Ft u_int16_t
75.Fn htole16 "u_int16_t host16"
76.Ft u_int32_t
77.Fn letoh32 "u_int32_t little32"
78.Ft u_int16_t
79.Fn letoh16 "u_int16_t little16"
80.Ft u_int32_t
81.Fn swap32 "u_int32_t val32"
82.Ft u_int16_t
83.Fn swap16 "u_int16_t val16"
55.Sh DESCRIPTION 84.Sh DESCRIPTION
56These routines convert 16 and 32 bit quantities between network 85These routines convert 16- and 32-bit quantities between different
86byte orderings.
87The
88.Dq swap
89functions reverse the byte ordering of
90the given quantity, the others converts either from/to the native
91byte order used by the host to/from either little- or big-endian (a.k.a
92network) order.
93.Pp
94Apart from the swap functions, the names can be described by this form:
95{src-order}to{dst-order}{size}.
96Both {src-order} and {dst-order} can take the following forms:
97.Pp
98.Bl -tag -width "be " -offset indent -compact
99.It h
100Host order.
101.It n
102Network order (big-endian).
103.It be
104Big-endian (most significant byte first).
105.It le
106Little-endian (least significant byte first).
107.El
108.Pp
109One of the specified orderings must be
110.Sq h .
111{size} will take these forms:
112.Pp
113.Bl -tag -width "32 " -offset indent -compact
114.It l
115Long (32-bit, used in conjunction with forms involving
116.Sq n ) .
117.It s
118Short (16-bit, used in conjunction with forms involving
119.Sq n ) .
120.It 16
12116-bit.
122.It 32
12332-bit.
124.El
125.Pp
126The swap functions are of the form: swap{size}.
127.Pp
128Names involving
129.Sq n
130convert quantities between network
57byte order and host byte order. 131byte order and host byte order.
132The last letter
133.Pf ( Sq s
134or
135.Sq l )
136is a mnemonic
137for the traditional names for such quantities,
138.Li short
139and
140.Li long ,
141respectively.
142Today, the C concept of
143.Li short
144and
145.Li long
146integers need not coincide with this traditional misunderstanding.
58On machines which have a byte order which is the same as the network 147On machines which have a byte order which is the same as the network
59order, routines are defined as null macros. 148order, routines are defined as null macros.
60.Pp 149.Pp
61These routines are most often used in conjunction with Internet 150The functions involving either
62addresses and ports as returned by 151.Dq be ,
152.Dq le ,
153or
154.Dq swap
155use the numbers
15616 and 32 for specifying the bitwidth of the quantities they operate on.
157Currently all supported architectures are either big- or little-endian
158so either the
159.Dq be
160or
161.Dq le
162variants are implemented as null macros.
163.Pp
164The routines mentioned above which have either {src-order} or {dst-order}
165set to
166.Sq n
167are most often used in
168conjunction with Internet addresses and ports as returned by
63.Xr gethostbyname 3 169.Xr gethostbyname 3
64and 170and
65.Xr getservent 3 . 171.Xr getservent 3 .
@@ -69,10 +175,9 @@ and
69.Sh HISTORY 175.Sh HISTORY
70The 176The
71.Nm byteorder 177.Nm byteorder
72functions appeared in 178functions appeared in
73.Bx 4.2 . 179.Bx 4.2 .
74.Sh BUGS 180.Sh BUGS
75On the 181On the vax, alpha, i386, and so far mips,
76.Tn VAX 182bytes are handled backwards from most everyone else in the world.
77bytes are handled backwards from most everyone else in 183This is not expected to be fixed in the near future.
78the world. This is not expected to be fixed in the near future.
diff --git a/src/lib/libc/net/ethers.3 b/src/lib/libc/net/ethers.3
index 81e6c65935..0509c121b8 100644
--- a/src/lib/libc/net/ethers.3
+++ b/src/lib/libc/net/ethers.3
@@ -1,15 +1,17 @@
1.\" $OpenBSD: ethers.3,v 1.14 2001/08/06 10:42:26 mpech Exp $
1.\" 2.\"
2.\" Written by roland@frob.com. Public domain. 3.\" Written by roland@frob.com. Public domain.
3.\" 4.\"
4.Dd December 16, 1993 5.Dd December 16, 1993
5.Dt ETHERS 3 6.Dt ETHERS 3
6.Os NetBSD 7.Os
7.Sh NAME 8.Sh NAME
9.Nm ether_aton ,
8.Nm ether_ntoa , 10.Nm ether_ntoa ,
9.Nm ether_addr , 11.Nm ether_addr ,
10.Nm ether_ntohost , 12.Nm ether_ntohost ,
11.Nm ether_hostton , 13.Nm ether_hostton ,
12.Nm ether_line , 14.Nm ether_line
13.Nd get ethers entry 15.Nd get ethers entry
14.Sh SYNOPSIS 16.Sh SYNOPSIS
15.Fd #include <netinet/if_ether.h> 17.Fd #include <netinet/if_ether.h>
@@ -17,49 +19,64 @@
17.Fn ether_ntoa "struct ether_addr *e" 19.Fn ether_ntoa "struct ether_addr *e"
18.Ft struct ether_addr * 20.Ft struct ether_addr *
19.Fn ether_aton "char *s" 21.Fn ether_aton "char *s"
22.Ft int
20.Fn ether_ntohost "char *hostname" "struct ether_addr *e" 23.Fn ether_ntohost "char *hostname" "struct ether_addr *e"
24.Ft int
21.Fn ether_hostton "char *hostname" "struct ether_addr *e" 25.Fn ether_hostton "char *hostname" "struct ether_addr *e"
26.Ft int
22.Fn ether_line "char *l" "struct ether_addr *e" "char *hostname" 27.Fn ether_line "char *l" "struct ether_addr *e" "char *hostname"
23.Sh DESCRIPTION 28.Sh DESCRIPTION
24Ethernet addresses are represented by the 29Ethernet addresses are represented by the
25following structure: 30following structure:
26.Bd -literal -offset indent 31.Bd -literal -offset indent
27struct ether_addr { 32struct ether_addr {
28 u_char ether_addr_octet[6]; 33 u_int8_t ether_addr_octet[6];
29}; 34};
30.Ed 35.Ed
31.Pp 36.Pp
32The 37The
33.Fn ether_ntoa 38.Fn ether_ntoa
34function converts this structure into an ASCII string of the form 39function converts this structure into an
35``xx:xx:xx:xx:xx:xx'', consisting of 6 hexadecimal numbers separated 40.Tn ASCII
36by colons. It returns a pointer to a static buffer that is reused for 41string of the form
37each call. 42.Dq xx:xx:xx:xx:xx:xx ,
43consisting of 6 hexadecimal numbers separated
44by colons.
45It returns a pointer to a static buffer that is reused for each call.
38The 46The
39.Fn ether_aton 47.Fn ether_aton
40converts an ASCII string of the same form and to a structure 48converts an
41containing the 6 octets of the address. It returns a pointer to a 49.Tn ASCII
42static structure that is reused for each call. 50string of the same form and to a structure
51containing the 6 octets of the address.
52It returns a pointer to a static structure that is reused for each call.
43.Pp 53.Pp
44The 54The
45.Fn ether_ntohost 55.Fn ether_ntohost
46and 56and
47.Fn ether_hostton 57.Fn ether_hostton
48functions interrogate the data base mapping host names to Ethernet 58functions interrogate the database mapping host names to Ethernet
49addresses, 59addresses,
50.Pa /etc/ethers . 60.Pa /etc/ethers .
51The 61The
52.Fn ether_ntohost 62.Fn ether_ntohost
53function looks up the given Ethernet address and writes the associated 63function looks up the given Ethernet address and writes the associated
54host name into the character buffer passed. 64host name into the character buffer passed.
65This buffer should be
66.Dv MAXHOSTNAMELEN
67characters in size.
55The 68The
56.Fn ether_hostton 69.Fn ether_hostton
57function looks up the given host name and writes the associated 70function looks up the given host name and writes the associated
58Ethernet address into the structure passed. Both functions return 71Ethernet address into the structure passed.
59zero if they find the requested host name or address, and -1 if not. 72Both functions return
73zero if they find the requested host name or address, and \-1 if not.
74.Pp
60Each call reads 75Each call reads
61.Pa /etc/ethers 76.Pa /etc/ethers
62from the beginning; if a + appears alone on a line in the file, then 77from the beginning; if a
78.Ql +
79appears alone on a line in the file, then
63.Fn ether_hostton 80.Fn ether_hostton
64will consult the 81will consult the
65.Pa ethers.byname 82.Pa ethers.byname
@@ -73,9 +90,13 @@ The
73.Fn ether_line 90.Fn ether_line
74function parses a line from the 91function parses a line from the
75.Pa /etc/ethers 92.Pa /etc/ethers
76file and fills in the passed ``struct ether_addr'' and character 93file and fills in the passed
77buffer with the Ethernet address and host name on the line. It 94.Li struct ether_addr
78returns zero if the line was successfully parsed and -1 if not. 95and character buffer with the Ethernet address and host name on the line.
96It returns zero if the line was successfully parsed and \-1 if not.
97The character buffer should be
98.Dv MAXHOSTNAMELEN
99characters in size.
79.Sh FILES 100.Sh FILES
80.Bl -tag -width /etc/ethers -compact 101.Bl -tag -width /etc/ethers -compact
81.It Pa /etc/ethers 102.It Pa /etc/ethers
@@ -91,12 +112,8 @@ The
91and 112and
92.Fn ether_line 113.Fn ether_line
93functions were adopted from SunOS and appeared in 114functions were adopted from SunOS and appeared in
94NetBSD 0.9b. 115.Nx 0.9 b.
95.Sh BUGS 116.Sh BUGS
96The data space used by these functions is static; if future use 117The data space used by these functions is static; if future use
97requires the data, it should be copied before any subsequent calls to 118requires the data, it should be copied before any subsequent calls to
98these functions overwrite it. There is no way to restrict how many 119these functions overwrite it.
99character will be written into the host name buffer passed. A very
100long line in
101.Pa /etc/ethers
102could overflow your buffer.
diff --git a/src/lib/libc/net/ethers.c b/src/lib/libc/net/ethers.c
index 0f32b9b71b..858ac5b3f3 100644
--- a/src/lib/libc/net/ethers.c
+++ b/src/lib/libc/net/ethers.c
@@ -1,12 +1,42 @@
1/* $NetBSD: ethers.c,v 1.5 1995/02/25 06:20:28 cgd Exp $ */ 1/* $OpenBSD: ethers.c,v 1.14 2002/05/24 21:22:37 deraadt Exp $ */
2 2
3/* 3/*
4 * ethers(3N) a la Sun. 4 * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
5 * 17 *
6 * Written by Roland McGrath <roland@frob.com> 10/14/93. 18 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
7 * Public domain. 19 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
20 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
27 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/*
31 * ethers(3) a la Sun.
32 * Originally Written by Roland McGrath <roland@frob.com> 10/14/93.
33 * Substantially modified by Todd C. Miller <Todd.Miller@courtesan.com>
8 */ 34 */
9 35
36#if defined(LIBC_SCCS) && !defined(lint)
37static char rcsid[] = "$OpenBSD: ethers.c,v 1.14 2002/05/24 21:22:37 deraadt Exp $";
38#endif /* LIBC_SCCS and not lint */
39
10#include <sys/types.h> 40#include <sys/types.h>
11#include <sys/socket.h> 41#include <sys/socket.h>
12#include <net/if.h> 42#include <net/if.h>
@@ -18,22 +48,63 @@
18#include <stdio.h> 48#include <stdio.h>
19#include <stdlib.h> 49#include <stdlib.h>
20#include <string.h> 50#include <string.h>
51#include <ctype.h>
52#ifdef YP
53#include <rpcsvc/ypclnt.h>
54#endif
21 55
22#ifndef _PATH_ETHERS 56#ifndef _PATH_ETHERS
23#define _PATH_ETHERS "/etc/ethers" 57#define _PATH_ETHERS "/etc/ethers"
24#endif 58#endif
25 59
60static char * _ether_aton(char *, struct ether_addr *);
61
26char * 62char *
27ether_ntoa(e) 63ether_ntoa(e)
28 struct ether_addr *e; 64 struct ether_addr *e;
29{ 65{
30 static char a[] = "xx:xx:xx:xx:xx:xx"; 66 static char a[] = "xx:xx:xx:xx:xx:xx";
31 67
32 sprintf(a, "%02x:%02x:%02x:%02x:%02x:%02x", 68 if (e->ether_addr_octet[0] > 0xFF || e->ether_addr_octet[1] > 0xFF ||
69 e->ether_addr_octet[2] > 0xFF || e->ether_addr_octet[3] > 0xFF ||
70 e->ether_addr_octet[4] > 0xFF || e->ether_addr_octet[5] > 0xFF) {
71 errno = EINVAL;
72 return (NULL);
73 }
74
75 (void)snprintf(a, sizeof a, "%02x:%02x:%02x:%02x:%02x:%02x",
33 e->ether_addr_octet[0], e->ether_addr_octet[1], 76 e->ether_addr_octet[0], e->ether_addr_octet[1],
34 e->ether_addr_octet[2], e->ether_addr_octet[3], 77 e->ether_addr_octet[2], e->ether_addr_octet[3],
35 e->ether_addr_octet[4], e->ether_addr_octet[5]); 78 e->ether_addr_octet[4], e->ether_addr_octet[5]);
36 return a; 79
80 return (a);
81}
82
83static char *
84_ether_aton(s, e)
85 char *s;
86 struct ether_addr *e;
87{
88 int i;
89 long l;
90 char *pp;
91
92 while (isspace(*s))
93 s++;
94
95 /* expect 6 hex octets separated by ':' or space/NUL if last octet */
96 for (i = 0; i < 6; i++) {
97 l = strtol(s, &pp, 16);
98 if (pp == s || l > 0xFF || l < 0)
99 return (NULL);
100 if (!(*pp == ':' || (i == 5 && (isspace(*pp) || *pp == '\0'))))
101 return (NULL);
102 e->ether_addr_octet[i] = (u_char)l;
103 s = pp + 1;
104 }
105
106 /* return character after the octets ala strtol(3) */
107 return (pp);
37} 108}
38 109
39struct ether_addr * 110struct ether_addr *
@@ -41,34 +112,33 @@ ether_aton(s)
41 char *s; 112 char *s;
42{ 113{
43 static struct ether_addr n; 114 static struct ether_addr n;
44 u_int i[6]; 115
45 116 return (_ether_aton(s, &n) ? &n : NULL);
46 if (sscanf(s, " %x:%x:%x:%x:%x:%x ", &i[0], &i[1],
47 &i[2], &i[3], &i[4], &i[5]) == 6) {
48 n.ether_addr_octet[0] = (u_char)i[0];
49 n.ether_addr_octet[1] = (u_char)i[1];
50 n.ether_addr_octet[2] = (u_char)i[2];
51 n.ether_addr_octet[3] = (u_char)i[3];
52 n.ether_addr_octet[4] = (u_char)i[4];
53 n.ether_addr_octet[5] = (u_char)i[5];
54 return &n;
55 }
56 return NULL;
57} 117}
58 118
119int
59ether_ntohost(hostname, e) 120ether_ntohost(hostname, e)
60 char *hostname; 121 char *hostname;
61 struct ether_addr *e; 122 struct ether_addr *e;
62{ 123{
63 FILE *f; 124 FILE *f;
64 char buf[BUFSIZ]; 125 char buf[BUFSIZ+1], *p;
126 size_t len;
65 struct ether_addr try; 127 struct ether_addr try;
66
67#ifdef YP 128#ifdef YP
68 char trybuf[sizeof "xx:xx:xx:xx:xx:xx"]; 129 char trybuf[sizeof("xx:xx:xx:xx:xx:xx")];
69 int trylen; 130 int trylen;
131#endif
132
133 if (e->ether_addr_octet[0] > 0xFF || e->ether_addr_octet[1] > 0xFF ||
134 e->ether_addr_octet[2] > 0xFF || e->ether_addr_octet[3] > 0xFF ||
135 e->ether_addr_octet[4] > 0xFF || e->ether_addr_octet[5] > 0xFF) {
136 errno = EINVAL;
137 return (-1);
138 }
70 139
71 sprintf(trybuf, "%x:%x:%x:%x:%x:%x", 140#ifdef YP
141 snprintf(trybuf, sizeof trybuf, "%x:%x:%x:%x:%x:%x",
72 e->ether_addr_octet[0], e->ether_addr_octet[1], 142 e->ether_addr_octet[0], e->ether_addr_octet[1],
73 e->ether_addr_octet[2], e->ether_addr_octet[3], 143 e->ether_addr_octet[2], e->ether_addr_octet[3],
74 e->ether_addr_octet[4], e->ether_addr_octet[5]); 144 e->ether_addr_octet[4], e->ether_addr_octet[5]);
@@ -76,12 +146,19 @@ ether_ntohost(hostname, e)
76#endif 146#endif
77 147
78 f = fopen(_PATH_ETHERS, "r"); 148 f = fopen(_PATH_ETHERS, "r");
79 if (f==NULL) 149 if (f == NULL)
80 return -1; 150 return (-1);
81 while (fgets(buf, sizeof buf, f)) { 151 while ((p = fgetln(f, &len)) != NULL) {
152 if (p[len-1] == '\n')
153 len--;
154 if (len > sizeof(buf) - 2)
155 continue;
156 (void)memcpy(buf, p, len);
157 buf[len] = '\n'; /* code assumes newlines later on */
158 buf[len+1] = '\0';
82#ifdef YP 159#ifdef YP
83 /* A + in the file means try YP now. */ 160 /* A + in the file means try YP now. */
84 if (!strncmp(buf, "+\n", sizeof buf)) { 161 if (!strncmp(buf, "+\n", sizeof(buf))) {
85 char *ypbuf, *ypdom; 162 char *ypbuf, *ypdom;
86 int ypbuflen; 163 int ypbuflen;
87 164
@@ -93,42 +170,51 @@ ether_ntohost(hostname, e)
93 if (ether_line(ypbuf, &try, hostname) == 0) { 170 if (ether_line(ypbuf, &try, hostname) == 0) {
94 free(ypbuf); 171 free(ypbuf);
95 (void)fclose(f); 172 (void)fclose(f);
96 return 0; 173 return (0);
97 } 174 }
98 free(ypbuf); 175 free(ypbuf);
99 continue; 176 continue;
100 } 177 }
101#endif 178#endif
102 if (ether_line(buf, &try, hostname) == 0 && 179 if (ether_line(buf, &try, hostname) == 0 &&
103 bcmp((char *)&try, (char *)e, sizeof try) == 0) { 180 memcmp((void *)&try, (void *)e, sizeof(try)) == 0) {
104 (void)fclose(f); 181 (void)fclose(f);
105 return 0; 182 return (0);
106 } 183 }
107 } 184 }
108 (void)fclose(f); 185 (void)fclose(f);
109 errno = ENOENT; 186 errno = ENOENT;
110 return -1; 187 return (-1);
111} 188}
112 189
190int
113ether_hostton(hostname, e) 191ether_hostton(hostname, e)
114 char *hostname; 192 char *hostname;
115 struct ether_addr *e; 193 struct ether_addr *e;
116{ 194{
117 FILE *f; 195 FILE *f;
118 char buf[BUFSIZ]; 196 char buf[BUFSIZ+1], *p;
119 char try[MAXHOSTNAMELEN]; 197 char try[MAXHOSTNAMELEN];
198 size_t len;
120#ifdef YP 199#ifdef YP
121 int hostlen = strlen(hostname); 200 int hostlen = strlen(hostname);
122#endif 201#endif
123 202
124 f = fopen(_PATH_ETHERS, "r"); 203 f = fopen(_PATH_ETHERS, "r");
125 if (f==NULL) 204 if (f==NULL)
126 return -1; 205 return (-1);
127 206
128 while (fgets(buf, sizeof buf, f)) { 207 while ((p = fgetln(f, &len)) != NULL) {
208 if (p[len-1] == '\n')
209 len--;
210 if (len > sizeof(buf) - 2)
211 continue;
212 memcpy(buf, p, len);
213 buf[len] = '\n'; /* code assumes newlines later on */
214 buf[len+1] = '\0';
129#ifdef YP 215#ifdef YP
130 /* A + in the file means try YP now. */ 216 /* A + in the file means try YP now. */
131 if (!strncmp(buf, "+\n", sizeof buf)) { 217 if (!strncmp(buf, "+\n", sizeof(buf))) {
132 char *ypbuf, *ypdom; 218 char *ypbuf, *ypdom;
133 int ypbuflen; 219 int ypbuflen;
134 220
@@ -140,7 +226,7 @@ ether_hostton(hostname, e)
140 if (ether_line(ypbuf, e, try) == 0) { 226 if (ether_line(ypbuf, e, try) == 0) {
141 free(ypbuf); 227 free(ypbuf);
142 (void)fclose(f); 228 (void)fclose(f);
143 return 0; 229 return (0);
144 } 230 }
145 free(ypbuf); 231 free(ypbuf);
146 continue; 232 continue;
@@ -148,31 +234,39 @@ ether_hostton(hostname, e)
148#endif 234#endif
149 if (ether_line(buf, e, try) == 0 && strcmp(hostname, try) == 0) { 235 if (ether_line(buf, e, try) == 0 && strcmp(hostname, try) == 0) {
150 (void)fclose(f); 236 (void)fclose(f);
151 return 0; 237 return (0);
152 } 238 }
153 } 239 }
154 (void)fclose(f); 240 (void)fclose(f);
155 errno = ENOENT; 241 errno = ENOENT;
156 return -1; 242 return (-1);
157} 243}
158 244
159ether_line(l, e, hostname) 245int
160 char *l; 246ether_line(line, e, hostname)
247 char *line;
161 struct ether_addr *e; 248 struct ether_addr *e;
162 char *hostname; 249 char *hostname;
163{ 250{
164 u_int i[6]; 251 char *p;
165 252 size_t n;
166 if (sscanf(l, " %x:%x:%x:%x:%x:%x %s\n", &i[0], &i[1], 253
167 &i[2], &i[3], &i[4], &i[5], hostname) == 7) { 254 /* Parse "xx:xx:xx:xx:xx:xx" */
168 e->ether_addr_octet[0] = (u_char)i[0]; 255 if ((p = _ether_aton(line, e)) == NULL || (*p != ' ' && *p != '\t'))
169 e->ether_addr_octet[1] = (u_char)i[1]; 256 goto bad;
170 e->ether_addr_octet[2] = (u_char)i[2]; 257
171 e->ether_addr_octet[3] = (u_char)i[3]; 258 /* Now get the hostname */
172 e->ether_addr_octet[4] = (u_char)i[4]; 259 while (isspace(*p))
173 e->ether_addr_octet[5] = (u_char)i[5]; 260 p++;
174 return 0; 261 if (*p == '\0')
175 } 262 goto bad;
263 n = strcspn(p, " \t\n");
264 if (n >= MAXHOSTNAMELEN)
265 goto bad;
266 strlcpy(hostname, p, n + 1);
267 return (0);
268
269bad:
176 errno = EINVAL; 270 errno = EINVAL;
177 return -1; 271 return (-1);
178} 272}
diff --git a/src/lib/libc/net/freeaddrinfo.c b/src/lib/libc/net/freeaddrinfo.c
new file mode 100644
index 0000000000..30fbecb805
--- /dev/null
+++ b/src/lib/libc/net/freeaddrinfo.c
@@ -0,0 +1,49 @@
1/*
2 * Copyright (c) 1996, 1997, 1998, 1999, Craig Metz, All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. All advertising materials mentioning features or use of this software
13 * must display the following acknowledgement:
14 * This product includes software developed by Craig Metz and
15 * by other contributors.
16 * 4. Neither the name of the author nor the names of contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#include <stdlib.h>
34#include <netdb.h>
35
36void
37freeaddrinfo(ai)
38 struct addrinfo *ai;
39{
40 struct addrinfo *p;
41
42 do {
43 p = ai;
44 ai = ai->ai_next;
45 if (p->ai_canonname)
46 free(p->ai_canonname);
47 free((void *)p);
48 } while (ai);
49}
diff --git a/src/lib/libc/net/gai_strerror.c b/src/lib/libc/net/gai_strerror.c
new file mode 100644
index 0000000000..a191cb5b28
--- /dev/null
+++ b/src/lib/libc/net/gai_strerror.c
@@ -0,0 +1,76 @@
1/* $OpenBSD: gai_strerror.c,v 1.5 2001/06/05 02:31:34 deraadt Exp $ */
2
3/*
4 * Copyright (c) 1997-1999, Craig Metz, All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by Craig Metz and
17 * by other contributors.
18 * 4. Neither the name of the author nor the names of contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35/* gai_strerror() v1.38 */
36
37#include <sys/types.h>
38#include <netdb.h>
39#include <errno.h>
40
41char *
42gai_strerror(int errnum)
43{
44 switch (errnum) {
45 case 0:
46 return "no error";
47 case EAI_BADFLAGS:
48 return "invalid value for ai_flags";
49 case EAI_NONAME:
50 return "name or service is not known";
51 case EAI_AGAIN:
52 return "temporary failure in name resolution";
53 case EAI_FAIL:
54 return "non-recoverable failure in name resolution";
55 case EAI_NODATA:
56 return "no address associated with name";
57 case EAI_FAMILY:
58 return "ai_family not supported";
59 case EAI_SOCKTYPE:
60 return "ai_socktype not supported";
61 case EAI_SERVICE:
62 return "service not supported for ai_socktype";
63 case EAI_ADDRFAMILY:
64 return "address family for name not supported";
65 case EAI_MEMORY:
66 return "memory allocation failure";
67 case EAI_SYSTEM:
68 return "system error";
69 case EAI_BADHINTS:
70 return "invalid value for hints";
71 case EAI_PROTOCOL:
72 return "resolved protocol is unknown";
73 default:
74 return "unknown/invalid error";
75 }
76}
diff --git a/src/lib/libc/net/getaddrinfo.3 b/src/lib/libc/net/getaddrinfo.3
new file mode 100644
index 0000000000..12b5500436
--- /dev/null
+++ b/src/lib/libc/net/getaddrinfo.3
@@ -0,0 +1,581 @@
1.\" $OpenBSD: getaddrinfo.3,v 1.21 2003/05/01 19:10:09 jmc Exp $
2.\" $KAME: getaddrinfo.3,v 1.29 2001/02/12 09:24:45 itojun Exp $
3.\"
4.\" Copyright (c) 1983, 1987, 1991, 1993
5.\" The Regents of the University of California. All rights reserved.
6.\"
7.\" Redistribution and use in source and binary forms, with or without
8.\" modification, are permitted provided that the following conditions
9.\" are met:
10.\" 1. Redistributions of source code must retain the above copyright
11.\" notice, this list of conditions and the following disclaimer.
12.\" 2. Redistributions in binary form must reproduce the above copyright
13.\" notice, this list of conditions and the following disclaimer in the
14.\" documentation and/or other materials provided with the distribution.
15.\" 3. All advertising materials mentioning features or use of this software
16.\" must display the following acknowledgement:
17.\" This product includes software developed by the University of
18.\" California, Berkeley and its contributors.
19.\" 4. Neither the name of the University nor the names of its contributors
20.\" may be used to endorse or promote products derived from this software
21.\" without specific prior written permission.
22.\"
23.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33.\" SUCH DAMAGE.
34.\"
35.\" From: @(#)gethostbyname.3 8.4 (Berkeley) 5/25/95
36.\"
37.Dd May 25, 1995
38.Dt GETADDRINFO 3
39.Os
40.\"
41.Sh NAME
42.Nm getaddrinfo ,
43.Nm freeaddrinfo ,
44.Nm gai_strerror
45.Nd nodename-to-address translation in protocol-independent manner
46.\"
47.Sh SYNOPSIS
48.Fd #include <sys/types.h>
49.Fd #include <sys/socket.h>
50.Fd #include <netdb.h>
51.Ft int
52.Fn getaddrinfo "const char *nodename" "const char *servname" \
53"const struct addrinfo *hints" "struct addrinfo **res"
54.Ft void
55.Fn freeaddrinfo "struct addrinfo *ai"
56.Ft "char *"
57.Fn gai_strerror "int ecode"
58.\"
59.Sh DESCRIPTION
60The
61.Fn getaddrinfo
62function is defined for protocol-independent nodename-to-address translation.
63It performs the functionality of
64.Xr gethostbyname 3
65and
66.Xr getservbyname 3 ,
67but in a more sophisticated manner.
68.Pp
69The
70.Li addrinfo
71structure is defined as a result of including the
72.Aq Pa netdb.h
73header:
74.Bd -literal -offset
75struct addrinfo { *
76 int ai_flags; /* AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST */
77 int ai_family; /* PF_xxx */
78 int ai_socktype; /* SOCK_xxx */
79 int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
80 size_t ai_addrlen; /* length of ai_addr */
81 char *ai_canonname; /* canonical name for nodename */
82 struct sockaddr *ai_addr; /* binary address */
83 struct addrinfo *ai_next; /* next structure in linked list */
84};
85.Ed
86.Pp
87The
88.Fa nodename
89and
90.Fa servname
91arguments are pointers to NUL-terminated strings or
92.Dv NULL .
93One or both of these two arguments must be a non-null pointer.
94In the normal client scenario, both the
95.Fa nodename
96and
97.Fa servname
98are specified.
99In the normal server scenario, only the
100.Fa servname
101is specified.
102A non-null
103.Fa nodename
104string can be either a node name or a numeric host address string
105(i.e., a dotted-decimal IPv4 address or an IPv6 hex address).
106A non-null
107.Fa servname
108string can be either a service name or a decimal port number.
109.Pp
110The caller can optionally pass an
111.Li addrinfo
112structure, pointed to by the third argument,
113to provide hints concerning the type of socket that the caller supports.
114In this
115.Fa hints
116structure all members other than
117.Fa ai_flags ,
118.Fa ai_family ,
119.Fa ai_socktype ,
120and
121.Fa ai_protocol
122must be zero or a null pointer.
123A value of
124.Dv PF_UNSPEC
125for
126.Fa ai_family
127means the caller will accept any protocol family.
128A value of 0 for
129.Fa ai_socktype
130means the caller will accept any socket type.
131A value of 0 for
132.Fa ai_protocol
133means the caller will accept any protocol.
134For example, if the caller handles only TCP and not UDP, then the
135.Fa ai_socktype
136member of the hints structure should be set to
137.Dv SOCK_STREAM
138when
139.Fn getaddrinfo
140is called.
141If the caller handles only IPv4 and not IPv6, then the
142.Fa ai_family
143member of the
144.Fa hints
145structure should be set to
146.Dv PF_INET
147when
148.Fn getaddrinfo
149is called.
150If the third argument to
151.Fn getaddrinfo
152is a null pointer, this is the same as if the caller had filled in an
153.Li addrinfo
154structure initialized to zero with
155.Fa ai_family
156set to
157.Dv PF_UNSPEC .
158.Pp
159Upon successful return a pointer to a linked list of one or more
160.Li addrinfo
161structures is returned through the final argument.
162The caller can process each
163.Li addrinfo
164structure in this list by following the
165.Fa ai_next
166pointer, until a null pointer is encountered.
167In each returned
168.Li addrinfo
169structure the three members
170.Fa ai_family ,
171.Fa ai_socktype ,
172and
173.Fa ai_protocol
174are the corresponding arguments for a call to the
175.Fn socket
176function.
177In each
178.Li addrinfo
179structure the
180.Fa ai_addr
181member points to a filled-in socket address structure whose length is
182specified by the
183.Fa ai_addrlen
184member.
185.Pp
186If the
187.Dv AI_PASSIVE
188bit is set in the
189.Fa ai_flags
190member of the
191.Fa hints
192structure, then the caller plans to use the returned socket address
193structure in a call to
194.Fn bind .
195In this case, if the
196.Fa nodename
197argument is a null pointer, then the IP address portion of the socket
198address structure will be set to
199.Dv INADDR_ANY
200for an IPv4 address or
201.Dv IN6ADDR_ANY_INIT
202for an IPv6 address.
203.Pp
204If the
205.Dv AI_PASSIVE
206bit is not set in the
207.Fa ai_flags
208member of the
209.Fa hints
210structure, then the returned socket address structure will be ready for a
211call to
212.Fn connect
213.Pq for a connection-oriented protocol
214or either
215.Fn connect ,
216.Fn sendto ,
217or
218.Fn sendmsg
219.Pq for a connectionless protocol .
220In this case, if the
221.Fa nodename
222argument is a null pointer, then the IP address portion of the
223socket address structure will be set to the loopback address.
224.Pp
225If the
226.Dv AI_CANONNAME
227bit is set in the
228.Fa ai_flags
229member of the
230.Fa hints
231structure, then upon successful return the
232.Fa ai_canonname
233member of the first
234.Li addrinfo
235structure in the linked list will point to a NUL-terminated string
236containing the canonical name of the specified
237.Fa nodename .
238.Pp
239If the
240.Dv AI_NUMERICHOST
241bit is set in the
242.Fa ai_flags
243member of the
244.Fa hints
245structure, then a non-null
246.Fa nodename
247string must be a numeric host address string.
248Otherwise an error of
249.Dv EAI_NONAME
250is returned.
251This flag prevents any type of name resolution service (e.g., the DNS)
252from being called.
253.Pp
254The arguments to
255.Fn getaddrinfo
256must sufficiently be consistent and unambiguous.
257Here are pitfall cases you may encounter:
258.Bl -bullet
259.It
260.Fn getaddrinfo
261will raise an error if members of the
262.Fa hints
263structure are not consistent.
264For example, for internet address families,
265.Fn getaddrinfo
266will raise an error if you specify
267.Dv SOCK_STREAM
268to
269.Fa ai_socktype
270while you specify
271.Dv IPPROTO_UDP
272to
273.Fa ai_protocol .
274.It
275If you specify a
276.Fa servname
277which is defined only for certain
278.Fa ai_socktype ,
279.Fn getaddrinfo
280will raise an error because the arguments are not consistent.
281For example,
282.Fn getaddrinfo
283will raise an error if you ask for
284.Dq Li tftp
285service on
286.Dv SOCK_STREAM .
287.It
288For internet address families, if you specify
289.Fa servname
290while you set
291.Fa ai_socktype
292to
293.Dv SOCK_RAW ,
294.Fn getaddrinfo
295will raise an error, because service names are not defined for the internet
296.Dv SOCK_RAW
297space.
298.It
299If you specify a numeric
300.Fa servname ,
301while leaving
302.Fa ai_socktype
303and
304.Fa ai_protocol
305unspecified,
306.Fn getaddrinfo
307will raise an error.
308This is because the numeric
309.Fa servname
310does not identify any socket type, and
311.Fn getaddrinfo
312is not allowed to glob the argument in such case.
313.El
314.Pp
315All of the information returned by
316.Fn getaddrinfo
317is dynamically allocated:
318the
319.Li addrinfo
320structures, the socket address structures, and canonical node name
321strings pointed to by the addrinfo structures.
322To return this information to the system the function
323.Fn freeaddrinfo
324is called.
325The
326.Fa addrinfo
327structure pointed to by the
328.Fa ai argument
329is freed, along with any dynamic storage pointed to by the structure.
330This operation is repeated until a
331.Dv NULL
332.Fa ai_next
333pointer is encountered.
334.Pp
335To aid applications in printing error messages based on the
336.Dv EAI_xxx
337codes returned by
338.Fn getaddrinfo ,
339.Fn gai_strerror
340is defined.
341The argument is one of the
342.Dv EAI_xxx
343values defined earlier and the return value points to a string describing
344the error.
345If the argument is not one of the
346.Dv EAI_xxx
347values, the function still returns a pointer to a string whose contents
348indicate an unknown error.
349.\"
350.Ss Extension for scoped IPv6 address
351The implementation allows experimental numeric IPv6 address notation with
352scope identifier.
353By appending the percent character and scope identifier to addresses,
354you can fill the
355.Li sin6_scope_id
356field for addresses.
357This would make management of scoped address easier,
358and allows cut-and-paste input of scoped address.
359.Pp
360At this moment the code supports only link-local addresses with the format.
361Scope identifier is hardcoded to the name of the hardware interface associated
362with the link.
363.Po
364such as
365.Li ne0
366.Pc .
367An example is
368.Dq Li fe80::1%ne0 ,
369which means
370.Do
371.Li fe80::1
372on the link associated with the
373.Li ne0
374interface
375.Dc .
376.Pp
377The implementation is still very experimental and non-standard.
378The current implementation assumes a one-to-one relationship between
379the interface and link, which is not necessarily true from the specification.
380.\"
381.Sh EXAMPLES
382The following code tries to connect to
383.Dq Li www.kame.net
384service
385.Dq Li http .
386via stream socket.
387It loops through all the addresses available, regardless of address family.
388If the destination resolves to an IPv4 address, it will use
389.Dv AF_INET
390socket.
391Similarly, if it resolves to IPv6,
392.Dv AF_INET6
393socket is used.
394Observe that there is no hardcoded reference to a particular address family.
395The code works even if
396.Nm getaddrinfo
397returns addresses that are not IPv4/v6.
398.Bd -literal -offset indent
399struct addrinfo hints, *res, *res0;
400int error;
401int s;
402const char *cause = NULL;
403
404memset(&hints, 0, sizeof(hints));
405hints.ai_family = PF_UNSPEC;
406hints.ai_socktype = SOCK_STREAM;
407error = getaddrinfo("www.kame.net", "http", &hints, &res0);
408if (error) {
409 errx(1, "%s", gai_strerror(error));
410 /*NOTREACHED*/
411}
412s = -1;
413for (res = res0; res; res = res->ai_next) {
414 s = socket(res->ai_family, res->ai_socktype,
415 res->ai_protocol);
416 if (s < 0) {
417 cause = "socket";
418 continue;
419 }
420
421 if (connect(s, res->ai_addr, res->ai_addrlen) < 0) {
422 cause = "connect";
423 close(s);
424 s = -1;
425 continue;
426 }
427
428 break; /* okay we got one */
429}
430if (s < 0) {
431 err(1, cause);
432 /*NOTREACHED*/
433}
434freeaddrinfo(res0);
435.Ed
436.Pp
437The following example tries to open a wildcard listening socket onto service
438.Dq Li http ,
439for all the address families available.
440.Bd -literal -offset indent
441struct addrinfo hints, *res, *res0;
442int error;
443int s[MAXSOCK];
444int nsock;
445const char *cause = NULL;
446
447memset(&hints, 0, sizeof(hints));
448hints.ai_family = PF_UNSPEC;
449hints.ai_socktype = SOCK_STREAM;
450hints.ai_flags = AI_PASSIVE;
451error = getaddrinfo(NULL, "http", &hints, &res0);
452if (error) {
453 errx(1, "%s", gai_strerror(error));
454 /*NOTREACHED*/
455}
456nsock = 0;
457for (res = res0; res && nsock < MAXSOCK; res = res->ai_next) {
458 s[nsock] = socket(res->ai_family, res->ai_socktype,
459 res->ai_protocol);
460 if (s[nsock] < 0) {
461 cause = "socket";
462 continue;
463 }
464
465 if (bind(s[nsock], res->ai_addr, res->ai_addrlen) < 0) {
466 cause = "bind";
467 close(s[nsock]);
468 continue;
469 }
470 (void) listen(s[nsock], 5);
471
472 nsock++;
473}
474if (nsock == 0) {
475 err(1, cause);
476 /*NOTREACHED*/
477}
478freeaddrinfo(res0);
479.Ed
480.\"
481.Sh DIAGNOSTICS
482Error return status from
483.Fn getaddrinfo
484is zero on success and non-zero on errors.
485Non-zero error codes are defined in
486.Aq Pa netdb.h ,
487and as follows:
488.Pp
489.Bl -tag -width EAI_ADDRFAMILY -compact
490.It Dv EAI_ADDRFAMILY
491Address family for
492.Fa nodename
493not supported.
494.It Dv EAI_AGAIN
495Temporary failure in name resolution.
496.It Dv EAI_BADFLAGS
497Invalid value for
498.Fa ai_flags .
499.It Dv EAI_FAIL
500Non-recoverable failure in name resolution.
501.It Dv EAI_FAMILY
502.Fa ai_family
503not supported.
504.It Dv EAI_MEMORY
505Memory allocation failure.
506.It Dv EAI_NODATA
507No address associated with
508.Fa nodename .
509.It Dv EAI_NONAME
510.Fa nodename
511nor
512.Fa servname
513provided, or not known.
514.It Dv EAI_SERVICE
515.Fa servname
516not supported for
517.Fa ai_socktype .
518.It Dv EAI_SOCKTYPE
519.Fa ai_socktype
520not supported.
521.It Dv EAI_SYSTEM
522System error returned in
523.Va errno .
524.El
525.Pp
526If called with proper argument,
527.Fn gai_strerror
528returns a pointer to a string describing the given error code.
529If the argument is not one of the
530.Dv EAI_xxx
531values, the function still returns a pointer to a string whose contents
532indicate an unknown error.
533.\"
534.Sh SEE ALSO
535.Xr gethostbyname 3 ,
536.Xr getnameinfo 3 ,
537.Xr getservbyname 3 ,
538.Xr hosts 5 ,
539.Xr resolv.conf 5 ,
540.Xr services 5 ,
541.Xr hostname 7 ,
542.Xr named 8
543.Rs
544.%A R. Gilligan
545.%A S. Thomson
546.%A J. Bound
547.%A W. Stevens
548.%T Basic Socket Interface Extensions for IPv6
549.%R RFC2553
550.%D March 1999
551.Re
552.Rs
553.%A Tatsuya Jinmei
554.%A Atsushi Onoe
555.%T "An Extension of Format for IPv6 Scoped Addresses"
556.%R internet draft
557.%N draft-ietf-ipngwg-scopedaddr-format-02.txt
558.%O work in progress material
559.Re
560.Rs
561.%A Craig Metz
562.%T Protocol Independence Using the Sockets API
563.%B "Proceedings of the freenix track: 2000 USENIX annual technical conference"
564.%D June 2000
565.Re
566.\"
567.Sh HISTORY
568The implementation first appeared in WIDE Hydrangea IPv6 protocol stack kit.
569.\"
570.Sh STANDARDS
571The
572.Fn getaddrinfo
573function is defined in IEEE POSIX 1003.1g draft specification,
574and documented in
575.Dq Basic Socket Interface Extensions for IPv6
576.Pq RFC2553 .
577.\"
578.Sh BUGS
579The current implementation is not thread-safe.
580.Pp
581The text was shamelessly copied from RFC2553.
diff --git a/src/lib/libc/net/getaddrinfo.c b/src/lib/libc/net/getaddrinfo.c
new file mode 100644
index 0000000000..490b9861ae
--- /dev/null
+++ b/src/lib/libc/net/getaddrinfo.c
@@ -0,0 +1,1866 @@
1/* $OpenBSD: getaddrinfo.c,v 1.46 2003/03/17 23:16:36 jason Exp $ */
2/* $KAME: getaddrinfo.c,v 1.31 2000/08/31 17:36:43 itojun Exp $ */
3
4/*
5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the project nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33/*
34 * Issues to be discussed:
35 * - Thread safe-ness must be checked.
36 * - Return values. There are nonstandard return values defined and used
37 * in the source code. This is because RFC2553 is silent about which error
38 * code must be returned for which situation.
39 * - IPv4 classful (shortened) form. RFC2553 is silent about it. XNET 5.2
40 * says to use inet_aton() to convert IPv4 numeric to binary (alows
41 * classful form as a result).
42 * current code - disallow classful form for IPv4 (due to use of inet_pton).
43 * - freeaddrinfo(NULL). RFC2553 is silent about it. XNET 5.2 says it is
44 * invalid.
45 * current code - SEGV on freeaddrinfo(NULL)
46 * Note:
47 * - We use getipnodebyname() just for thread-safeness. There's no intent
48 * to let it do PF_UNSPEC (actually we never pass PF_UNSPEC to
49 * getipnodebyname().
50 * - The code filters out AFs that are not supported by the kernel,
51 * when globbing NULL hostname (to loopback, or wildcard). Is it the right
52 * thing to do? What is the relationship with post-RFC2553 AI_ADDRCONFIG
53 * in ai_flags?
54 * - (post-2553) semantics of AI_ADDRCONFIG itself is too vague.
55 * (1) what should we do against numeric hostname (2) what should we do
56 * against NULL hostname (3) what is AI_ADDRCONFIG itself. AF not ready?
57 * non-loopback address configured? global address configured?
58 * - To avoid search order issue, we have a big amount of code duplicate
59 * from gethnamaddr.c and some other places. The issues that there's no
60 * lower layer function to lookup "IPv4 or IPv6" record. Calling
61 * gethostbyname2 from getaddrinfo will end up in wrong search order, as
62 * follows:
63 * - The code makes use of following calls when asked to resolver with
64 * ai_family = PF_UNSPEC:
65 * getipnodebyname(host, AF_INET6);
66 * getipnodebyname(host, AF_INET);
67 * This will result in the following queries if the node is configure to
68 * prefer /etc/hosts than DNS:
69 * lookup /etc/hosts for IPv6 address
70 * lookup DNS for IPv6 address
71 * lookup /etc/hosts for IPv4 address
72 * lookup DNS for IPv4 address
73 * which may not meet people's requirement.
74 * The right thing to happen is to have underlying layer which does
75 * PF_UNSPEC lookup (lookup both) and return chain of addrinfos.
76 * This would result in a bit of code duplicate with _dns_ghbyname() and
77 * friends.
78 */
79
80#ifndef INET6
81#define INET6
82#endif
83
84#include <sys/types.h>
85#include <sys/param.h>
86#include <sys/socket.h>
87#include <net/if.h>
88#include <netinet/in.h>
89#include <arpa/inet.h>
90#include <arpa/nameser.h>
91#include <netdb.h>
92#include <resolv.h>
93#include <string.h>
94#include <stdlib.h>
95#include <stddef.h>
96#include <ctype.h>
97#include <unistd.h>
98#include <stdio.h>
99#include <errno.h>
100
101#include <syslog.h>
102#include <stdarg.h>
103
104#ifdef YP
105#include <rpc/rpc.h>
106#include <rpcsvc/yp.h>
107#include <rpcsvc/ypclnt.h>
108#include "ypinternal.h"
109#endif
110
111#include "thread_private.h"
112
113#define SUCCESS 0
114#define ANY 0
115#define YES 1
116#define NO 0
117
118static const char in_addrany[] = { 0, 0, 0, 0 };
119static const char in6_addrany[] = {
120 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
121};
122static const char in_loopback[] = { 127, 0, 0, 1 };
123static const char in6_loopback[] = {
124 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
125};
126
127static const struct afd {
128 int a_af;
129 int a_addrlen;
130 int a_socklen;
131 int a_off;
132 const char *a_addrany;
133 const char *a_loopback;
134 int a_scoped;
135} afdl [] = {
136#ifdef INET6
137 {PF_INET6, sizeof(struct in6_addr),
138 sizeof(struct sockaddr_in6),
139 offsetof(struct sockaddr_in6, sin6_addr),
140 in6_addrany, in6_loopback, 1},
141#endif
142 {PF_INET, sizeof(struct in_addr),
143 sizeof(struct sockaddr_in),
144 offsetof(struct sockaddr_in, sin_addr),
145 in_addrany, in_loopback, 0},
146 {0, 0, 0, 0, NULL, NULL, 0},
147};
148
149struct explore {
150 int e_af;
151 int e_socktype;
152 int e_protocol;
153 const char *e_protostr;
154 int e_wild;
155#define WILD_AF(ex) ((ex)->e_wild & 0x01)
156#define WILD_SOCKTYPE(ex) ((ex)->e_wild & 0x02)
157#define WILD_PROTOCOL(ex) ((ex)->e_wild & 0x04)
158};
159
160static const struct explore explore[] = {
161#if 0
162 { PF_LOCAL, 0, ANY, ANY, NULL, 0x01 },
163#endif
164#ifdef INET6
165 { PF_INET6, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
166 { PF_INET6, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
167 { PF_INET6, SOCK_RAW, ANY, NULL, 0x05 },
168#endif
169 { PF_INET, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
170 { PF_INET, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
171 { PF_INET, SOCK_RAW, ANY, NULL, 0x05 },
172 { PF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
173 { PF_UNSPEC, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
174 { PF_UNSPEC, SOCK_RAW, ANY, NULL, 0x05 },
175 { -1, 0, 0, NULL, 0 },
176};
177
178#ifdef INET6
179#define PTON_MAX 16
180#else
181#define PTON_MAX 4
182#endif
183
184#define MAXPACKET (64*1024)
185
186typedef union {
187 HEADER hdr;
188 u_char buf[MAXPACKET];
189} querybuf;
190
191struct res_target {
192 struct res_target *next;
193 const char *name; /* domain name */
194 int qclass, qtype; /* class and type of query */
195 u_char *answer; /* buffer to put answer */
196 int anslen; /* size of answer buffer */
197 int n; /* result length */
198};
199
200static int str_isnumber(const char *);
201static int explore_fqdn(const struct addrinfo *, const char *,
202 const char *, struct addrinfo **);
203static int explore_null(const struct addrinfo *,
204 const char *, struct addrinfo **);
205static int explore_numeric(const struct addrinfo *, const char *,
206 const char *, struct addrinfo **);
207static int explore_numeric_scope(const struct addrinfo *, const char *,
208 const char *, struct addrinfo **);
209static int get_canonname(const struct addrinfo *,
210 struct addrinfo *, const char *);
211static struct addrinfo *get_ai(const struct addrinfo *,
212 const struct afd *, const char *);
213static int get_portmatch(const struct addrinfo *, const char *);
214static int get_port(struct addrinfo *, const char *, int);
215static const struct afd *find_afd(int);
216#if 0
217static int addrconfig(const struct addrinfo *);
218#endif
219#ifdef INET6
220static int ip6_str2scopeid(char *, struct sockaddr_in6 *, u_int32_t *);
221#endif
222
223static void _sethtent(void);
224static void _endhtent(void);
225static struct addrinfo * _gethtent(const char *, const struct addrinfo *);
226static struct addrinfo *_files_getaddrinfo(const char *,
227 const struct addrinfo *);
228
229#ifdef YP
230static struct addrinfo *_yphostent(char *, const struct addrinfo *);
231static struct addrinfo *_yp_getaddrinfo(const char *,
232 const struct addrinfo *);
233#endif
234
235static struct addrinfo *getanswer(const querybuf *, int, const char *, int,
236 const struct addrinfo *);
237static int res_queryN(const char *, struct res_target *);
238static int res_searchN(const char *, struct res_target *);
239static int res_querydomainN(const char *, const char *, struct res_target *);
240static struct addrinfo *_dns_getaddrinfo(const char *, const struct addrinfo *);
241
242
243/* XXX macros that make external reference is BAD. */
244
245#define GET_AI(ai, afd, addr) \
246do { \
247 /* external reference: pai, error, and label free */ \
248 (ai) = get_ai(pai, (afd), (addr)); \
249 if ((ai) == NULL) { \
250 error = EAI_MEMORY; \
251 goto free; \
252 } \
253} while (/*CONSTCOND*/0)
254
255#define GET_PORT(ai, serv) \
256do { \
257 /* external reference: error and label free */ \
258 error = get_port((ai), (serv), 0); \
259 if (error != 0) \
260 goto free; \
261} while (/*CONSTCOND*/0)
262
263#define GET_CANONNAME(ai, str) \
264do { \
265 /* external reference: pai, error and label free */ \
266 error = get_canonname(pai, (ai), (str)); \
267 if (error != 0) \
268 goto free; \
269} while (/*CONSTCOND*/0)
270
271#define ERR(err) \
272do { \
273 /* external reference: error, and label bad */ \
274 error = (err); \
275 goto bad; \
276 /*NOTREACHED*/ \
277} while (/*CONSTCOND*/0)
278
279#define MATCH_FAMILY(x, y, w) \
280 ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == PF_UNSPEC || (y) == PF_UNSPEC)))
281#define MATCH(x, y, w) \
282 ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == ANY || (y) == ANY)))
283
284static int
285str_isnumber(p)
286 const char *p;
287{
288 char *ep;
289
290 if (*p == '\0')
291 return NO;
292 ep = NULL;
293 errno = 0;
294 (void)strtoul(p, &ep, 10);
295 if (errno == 0 && ep && *ep == '\0')
296 return YES;
297 else
298 return NO;
299}
300
301int
302getaddrinfo(hostname, servname, hints, res)
303 const char *hostname, *servname;
304 const struct addrinfo *hints;
305 struct addrinfo **res;
306{
307 struct addrinfo sentinel;
308 struct addrinfo *cur;
309 int error = 0;
310 struct addrinfo ai;
311 struct addrinfo ai0;
312 struct addrinfo *pai;
313 const struct explore *ex;
314
315 memset(&sentinel, 0, sizeof(sentinel));
316 cur = &sentinel;
317 pai = &ai;
318 pai->ai_flags = 0;
319 pai->ai_family = PF_UNSPEC;
320 pai->ai_socktype = ANY;
321 pai->ai_protocol = ANY;
322 pai->ai_addrlen = 0;
323 pai->ai_canonname = NULL;
324 pai->ai_addr = NULL;
325 pai->ai_next = NULL;
326
327 if (hostname == NULL && servname == NULL)
328 return EAI_NONAME;
329 if (hints) {
330 /* error check for hints */
331 if (hints->ai_addrlen || hints->ai_canonname ||
332 hints->ai_addr || hints->ai_next)
333 ERR(EAI_BADHINTS); /* xxx */
334 if (hints->ai_flags & ~AI_MASK)
335 ERR(EAI_BADFLAGS);
336 switch (hints->ai_family) {
337 case PF_UNSPEC:
338 case PF_INET:
339#ifdef INET6
340 case PF_INET6:
341#endif
342 break;
343 default:
344 ERR(EAI_FAMILY);
345 }
346 memcpy(pai, hints, sizeof(*pai));
347
348 /*
349 * if both socktype/protocol are specified, check if they
350 * are meaningful combination.
351 */
352 if (pai->ai_socktype != ANY && pai->ai_protocol != ANY) {
353 for (ex = explore; ex->e_af >= 0; ex++) {
354 if (pai->ai_family != ex->e_af)
355 continue;
356 if (ex->e_socktype == ANY)
357 continue;
358 if (ex->e_protocol == ANY)
359 continue;
360 if (pai->ai_socktype == ex->e_socktype
361 && pai->ai_protocol != ex->e_protocol) {
362 ERR(EAI_BADHINTS);
363 }
364 }
365 }
366 }
367
368 /*
369 * check for special cases. (1) numeric servname is disallowed if
370 * socktype/protocol are left unspecified. (2) servname is disallowed
371 * for raw and other inet{,6} sockets.
372 */
373 if (MATCH_FAMILY(pai->ai_family, PF_INET, 1)
374#ifdef PF_INET6
375 || MATCH_FAMILY(pai->ai_family, PF_INET6, 1)
376#endif
377 ) {
378 ai0 = *pai; /* backup *pai */
379
380 if (pai->ai_family == PF_UNSPEC) {
381#ifdef PF_INET6
382 pai->ai_family = PF_INET6;
383#else
384 pai->ai_family = PF_INET;
385#endif
386 }
387 error = get_portmatch(pai, servname);
388 if (error)
389 ERR(error);
390
391 *pai = ai0;
392 }
393
394 ai0 = *pai;
395
396 /* NULL hostname, or numeric hostname */
397 for (ex = explore; ex->e_af >= 0; ex++) {
398 *pai = ai0;
399
400 /* PF_UNSPEC entries are prepared for DNS queries only */
401 if (ex->e_af == PF_UNSPEC)
402 continue;
403
404 if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex)))
405 continue;
406 if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex)))
407 continue;
408 if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex)))
409 continue;
410
411 if (pai->ai_family == PF_UNSPEC)
412 pai->ai_family = ex->e_af;
413 if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
414 pai->ai_socktype = ex->e_socktype;
415 if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
416 pai->ai_protocol = ex->e_protocol;
417
418 if (hostname == NULL)
419 error = explore_null(pai, servname, &cur->ai_next);
420 else
421 error = explore_numeric_scope(pai, hostname, servname, &cur->ai_next);
422
423 if (error)
424 goto free;
425
426 while (cur && cur->ai_next)
427 cur = cur->ai_next;
428 }
429
430 /*
431 * XXX
432 * If numreic representation of AF1 can be interpreted as FQDN
433 * representation of AF2, we need to think again about the code below.
434 */
435 if (sentinel.ai_next)
436 goto good;
437
438 if (hostname == NULL)
439 ERR(EAI_NODATA);
440 if (pai->ai_flags & AI_NUMERICHOST)
441 ERR(EAI_NONAME);
442
443 /*
444 * hostname as alphabetical name.
445 * we would like to prefer AF_INET6 than AF_INET, so we'll make a
446 * outer loop by AFs.
447 */
448 for (ex = explore; ex->e_af >= 0; ex++) {
449 *pai = ai0;
450
451 /* require exact match for family field */
452 if (pai->ai_family != ex->e_af)
453 continue;
454
455 if (!MATCH(pai->ai_socktype, ex->e_socktype,
456 WILD_SOCKTYPE(ex))) {
457 continue;
458 }
459 if (!MATCH(pai->ai_protocol, ex->e_protocol,
460 WILD_PROTOCOL(ex))) {
461 continue;
462 }
463
464 if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
465 pai->ai_socktype = ex->e_socktype;
466 if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
467 pai->ai_protocol = ex->e_protocol;
468
469 error = explore_fqdn(pai, hostname, servname,
470 &cur->ai_next);
471
472 while (cur && cur->ai_next)
473 cur = cur->ai_next;
474 }
475
476 /* XXX */
477 if (sentinel.ai_next)
478 error = 0;
479
480 if (error)
481 goto free;
482 if (error == 0) {
483 if (sentinel.ai_next) {
484 good:
485 *res = sentinel.ai_next;
486 return SUCCESS;
487 } else
488 error = EAI_FAIL;
489 }
490 free:
491 bad:
492 if (sentinel.ai_next)
493 freeaddrinfo(sentinel.ai_next);
494 *res = NULL;
495 return error;
496}
497
498/*
499 * FQDN hostname, DNS lookup
500 */
501
502static int
503explore_fqdn(pai, hostname, servname, res)
504 const struct addrinfo *pai;
505 const char *hostname;
506 const char *servname;
507 struct addrinfo **res;
508{
509 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
510 struct addrinfo *result;
511 struct addrinfo *cur;
512 int error = 0;
513 char lookups[MAXDNSLUS];
514 int i;
515 _THREAD_PRIVATE_MUTEX(_explore_mutex);
516
517 result = NULL;
518
519#if 0
520 /*
521 * If AI_ADDRCONFIG is specified, check if we are expected to
522 * return the address family or not.
523 * XXX does not handle PF_UNSPEC case, should filter final result
524 */
525 if ((pai->ai_flags & AI_ADDRCONFIG) != 0 && !addrconfig(pai)) {
526 return 0;
527 }
528#endif
529
530 /*
531 * if the servname does not match socktype/protocol, ignore it.
532 */
533 if (get_portmatch(pai, servname) != 0) {
534 return 0;
535 }
536
537 if ((_resp->options & RES_INIT) == 0 && res_init() == -1)
538 strlcpy(lookups, "f", sizeof lookups);
539 else {
540 bcopy(_resp->lookups, lookups, sizeof lookups);
541 if (lookups[0] == '\0')
542 strlcpy(lookups, "bf", sizeof lookups);
543 }
544
545 /*
546 * The yp/dns/files getaddrinfo functions are not thread safe.
547 * Protect them with a mutex.
548 */
549 _THREAD_PRIVATE_MUTEX_LOCK(_explore_mutex);
550 for (i = 0; i < MAXDNSLUS && result == NULL && lookups[i]; i++) {
551 switch (lookups[i]) {
552#ifdef YP
553 case 'y':
554 result = _yp_getaddrinfo(hostname, pai);
555 break;
556#endif
557 case 'b':
558 result = _dns_getaddrinfo(hostname, pai);
559 break;
560 case 'f':
561 result = _files_getaddrinfo(hostname, pai);
562 break;
563 }
564 }
565 _THREAD_PRIVATE_MUTEX_UNLOCK(_explore_mutex);
566 if (result) {
567 for (cur = result; cur; cur = cur->ai_next) {
568 GET_PORT(cur, servname);
569 /* canonname should be filled already */
570 }
571 *res = result;
572 return 0;
573 } else {
574 /* translate error code */
575 switch (h_errno) {
576 case NETDB_SUCCESS:
577 error = EAI_FAIL; /*XXX strange */
578 break;
579 case HOST_NOT_FOUND:
580 error = EAI_NODATA;
581 break;
582 case TRY_AGAIN:
583 error = EAI_AGAIN;
584 break;
585 case NO_RECOVERY:
586 error = EAI_FAIL;
587 break;
588 case NO_DATA:
589#if NO_ADDRESS != NO_DATA
590 case NO_ADDRESS:
591#endif
592 error = EAI_NODATA;
593 break;
594 default: /* unknown ones */
595 error = EAI_FAIL;
596 break;
597 }
598 }
599
600free:
601 if (result)
602 freeaddrinfo(result);
603 return error;
604}
605
606/*
607 * hostname == NULL.
608 * passive socket -> anyaddr (0.0.0.0 or ::)
609 * non-passive socket -> localhost (127.0.0.1 or ::1)
610 */
611static int
612explore_null(pai, servname, res)
613 const struct addrinfo *pai;
614 const char *servname;
615 struct addrinfo **res;
616{
617 int s;
618 const struct afd *afd;
619 struct addrinfo *cur;
620 struct addrinfo sentinel;
621 int error;
622
623 *res = NULL;
624 sentinel.ai_next = NULL;
625 cur = &sentinel;
626
627 /*
628 * filter out AFs that are not supported by the kernel
629 * XXX errno?
630 */
631 s = socket(pai->ai_family, SOCK_DGRAM, 0);
632 if (s < 0) {
633 if (errno != EMFILE)
634 return 0;
635 } else
636 close(s);
637
638 /*
639 * if the servname does not match socktype/protocol, ignore it.
640 */
641 if (get_portmatch(pai, servname) != 0)
642 return 0;
643
644 afd = find_afd(pai->ai_family);
645 if (afd == NULL)
646 return 0;
647
648 if (pai->ai_flags & AI_PASSIVE) {
649 GET_AI(cur->ai_next, afd, afd->a_addrany);
650 /* xxx meaningless?
651 * GET_CANONNAME(cur->ai_next, "anyaddr");
652 */
653 GET_PORT(cur->ai_next, servname);
654 } else {
655 GET_AI(cur->ai_next, afd, afd->a_loopback);
656 /* xxx meaningless?
657 * GET_CANONNAME(cur->ai_next, "localhost");
658 */
659 GET_PORT(cur->ai_next, servname);
660 }
661 cur = cur->ai_next;
662
663 *res = sentinel.ai_next;
664 return 0;
665
666free:
667 if (sentinel.ai_next)
668 freeaddrinfo(sentinel.ai_next);
669 return error;
670}
671
672/*
673 * numeric hostname
674 */
675static int
676explore_numeric(pai, hostname, servname, res)
677 const struct addrinfo *pai;
678 const char *hostname;
679 const char *servname;
680 struct addrinfo **res;
681{
682 const struct afd *afd;
683 struct addrinfo *cur;
684 struct addrinfo sentinel;
685 int error;
686 char pton[PTON_MAX];
687
688 *res = NULL;
689 sentinel.ai_next = NULL;
690 cur = &sentinel;
691
692 /*
693 * if the servname does not match socktype/protocol, ignore it.
694 */
695 if (get_portmatch(pai, servname) != 0)
696 return 0;
697
698 afd = find_afd(pai->ai_family);
699 if (afd == NULL)
700 return 0;
701
702 switch (afd->a_af) {
703#if 0 /*X/Open spec*/
704 case AF_INET:
705 if (inet_aton(hostname, (struct in_addr *)pton) == 1) {
706 if (pai->ai_family == afd->a_af ||
707 pai->ai_family == PF_UNSPEC /*?*/) {
708 GET_AI(cur->ai_next, afd, pton);
709 GET_PORT(cur->ai_next, servname);
710 while (cur && cur->ai_next)
711 cur = cur->ai_next;
712 } else
713 ERR(EAI_FAMILY); /*xxx*/
714 }
715 break;
716#endif
717 default:
718 if (inet_pton(afd->a_af, hostname, pton) == 1) {
719 if (pai->ai_family == afd->a_af ||
720 pai->ai_family == PF_UNSPEC /*?*/) {
721 GET_AI(cur->ai_next, afd, pton);
722 GET_PORT(cur->ai_next, servname);
723 while (cur && cur->ai_next)
724 cur = cur->ai_next;
725 } else
726 ERR(EAI_FAMILY); /*xxx*/
727 }
728 break;
729 }
730
731 *res = sentinel.ai_next;
732 return 0;
733
734free:
735bad:
736 if (sentinel.ai_next)
737 freeaddrinfo(sentinel.ai_next);
738 return error;
739}
740
741/*
742 * numeric hostname with scope
743 */
744static int
745explore_numeric_scope(pai, hostname, servname, res)
746 const struct addrinfo *pai;
747 const char *hostname;
748 const char *servname;
749 struct addrinfo **res;
750{
751#if !defined(SCOPE_DELIMITER) || !defined(INET6)
752 return explore_numeric(pai, hostname, servname, res);
753#else
754 const struct afd *afd;
755 struct addrinfo *cur;
756 int error;
757 char *cp, *hostname2 = NULL, *scope, *addr;
758 struct sockaddr_in6 *sin6;
759
760 /*
761 * if the servname does not match socktype/protocol, ignore it.
762 */
763 if (get_portmatch(pai, servname) != 0)
764 return 0;
765
766 afd = find_afd(pai->ai_family);
767 if (afd == NULL)
768 return 0;
769
770 if (!afd->a_scoped)
771 return explore_numeric(pai, hostname, servname, res);
772
773 cp = strchr(hostname, SCOPE_DELIMITER);
774 if (cp == NULL)
775 return explore_numeric(pai, hostname, servname, res);
776
777 /*
778 * Handle special case of <scoped_address><delimiter><scope id>
779 */
780 hostname2 = strdup(hostname);
781 if (hostname2 == NULL)
782 return EAI_MEMORY;
783 /* terminate at the delimiter */
784 hostname2[cp - hostname] = '\0';
785 addr = hostname2;
786 scope = cp + 1;
787
788 error = explore_numeric(pai, addr, servname, res);
789 if (error == 0) {
790 u_int32_t scopeid;
791
792 for (cur = *res; cur; cur = cur->ai_next) {
793 if (cur->ai_family != AF_INET6)
794 continue;
795 sin6 = (struct sockaddr_in6 *)(void *)cur->ai_addr;
796 if (ip6_str2scopeid(scope, sin6, &scopeid) == -1) {
797 free(hostname2);
798 return(EAI_NODATA); /* XXX: is return OK? */
799 }
800 sin6->sin6_scope_id = scopeid;
801 }
802 }
803
804 free(hostname2);
805
806 return error;
807#endif
808}
809
810static int
811get_canonname(pai, ai, str)
812 const struct addrinfo *pai;
813 struct addrinfo *ai;
814 const char *str;
815{
816 if ((pai->ai_flags & AI_CANONNAME) != 0) {
817 ai->ai_canonname = strdup(str);
818 if (ai->ai_canonname == NULL)
819 return EAI_MEMORY;
820 }
821 return 0;
822}
823
824static struct addrinfo *
825get_ai(pai, afd, addr)
826 const struct addrinfo *pai;
827 const struct afd *afd;
828 const char *addr;
829{
830 char *p;
831 struct addrinfo *ai;
832
833 ai = (struct addrinfo *)malloc(sizeof(struct addrinfo)
834 + (afd->a_socklen));
835 if (ai == NULL)
836 return NULL;
837
838 memcpy(ai, pai, sizeof(struct addrinfo));
839 ai->ai_addr = (struct sockaddr *)(void *)(ai + 1);
840 memset(ai->ai_addr, 0, (size_t)afd->a_socklen);
841 ai->ai_addr->sa_len = afd->a_socklen;
842 ai->ai_addrlen = afd->a_socklen;
843 ai->ai_addr->sa_family = ai->ai_family = afd->a_af;
844 p = (char *)(void *)(ai->ai_addr);
845 memcpy(p + afd->a_off, addr, (size_t)afd->a_addrlen);
846 return ai;
847}
848
849static int
850get_portmatch(ai, servname)
851 const struct addrinfo *ai;
852 const char *servname;
853{
854
855 /* get_port does not touch first argument. when matchonly == 1. */
856 /* LINTED const cast */
857 return get_port((struct addrinfo *)ai, servname, 1);
858}
859
860static int
861get_port(ai, servname, matchonly)
862 struct addrinfo *ai;
863 const char *servname;
864 int matchonly;
865{
866 const char *proto;
867 struct servent *sp;
868 int port;
869 int allownumeric;
870 _THREAD_PRIVATE_MUTEX(serv_mutex);
871
872 if (servname == NULL)
873 return 0;
874 switch (ai->ai_family) {
875 case AF_INET:
876#ifdef AF_INET6
877 case AF_INET6:
878#endif
879 break;
880 default:
881 return 0;
882 }
883
884 switch (ai->ai_socktype) {
885 case SOCK_RAW:
886 return EAI_SERVICE;
887 case SOCK_DGRAM:
888 case SOCK_STREAM:
889 allownumeric = 1;
890 break;
891 case ANY:
892 allownumeric = 0;
893 break;
894 default:
895 return EAI_SOCKTYPE;
896 }
897
898 if (str_isnumber(servname)) {
899 if (!allownumeric)
900 return EAI_SERVICE;
901 port = atoi(servname);
902 if (port < 0 || port > 65535)
903 return EAI_SERVICE;
904 port = htons(port);
905 } else {
906 switch (ai->ai_socktype) {
907 case SOCK_DGRAM:
908 proto = "udp";
909 break;
910 case SOCK_STREAM:
911 proto = "tcp";
912 break;
913 default:
914 proto = NULL;
915 break;
916 }
917
918 _THREAD_PRIVATE_MUTEX_LOCK(serv_mutex);
919 sp = getservbyname(servname, proto);
920 _THREAD_PRIVATE_MUTEX_UNLOCK(serv_mutex);
921 if (sp == NULL)
922 return EAI_SERVICE;
923 port = sp->s_port;
924 }
925
926 if (!matchonly) {
927 switch (ai->ai_family) {
928 case AF_INET:
929 ((struct sockaddr_in *)(void *)
930 ai->ai_addr)->sin_port = port;
931 break;
932#ifdef INET6
933 case AF_INET6:
934 ((struct sockaddr_in6 *)(void *)
935 ai->ai_addr)->sin6_port = port;
936 break;
937#endif
938 }
939 }
940
941 return 0;
942}
943
944static const struct afd *
945find_afd(af)
946 int af;
947{
948 const struct afd *afd;
949
950 if (af == PF_UNSPEC)
951 return NULL;
952 for (afd = afdl; afd->a_af; afd++) {
953 if (afd->a_af == af)
954 return afd;
955 }
956 return NULL;
957}
958
959#if 0
960/*
961 * post-2553: AI_ADDRCONFIG check. if we use getipnodeby* as backend, backend
962 * will take care of it.
963 * the semantics of AI_ADDRCONFIG is not defined well. we are not sure
964 * if the code is right or not.
965 */
966static int
967addrconfig(pai)
968 const struct addrinfo *pai;
969{
970 int s;
971
972 /* XXX errno */
973 s = socket(pai->ai_family, SOCK_DGRAM, 0);
974 if (s < 0)
975 return 0;
976 close(s);
977 return 1;
978}
979#endif
980
981#ifdef INET6
982/* convert a string to a scope identifier. XXX: IPv6 specific */
983static int
984ip6_str2scopeid(scope, sin6, scopeid)
985 char *scope;
986 struct sockaddr_in6 *sin6;
987 u_int32_t *scopeid;
988{
989 u_long lscopeid;
990 struct in6_addr *a6 = &sin6->sin6_addr;
991 char *ep;
992
993 /* empty scopeid portion is invalid */
994 if (*scope == '\0')
995 return -1;
996
997 if (IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6)) {
998 /*
999 * We currently assume a one-to-one mapping between links
1000 * and interfaces, so we simply use interface indices for
1001 * like-local scopes.
1002 */
1003 *scopeid = if_nametoindex(scope);
1004 if (*scopeid == 0)
1005 goto trynumeric;
1006 return 0;
1007 }
1008
1009 /* still unclear about literal, allow numeric only - placeholder */
1010 if (IN6_IS_ADDR_SITELOCAL(a6) || IN6_IS_ADDR_MC_SITELOCAL(a6))
1011 goto trynumeric;
1012 if (IN6_IS_ADDR_MC_ORGLOCAL(a6))
1013 goto trynumeric;
1014 else
1015 goto trynumeric; /* global */
1016
1017 /* try to convert to a numeric id as a last resort */
1018 trynumeric:
1019 errno = 0;
1020 lscopeid = strtoul(scope, &ep, 10);
1021 *scopeid = (u_int32_t)(lscopeid & 0xffffffffUL);
1022 if (errno == 0 && ep && *ep == '\0' && *scopeid == lscopeid)
1023 return 0;
1024 else
1025 return -1;
1026}
1027#endif
1028
1029/* code duplicate with gethnamaddr.c */
1030
1031static const char AskedForGot[] =
1032 "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
1033static FILE *hostf = NULL;
1034
1035static struct addrinfo *
1036getanswer(answer, anslen, qname, qtype, pai)
1037 const querybuf *answer;
1038 int anslen;
1039 const char *qname;
1040 int qtype;
1041 const struct addrinfo *pai;
1042{
1043 struct addrinfo sentinel, *cur;
1044 struct addrinfo ai;
1045 const struct afd *afd;
1046 char *canonname;
1047 const HEADER *hp;
1048 const u_char *cp;
1049 int n;
1050 const u_char *eom;
1051 char *bp, *ep;
1052 int type, class, ancount, qdcount;
1053 int haveanswer, had_error;
1054 char tbuf[MAXDNAME];
1055 int (*name_ok)(const char *);
1056 char hostbuf[8*1024];
1057
1058 memset(&sentinel, 0, sizeof(sentinel));
1059 cur = &sentinel;
1060
1061 canonname = NULL;
1062 eom = answer->buf + anslen;
1063 switch (qtype) {
1064 case T_A:
1065 case T_AAAA:
1066 case T_ANY: /*use T_ANY only for T_A/T_AAAA lookup*/
1067 name_ok = res_hnok;
1068 break;
1069 default:
1070 return (NULL); /* XXX should be abort() -- but that is illegal */
1071 }
1072 /*
1073 * find first satisfactory answer
1074 */
1075 hp = &answer->hdr;
1076 ancount = ntohs(hp->ancount);
1077 qdcount = ntohs(hp->qdcount);
1078 bp = hostbuf;
1079 ep = hostbuf + sizeof hostbuf;
1080 cp = answer->buf + HFIXEDSZ;
1081 if (qdcount != 1) {
1082 h_errno = NO_RECOVERY;
1083 return (NULL);
1084 }
1085 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
1086 if ((n < 0) || !(*name_ok)(bp)) {
1087 h_errno = NO_RECOVERY;
1088 return (NULL);
1089 }
1090 cp += n + QFIXEDSZ;
1091 if (qtype == T_A || qtype == T_AAAA || qtype == T_ANY) {
1092 /* res_send() has already verified that the query name is the
1093 * same as the one we sent; this just gets the expanded name
1094 * (i.e., with the succeeding search-domain tacked on).
1095 */
1096 n = strlen(bp) + 1; /* for the \0 */
1097 if (n >= MAXHOSTNAMELEN) {
1098 h_errno = NO_RECOVERY;
1099 return (NULL);
1100 }
1101 canonname = bp;
1102 bp += n;
1103 /* The qname can be abbreviated, but h_name is now absolute. */
1104 qname = canonname;
1105 }
1106 haveanswer = 0;
1107 had_error = 0;
1108 while (ancount-- > 0 && cp < eom && !had_error) {
1109 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
1110 if ((n < 0) || !(*name_ok)(bp)) {
1111 had_error++;
1112 continue;
1113 }
1114 cp += n; /* name */
1115 type = _getshort(cp);
1116 cp += INT16SZ; /* type */
1117 class = _getshort(cp);
1118 cp += INT16SZ + INT32SZ; /* class, TTL */
1119 n = _getshort(cp);
1120 cp += INT16SZ; /* len */
1121 if (class != C_IN) {
1122 /* XXX - debug? syslog? */
1123 cp += n;
1124 continue; /* XXX - had_error++ ? */
1125 }
1126 if ((qtype == T_A || qtype == T_AAAA || qtype == T_ANY) &&
1127 type == T_CNAME) {
1128 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
1129 if ((n < 0) || !(*name_ok)(tbuf)) {
1130 had_error++;
1131 continue;
1132 }
1133 cp += n;
1134 /* Get canonical name. */
1135 n = strlen(tbuf) + 1; /* for the \0 */
1136 if (n > ep - bp || n >= MAXHOSTNAMELEN) {
1137 had_error++;
1138 continue;
1139 }
1140 strlcpy(bp, tbuf, ep - bp);
1141 canonname = bp;
1142 bp += n;
1143 continue;
1144 }
1145 if (qtype == T_ANY) {
1146 if (!(type == T_A || type == T_AAAA)) {
1147 cp += n;
1148 continue;
1149 }
1150 } else if (type != qtype) {
1151 if (type != T_KEY && type != T_SIG)
1152 syslog(LOG_NOTICE|LOG_AUTH,
1153 "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
1154 qname, p_class(C_IN), p_type(qtype),
1155 p_type(type));
1156 cp += n;
1157 continue; /* XXX - had_error++ ? */
1158 }
1159 switch (type) {
1160 case T_A:
1161 case T_AAAA:
1162 if (strcasecmp(canonname, bp) != 0) {
1163 syslog(LOG_NOTICE|LOG_AUTH,
1164 AskedForGot, canonname, bp);
1165 cp += n;
1166 continue; /* XXX - had_error++ ? */
1167 }
1168 if (type == T_A && n != INADDRSZ) {
1169 cp += n;
1170 continue;
1171 }
1172 if (type == T_AAAA && n != IN6ADDRSZ) {
1173 cp += n;
1174 continue;
1175 }
1176 if (type == T_AAAA) {
1177 struct in6_addr in6;
1178 memcpy(&in6, cp, IN6ADDRSZ);
1179 if (IN6_IS_ADDR_V4MAPPED(&in6)) {
1180 cp += n;
1181 continue;
1182 }
1183 }
1184 if (!haveanswer) {
1185 int nn;
1186
1187 canonname = bp;
1188 nn = strlen(bp) + 1; /* for the \0 */
1189 bp += nn;
1190 }
1191
1192 /* don't overwrite pai */
1193 ai = *pai;
1194 ai.ai_family = (type == T_A) ? AF_INET : AF_INET6;
1195 afd = find_afd(ai.ai_family);
1196 if (afd == NULL) {
1197 cp += n;
1198 continue;
1199 }
1200 cur->ai_next = get_ai(&ai, afd, (const char *)cp);
1201 if (cur->ai_next == NULL)
1202 had_error++;
1203 while (cur && cur->ai_next)
1204 cur = cur->ai_next;
1205 cp += n;
1206 break;
1207 default:
1208 abort(); /* XXX abort illegal in library */
1209 }
1210 if (!had_error)
1211 haveanswer++;
1212 }
1213 if (haveanswer) {
1214 if (!canonname)
1215 (void)get_canonname(pai, sentinel.ai_next, qname);
1216 else
1217 (void)get_canonname(pai, sentinel.ai_next, canonname);
1218 h_errno = NETDB_SUCCESS;
1219 return sentinel.ai_next;
1220 }
1221
1222 h_errno = NO_RECOVERY;
1223 return NULL;
1224}
1225
1226/*ARGSUSED*/
1227static struct addrinfo *
1228_dns_getaddrinfo(name, pai)
1229 const char *name;
1230 const struct addrinfo *pai;
1231{
1232 struct addrinfo *ai;
1233 querybuf *buf, *buf2;
1234 struct addrinfo sentinel, *cur;
1235 struct res_target q, q2;
1236
1237 memset(&q, 0, sizeof(q2));
1238 memset(&q2, 0, sizeof(q2));
1239 memset(&sentinel, 0, sizeof(sentinel));
1240 cur = &sentinel;
1241
1242 buf = malloc(sizeof(*buf));
1243 if (buf == NULL) {
1244 h_errno = NETDB_INTERNAL;
1245 return NULL;
1246 }
1247 buf2 = malloc(sizeof(*buf2));
1248 if (buf2 == NULL) {
1249 free(buf);
1250 h_errno = NETDB_INTERNAL;
1251 return NULL;
1252 }
1253
1254 switch (pai->ai_family) {
1255 case AF_UNSPEC:
1256 /* prefer IPv6 */
1257 q.qclass = C_IN;
1258 q.qtype = T_AAAA;
1259 q.answer = buf->buf;
1260 q.anslen = sizeof(buf->buf);
1261 q.next = &q2;
1262 q2.qclass = C_IN;
1263 q2.qtype = T_A;
1264 q2.answer = buf2->buf;
1265 q2.anslen = sizeof(buf2->buf);
1266 break;
1267 case AF_INET:
1268 q.qclass = C_IN;
1269 q.qtype = T_A;
1270 q.answer = buf->buf;
1271 q.anslen = sizeof(buf->buf);
1272 break;
1273 case AF_INET6:
1274 q.qclass = C_IN;
1275 q.qtype = T_AAAA;
1276 q.answer = buf->buf;
1277 q.anslen = sizeof(buf->buf);
1278 break;
1279 default:
1280 free(buf);
1281 free(buf2);
1282 return NULL;
1283 }
1284 if (res_searchN(name, &q) < 0) {
1285 free(buf);
1286 free(buf2);
1287 return NULL;
1288 }
1289 ai = getanswer(buf, q.n, q.name, q.qtype, pai);
1290 if (ai) {
1291 cur->ai_next = ai;
1292 while (cur && cur->ai_next)
1293 cur = cur->ai_next;
1294 }
1295 if (q.next) {
1296 ai = getanswer(buf2, q2.n, q2.name, q2.qtype, pai);
1297 if (ai)
1298 cur->ai_next = ai;
1299 }
1300 free(buf);
1301 free(buf2);
1302 return sentinel.ai_next;
1303}
1304
1305static FILE *hostf;
1306
1307static void
1308_sethtent()
1309{
1310 if (!hostf)
1311 hostf = fopen(_PATH_HOSTS, "r" );
1312 else
1313 rewind(hostf);
1314}
1315
1316static void
1317_endhtent()
1318{
1319 if (hostf) {
1320 (void) fclose(hostf);
1321 hostf = NULL;
1322 }
1323}
1324
1325static struct addrinfo *
1326_gethtent(name, pai)
1327 const char *name;
1328 const struct addrinfo *pai;
1329{
1330 char *p;
1331 char *cp, *tname, *cname;
1332 struct addrinfo hints, *res0, *res;
1333 int error;
1334 const char *addr;
1335 char hostbuf[8*1024];
1336
1337 if (!hostf && !(hostf = fopen(_PATH_HOSTS, "r" )))
1338 return (NULL);
1339 again:
1340 if (!(p = fgets(hostbuf, sizeof hostbuf, hostf)))
1341 return (NULL);
1342 if (*p == '#')
1343 goto again;
1344 if (!(cp = strpbrk(p, "#\n")))
1345 goto again;
1346 *cp = '\0';
1347 if (!(cp = strpbrk(p, " \t")))
1348 goto again;
1349 *cp++ = '\0';
1350 addr = p;
1351 /* if this is not something we're looking for, skip it. */
1352 cname = NULL;
1353 while (cp && *cp) {
1354 if (*cp == ' ' || *cp == '\t') {
1355 cp++;
1356 continue;
1357 }
1358 if (!cname)
1359 cname = cp;
1360 tname = cp;
1361 if ((cp = strpbrk(cp, " \t")) != NULL)
1362 *cp++ = '\0';
1363 if (strcasecmp(name, tname) == 0)
1364 goto found;
1365 }
1366 goto again;
1367
1368found:
1369 hints = *pai;
1370 hints.ai_flags = AI_NUMERICHOST;
1371 error = getaddrinfo(addr, NULL, &hints, &res0);
1372 if (error)
1373 goto again;
1374 for (res = res0; res; res = res->ai_next) {
1375 /* cover it up */
1376 res->ai_flags = pai->ai_flags;
1377
1378 if (pai->ai_flags & AI_CANONNAME) {
1379 if (get_canonname(pai, res, cname) != 0) {
1380 freeaddrinfo(res0);
1381 goto again;
1382 }
1383 }
1384 }
1385 return res0;
1386}
1387
1388/*ARGSUSED*/
1389static struct addrinfo *
1390_files_getaddrinfo(name, pai)
1391 const char *name;
1392 const struct addrinfo *pai;
1393{
1394 struct addrinfo sentinel, *cur;
1395 struct addrinfo *p;
1396
1397 memset(&sentinel, 0, sizeof(sentinel));
1398 cur = &sentinel;
1399
1400 _sethtent();
1401 while ((p = _gethtent(name, pai)) != NULL) {
1402 cur->ai_next = p;
1403 while (cur && cur->ai_next)
1404 cur = cur->ai_next;
1405 }
1406 _endhtent();
1407
1408 return sentinel.ai_next;
1409}
1410
1411#ifdef YP
1412static char *__ypdomain;
1413
1414/*ARGSUSED*/
1415static struct addrinfo *
1416_yphostent(line, pai)
1417 char *line;
1418 const struct addrinfo *pai;
1419{
1420 struct addrinfo sentinel, *cur;
1421 struct addrinfo hints, *res, *res0;
1422 int error;
1423 char *p = line;
1424 const char *addr, *canonname;
1425 char *nextline;
1426 char *cp;
1427
1428 addr = canonname = NULL;
1429
1430 memset(&sentinel, 0, sizeof(sentinel));
1431 cur = &sentinel;
1432
1433nextline:
1434 /* terminate line */
1435 cp = strchr(p, '\n');
1436 if (cp) {
1437 *cp++ = '\0';
1438 nextline = cp;
1439 } else
1440 nextline = NULL;
1441
1442 cp = strpbrk(p, " \t");
1443 if (cp == NULL) {
1444 if (canonname == NULL)
1445 return (NULL);
1446 else
1447 goto done;
1448 }
1449 *cp++ = '\0';
1450
1451 addr = p;
1452
1453 while (cp && *cp) {
1454 if (*cp == ' ' || *cp == '\t') {
1455 cp++;
1456 continue;
1457 }
1458 if (!canonname)
1459 canonname = cp;
1460 if ((cp = strpbrk(cp, " \t")) != NULL)
1461 *cp++ = '\0';
1462 }
1463
1464 hints = *pai;
1465 hints.ai_flags = AI_NUMERICHOST;
1466 error = getaddrinfo(addr, NULL, &hints, &res0);
1467 if (error == 0) {
1468 for (res = res0; res; res = res->ai_next) {
1469 /* cover it up */
1470 res->ai_flags = pai->ai_flags;
1471
1472 if (pai->ai_flags & AI_CANONNAME)
1473 (void)get_canonname(pai, res, canonname);
1474 }
1475 } else
1476 res0 = NULL;
1477 if (res0) {
1478 cur->ai_next = res0;
1479 while (cur && cur->ai_next)
1480 cur = cur->ai_next;
1481 }
1482
1483 if (nextline) {
1484 p = nextline;
1485 goto nextline;
1486 }
1487
1488done:
1489 return sentinel.ai_next;
1490}
1491
1492/*ARGSUSED*/
1493static struct addrinfo *
1494_yp_getaddrinfo(name, pai)
1495 const char *name;
1496 const struct addrinfo *pai;
1497{
1498 struct addrinfo sentinel, *cur;
1499 struct addrinfo *ai = NULL;
1500 static char *__ypcurrent;
1501 int __ypcurrentlen, r;
1502
1503 memset(&sentinel, 0, sizeof(sentinel));
1504 cur = &sentinel;
1505
1506 if (!__ypdomain) {
1507 if (_yp_check(&__ypdomain) == 0)
1508 return NULL;
1509 }
1510 if (__ypcurrent)
1511 free(__ypcurrent);
1512 __ypcurrent = NULL;
1513
1514 /* hosts.byname is only for IPv4 (Solaris8) */
1515 if (pai->ai_family == PF_UNSPEC || pai->ai_family == PF_INET) {
1516 r = yp_match(__ypdomain, "hosts.byname", name,
1517 (int)strlen(name), &__ypcurrent, &__ypcurrentlen);
1518 if (r == 0) {
1519 struct addrinfo ai4;
1520
1521 ai4 = *pai;
1522 ai4.ai_family = AF_INET;
1523 ai = _yphostent(__ypcurrent, &ai4);
1524 if (ai) {
1525 cur->ai_next = ai;
1526 while (cur && cur->ai_next)
1527 cur = cur->ai_next;
1528 }
1529 }
1530 }
1531
1532 /* ipnodes.byname can hold both IPv4/v6 */
1533 r = yp_match(__ypdomain, "ipnodes.byname", name,
1534 (int)strlen(name), &__ypcurrent, &__ypcurrentlen);
1535 if (r == 0) {
1536 ai = _yphostent(__ypcurrent, pai);
1537 if (ai) {
1538 cur->ai_next = ai;
1539 while (cur && cur->ai_next)
1540 cur = cur->ai_next;
1541 }
1542 }
1543
1544 return sentinel.ai_next;
1545}
1546#endif
1547
1548
1549/* resolver logic */
1550
1551extern const char *__hostalias(const char *);
1552extern int h_errno;
1553extern int res_opt(int, u_char *, int, int);
1554
1555/*
1556 * Formulate a normal query, send, and await answer.
1557 * Returned answer is placed in supplied buffer "answer".
1558 * Perform preliminary check of answer, returning success only
1559 * if no error is indicated and the answer count is nonzero.
1560 * Return the size of the response on success, -1 on error.
1561 * Error number is left in h_errno.
1562 *
1563 * Caller must parse answer and determine whether it answers the question.
1564 */
1565static int
1566res_queryN(name, target)
1567 const char *name; /* domain name */
1568 struct res_target *target;
1569{
1570 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
1571 u_char *buf;
1572 HEADER *hp;
1573 int n;
1574 struct res_target *t;
1575 int rcode;
1576 int ancount;
1577
1578 buf = malloc(MAXPACKET);
1579 if (buf == NULL) {
1580 h_errno = NETDB_INTERNAL;
1581 return (-1);
1582 }
1583
1584 rcode = NOERROR;
1585 ancount = 0;
1586
1587 if ((_resp->options & RES_INIT) == 0 && res_init() == -1) {
1588 h_errno = NETDB_INTERNAL;
1589 free(buf);
1590 return (-1);
1591 }
1592
1593 for (t = target; t; t = t->next) {
1594 int class, type;
1595 u_char *answer;
1596 int anslen;
1597
1598 hp = (HEADER *)(void *)t->answer;
1599 hp->rcode = NOERROR; /* default */
1600
1601 /* make it easier... */
1602 class = t->qclass;
1603 type = t->qtype;
1604 answer = t->answer;
1605 anslen = t->anslen;
1606#ifdef DEBUG
1607 if (_resp->options & RES_DEBUG)
1608 printf(";; res_query(%s, %d, %d)\n", name, class, type);
1609#endif
1610
1611 n = res_mkquery(QUERY, name, class, type, NULL, 0, NULL,
1612 buf, MAXPACKET);
1613 if (n > 0 && (_resp->options & RES_USE_EDNS0) != 0)
1614 n = res_opt(n, buf, MAXPACKET, anslen);
1615 if (n <= 0) {
1616#ifdef DEBUG
1617 if (_resp->options & RES_DEBUG)
1618 printf(";; res_query: mkquery failed\n");
1619#endif
1620 h_errno = NO_RECOVERY;
1621 free(buf);
1622 return (n);
1623 }
1624 n = res_send(buf, n, answer, anslen);
1625#if 0
1626 if (n < 0) {
1627#ifdef DEBUG
1628 if (_resp->options & RES_DEBUG)
1629 printf(";; res_query: send error\n");
1630#endif
1631 h_errno = TRY_AGAIN;
1632 free(buf);
1633 return (n);
1634 }
1635#endif
1636
1637 if (n < 0 || hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
1638 rcode = hp->rcode; /* record most recent error */
1639#ifdef DEBUG
1640 if (_resp->options & RES_DEBUG)
1641 printf(";; rcode = %u, ancount=%u\n", hp->rcode,
1642 ntohs(hp->ancount));
1643#endif
1644 continue;
1645 }
1646
1647 ancount += ntohs(hp->ancount);
1648
1649 t->n = n;
1650 }
1651
1652 if (ancount == 0) {
1653 switch (rcode) {
1654 case NXDOMAIN:
1655 h_errno = HOST_NOT_FOUND;
1656 break;
1657 case SERVFAIL:
1658 h_errno = TRY_AGAIN;
1659 break;
1660 case NOERROR:
1661 h_errno = NO_DATA;
1662 break;
1663 case FORMERR:
1664 case NOTIMP:
1665 case REFUSED:
1666 default:
1667 h_errno = NO_RECOVERY;
1668 break;
1669 }
1670 free(buf);
1671 return (-1);
1672 }
1673 free(buf);
1674 return (ancount);
1675}
1676
1677/*
1678 * Formulate a normal query, send, and retrieve answer in supplied buffer.
1679 * Return the size of the response on success, -1 on error.
1680 * If enabled, implement search rules until answer or unrecoverable failure
1681 * is detected. Error code, if any, is left in h_errno.
1682 */
1683static int
1684res_searchN(name, target)
1685 const char *name; /* domain name */
1686 struct res_target *target;
1687{
1688 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
1689 const char *cp, * const *domain;
1690 HEADER *hp = (HEADER *)(void *)target->answer; /*XXX*/
1691 u_int dots;
1692 int trailing_dot, ret, saved_herrno;
1693 int got_nodata = 0, got_servfail = 0, tried_as_is = 0;
1694
1695 if ((_resp->options & RES_INIT) == 0 && res_init() == -1) {
1696 h_errno = NETDB_INTERNAL;
1697 return (-1);
1698 }
1699
1700 errno = 0;
1701 h_errno = HOST_NOT_FOUND; /* default, if we never query */
1702 dots = 0;
1703 for (cp = name; *cp; cp++)
1704 dots += (*cp == '.');
1705 trailing_dot = 0;
1706 if (cp > name && *--cp == '.')
1707 trailing_dot++;
1708
1709 /*
1710 * if there aren't any dots, it could be a user-level alias
1711 */
1712 if (!dots && (cp = __hostalias(name)) != NULL)
1713 return (res_queryN(cp, target));
1714
1715 /*
1716 * If there are dots in the name already, let's just give it a try
1717 * 'as is'. The threshold can be set with the "ndots" option.
1718 */
1719 saved_herrno = -1;
1720 if (dots >= _resp->ndots) {
1721 ret = res_querydomainN(name, NULL, target);
1722 if (ret > 0)
1723 return (ret);
1724 saved_herrno = h_errno;
1725 tried_as_is++;
1726 }
1727
1728 /*
1729 * We do at least one level of search if
1730 * - there is no dot and RES_DEFNAME is set, or
1731 * - there is at least one dot, there is no trailing dot,
1732 * and RES_DNSRCH is set.
1733 */
1734 if ((!dots && (_resp->options & RES_DEFNAMES)) ||
1735 (dots && !trailing_dot && (_resp->options & RES_DNSRCH))) {
1736 int done = 0;
1737
1738 for (domain = (const char * const *)_resp->dnsrch;
1739 *domain && !done;
1740 domain++) {
1741
1742 ret = res_querydomainN(name, *domain, target);
1743 if (ret > 0)
1744 return (ret);
1745
1746 /*
1747 * If no server present, give up.
1748 * If name isn't found in this domain,
1749 * keep trying higher domains in the search list
1750 * (if that's enabled).
1751 * On a NO_DATA error, keep trying, otherwise
1752 * a wildcard entry of another type could keep us
1753 * from finding this entry higher in the domain.
1754 * If we get some other error (negative answer or
1755 * server failure), then stop searching up,
1756 * but try the input name below in case it's
1757 * fully-qualified.
1758 */
1759 if (errno == ECONNREFUSED) {
1760 h_errno = TRY_AGAIN;
1761 return (-1);
1762 }
1763
1764 switch (h_errno) {
1765 case NO_DATA:
1766 got_nodata++;
1767 /* FALLTHROUGH */
1768 case HOST_NOT_FOUND:
1769 /* keep trying */
1770 break;
1771 case TRY_AGAIN:
1772 if (hp->rcode == SERVFAIL) {
1773 /* try next search element, if any */
1774 got_servfail++;
1775 break;
1776 }
1777 /* FALLTHROUGH */
1778 default:
1779 /* anything else implies that we're done */
1780 done++;
1781 }
1782 /*
1783 * if we got here for some reason other than DNSRCH,
1784 * we only wanted one iteration of the loop, so stop.
1785 */
1786 if (!(_resp->options & RES_DNSRCH))
1787 done++;
1788 }
1789 }
1790
1791 /*
1792 * if we have not already tried the name "as is", do that now.
1793 * note that we do this regardless of how many dots were in the
1794 * name or whether it ends with a dot.
1795 */
1796 if (!tried_as_is) {
1797 ret = res_querydomainN(name, NULL, target);
1798 if (ret > 0)
1799 return (ret);
1800 }
1801
1802 /*
1803 * if we got here, we didn't satisfy the search.
1804 * if we did an initial full query, return that query's h_errno
1805 * (note that we wouldn't be here if that query had succeeded).
1806 * else if we ever got a nodata, send that back as the reason.
1807 * else send back meaningless h_errno, that being the one from
1808 * the last DNSRCH we did.
1809 */
1810 if (saved_herrno != -1)
1811 h_errno = saved_herrno;
1812 else if (got_nodata)
1813 h_errno = NO_DATA;
1814 else if (got_servfail)
1815 h_errno = TRY_AGAIN;
1816 return (-1);
1817}
1818
1819/*
1820 * Perform a call on res_query on the concatenation of name and domain,
1821 * removing a trailing dot from name if domain is NULL.
1822 */
1823static int
1824res_querydomainN(name, domain, target)
1825 const char *name, *domain;
1826 struct res_target *target;
1827{
1828 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
1829 char nbuf[MAXDNAME];
1830 const char *longname = nbuf;
1831 size_t n, d;
1832
1833 if ((_resp->options & RES_INIT) == 0 && res_init() == -1) {
1834 h_errno = NETDB_INTERNAL;
1835 return (-1);
1836 }
1837#ifdef DEBUG
1838 if (_resp->options & RES_DEBUG)
1839 printf(";; res_querydomain(%s, %s)\n",
1840 name, domain?domain:"<Nil>");
1841#endif
1842 if (domain == NULL) {
1843 /*
1844 * Check for trailing '.';
1845 * copy without '.' if present.
1846 */
1847 n = strlen(name);
1848 if (n >= MAXDNAME) {
1849 h_errno = NO_RECOVERY;
1850 return (-1);
1851 }
1852 if (n > 0 && name[--n] == '.') {
1853 strlcpy(nbuf, name, n + 1);
1854 } else
1855 longname = name;
1856 } else {
1857 n = strlen(name);
1858 d = strlen(domain);
1859 if (n + d + 1 >= MAXDNAME) {
1860 h_errno = NO_RECOVERY;
1861 return (-1);
1862 }
1863 snprintf(nbuf, sizeof(nbuf), "%s.%s", name, domain);
1864 }
1865 return (res_queryN(longname, target));
1866}
diff --git a/src/lib/libc/net/gethostbyname.3 b/src/lib/libc/net/gethostbyname.3
index bac0368296..d90ea55542 100644
--- a/src/lib/libc/net/gethostbyname.3
+++ b/src/lib/libc/net/gethostbyname.3
@@ -1,4 +1,4 @@
1.\" $NetBSD: gethostbyname.3,v 1.6 1995/02/25 06:20:28 cgd Exp $ 1.\" $OpenBSD: gethostbyname.3,v 1.17 2002/04/30 16:31:42 mpech Exp $
2.\" 2.\"
3.\" Copyright (c) 1983, 1987, 1991, 1993 3.\" Copyright (c) 1983, 1987, 1991, 1993
4.\" The Regents of the University of California. All rights reserved. 4.\" The Regents of the University of California. All rights reserved.
@@ -31,17 +31,17 @@
31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32.\" SUCH DAMAGE. 32.\" SUCH DAMAGE.
33.\" 33.\"
34.\" @(#)gethostbyname.3 8.2 (Berkeley) 4/19/94 34.Dd March 13, 1997
35.\"
36.Dd April 19, 1994
37.Dt GETHOSTBYNAME 3 35.Dt GETHOSTBYNAME 3
38.Os BSD 4.2 36.Os
39.Sh NAME 37.Sh NAME
40.Nm gethostbyname , 38.Nm gethostbyname ,
39.Nm gethostbyname2 ,
41.Nm gethostbyaddr , 40.Nm gethostbyaddr ,
42.Nm gethostent , 41.Nm gethostent ,
43.Nm sethostent , 42.Nm sethostent ,
44.Nm endhostent , 43.Nm endhostent ,
44.Nm hstrerror ,
45.Nm herror 45.Nm herror
46.Nd get network host entry 46.Nd get network host entry
47.Sh SYNOPSIS 47.Sh SYNOPSIS
@@ -50,30 +50,37 @@
50.Ft struct hostent * 50.Ft struct hostent *
51.Fn gethostbyname "const char *name" 51.Fn gethostbyname "const char *name"
52.Ft struct hostent * 52.Ft struct hostent *
53.Fn gethostbyaddr "const char *addr" "int len" "int type" 53.Fn gethostbyname2 "const char *name" "int af"
54.Ft struct hostent *
55.Fn gethostbyaddr "const char *addr" "int len" "int af"
54.Ft struct hostent * 56.Ft struct hostent *
55.Fn gethostent void 57.Fn gethostent void
58.Ft void
56.Fn sethostent "int stayopen" 59.Fn sethostent "int stayopen"
60.Ft void
57.Fn endhostent void 61.Fn endhostent void
58.Fn herror "char *string" 62.Ft void
63.Fn herror "const char *string"
64.Ft const char *
65.Fn hstrerror "int err"
59.Sh DESCRIPTION 66.Sh DESCRIPTION
60The 67The
61.Fn gethostbyname 68.Fn gethostbyname
62and 69and
63.Fn gethostbyaddr 70.Fn gethostbyaddr
64functions 71functions each return a pointer to an object with the following structure
65each return a pointer to an object with the 72describing an internet host referenced by name or by address, respectively.
66following structure describing an internet host 73This structure contains either information obtained from the name server (i.e.,
67referenced by name or by address, respectively. 74.Xr resolver 3
68This structure contains either the information obtained from the name server, 75and
69.Xr named 8 , 76.Xr named 8 ) ,
70broken-out fields from a line in 77broken-out fields from a line in
71.Pa /etc/hosts , 78.Pa /etc/hosts ,
72or database entries supplied by the 79or database entries supplied by the
73.Xr yp 8 80.Xr yp 8
74system . 81system.
75If the local name server is not running these routines do a lookup in 82.Xr resolv.conf 5
76.Pa /etc/hosts . 83describes how the particular database is chosen.
77.Bd -literal 84.Bd -literal
78struct hostent { 85struct hostent {
79 char *h_name; /* official name of host */ 86 char *h_name; /* official name of host */
@@ -90,36 +97,48 @@ The members of this structure are:
90.It Fa h_name 97.It Fa h_name
91Official name of the host. 98Official name of the host.
92.It Fa h_aliases 99.It Fa h_aliases
93A zero terminated array of alternate names for the host. 100A zero-terminated array of alternate names for the host.
94.It Fa h_addrtype 101.It Fa h_addrtype
95The type of address being returned; currently always 102The type of address being returned.
96.Dv AF_INET .
97.It Fa h_length 103.It Fa h_length
98The length, in bytes, of the address. 104The length, in bytes, of the address.
99.It Fa h_addr_list 105.It Fa h_addr_list
100A zero terminated array of network addresses for the host. 106A zero-terminated array of network addresses for the host.
101Host addresses are returned in network byte order. 107Host addresses are returned in network byte order.
102.It Fa h_addr 108.It Fa h_addr
103The first address in 109The first address in
104.Fa h_addr_list ; 110.Fa h_addr_list ;
105this is for backward compatibility. 111this is for backward compatibility.
112.El
106.Pp 113.Pp
107When using the nameserver, 114The function
108.Fn gethostbyname 115.Fn gethostbyname
109will search for the named host in the current domain and its parents 116will search for the named host in the current domain and its parents
110unless the name ends in a dot. 117using the search lookup semantics detailed in
111If the name contains no dot, and if the environment variable 118.Xr resolv.conf 5
112.Dq Ev HOSTALIASES 119and
113contains the name of an alias file, the alias file will first be searched 120.Xr hostname 7 .
114for an alias matching the input name. 121.Pp
115See 122.Fn gethostbyname2
116.Xr hostname 7 123is an advanced form of
117for the domain search procedure and the alias file format. 124.Fn gethostbyname
125which allows lookups in address families other than
126.Dv AF_INET ,
127for example
128.Dv AF_INET6 .
129.Pp
130The
131.Fn gethostbyaddr
132function will search for the specified address of length
133.Fa len
134in the address family
135.Fa af .
136The only address family currently supported is
137.Dv AF_INET .
118.Pp 138.Pp
119The 139The
120.Fn sethostent 140.Fn sethostent
121function 141function may be used to request the use of a connected
122may be used to request the use of a connected
123.Tn TCP 142.Tn TCP
124socket for queries. 143socket for queries.
125If the 144If the
@@ -127,7 +146,7 @@ If the
127flag is non-zero, 146flag is non-zero,
128this sets the option to send all queries to the name server using 147this sets the option to send all queries to the name server using
129.Tn TCP 148.Tn TCP
130and to retain the connection after each call to 149and to retain the connection after each call to
131.Fn gethostbyname 150.Fn gethostbyname
132or 151or
133.Fn gethostbyaddr . 152.Fn gethostbyaddr .
@@ -137,17 +156,33 @@ datagrams.
137.Pp 156.Pp
138The 157The
139.Fn endhostent 158.Fn endhostent
140function 159function closes the
141closes the
142.Tn TCP 160.Tn TCP
143connection. 161connection.
162.Pp
163The
164.Fn herror
165function prints an error message describing the failure.
166If its argument
167.Fa string
168is non-null,
169it is prepended to the message string and separated from it by a colon
170.Pq Ql \&:
171and a space.
172The error message is printed with a trailing newline.
173The contents of the error message is the same as that returned by
174.Fn hstrerror
175with argument
176.Fa h_errno .
144.Sh FILES 177.Sh FILES
145.Bl -tag -width /etc/hosts -compact 178.Bl -tag -width /etc/resolv.conf -compact
146.It Pa /etc/hosts 179.It Pa /etc/hosts
180.It Pa /etc/resolv.conf
147.El 181.El
148.Sh DIAGNOSTICS 182.Sh DIAGNOSTICS
149Error return status from 183Error return status from
150.Fn gethostbyname 184.Fn gethostbyname ,
185.Fn gethostbyname2 ,
151and 186and
152.Fn gethostbyaddr 187.Fn gethostbyaddr
153is indicated by return of a null pointer. 188is indicated by return of a null pointer.
@@ -155,15 +190,6 @@ The external integer
155.Va h_errno 190.Va h_errno
156may then be checked to see whether this is a temporary failure 191may then be checked to see whether this is a temporary failure
157or an invalid or unknown host. 192or an invalid or unknown host.
158The routine
159.Fn herror
160can be used to print an error message describing the failure.
161If its argument
162.Fa string
163is
164.Pf non Dv -NULL ,
165it is printed, followed by a colon and a space.
166The error message is printed with a trailing newline.
167.Pp 193.Pp
168The variable 194The variable
169.Va h_errno 195.Va h_errno
@@ -180,8 +206,8 @@ A retry at some later time may succeed.
180Some unexpected server failure was encountered. 206Some unexpected server failure was encountered.
181This is a non-recoverable error. 207This is a non-recoverable error.
182.It Dv NO_DATA 208.It Dv NO_DATA
183The requested name is valid but does not have an IP address; 209The requested name is valid but does not have an IP address;
184this is not a temporary error. 210this is not a temporary error.
185This means that the name is known to the name server but there is no address 211This means that the name is known to the name server but there is no address
186associated with this name. 212associated with this name.
187Another type of request to the name server using this domain name 213Another type of request to the name server using this domain name
@@ -190,52 +216,42 @@ for example, a mail-forwarder may be registered for this domain.
190.El 216.El
191.Sh SEE ALSO 217.Sh SEE ALSO
192.Xr resolver 3 , 218.Xr resolver 3 ,
219.Xr getaddrinfo 3 ,
220.Xr getnameinfo 3 ,
193.Xr hosts 5 , 221.Xr hosts 5 ,
222.Xr resolv.conf 5 ,
194.Xr hostname 7 , 223.Xr hostname 7 ,
195.Xr named 8 224.Xr named 8
196.Sh CAVEAT 225.Sh CAVEATS
197The 226If the search routines in
198.Fn gethostent 227.Xr resolv.conf 5
199function 228decide to read the
200is defined, and
201.Fn sethostent
202and
203.Fn endhostent
204are redefined,
205when
206.Xr libc 3
207is built to use only the routines to lookup in
208.Pa /etc/hosts 229.Pa /etc/hosts
209and not the name server. 230file,
210.Pp
211The
212.Fn gethostent 231.Fn gethostent
213function 232and other functions will
214reads the next line of 233read the next line of the file,
215.Pa /etc/hosts , 234re-opening the file if necessary.
216opening the file if necessary.
217.Pp 235.Pp
218The 236The
219.Fn sethostent 237.Fn sethostent
220function 238function opens and/or rewinds the file
221opens and/or rewinds the file
222.Pa /etc/hosts . 239.Pa /etc/hosts .
223If the 240If the
224.Fa stayopen 241.Fa stayopen
225argument is non-zero, 242argument is non-zero, the file will not be closed after each call to
226the file will not be closed after each call to 243.Fn gethostbyname ,
227.Fn gethostbyname 244.Fn gethostbyname2 ,
228or 245or
229.Fn gethostbyaddr . 246.Fn gethostbyaddr .
230.Pp 247.Pp
231The 248The
232.Fn endhostent 249.Fn endhostent
233function 250function closes the file.
234closes the file.
235.Sh HISTORY 251.Sh HISTORY
236The 252The
237.Fn herror 253.Fn herror
238function appeared in 254function appeared in
239.Bx 4.3 . 255.Bx 4.3 .
240The 256The
241.Fn endhostent , 257.Fn endhostent ,
@@ -251,4 +267,9 @@ These functions use static data storage;
251if the data is needed for future use, it should be 267if the data is needed for future use, it should be
252copied before any subsequent calls overwrite it. 268copied before any subsequent calls overwrite it.
253Only the Internet 269Only the Internet
254address format is currently understood. 270address formats are currently understood.
271.Pp
272YP does not support any address families other than
273.Dv AF_INET
274and uses
275the traditional database format.
diff --git a/src/lib/libc/net/gethostnamadr.c b/src/lib/libc/net/gethostnamadr.c
index ec3f14a900..7cf419fdb1 100644
--- a/src/lib/libc/net/gethostnamadr.c
+++ b/src/lib/libc/net/gethostnamadr.c
@@ -1,5 +1,3 @@
1/* $NetBSD: gethostnamadr.c,v 1.13 1995/05/21 16:21:14 mycroft Exp $ */
2
3/*- 1/*-
4 * Copyright (c) 1985, 1988, 1993 2 * Copyright (c) 1985, 1988, 1993
5 * The Regents of the University of California. All rights reserved. 3 * The Regents of the University of California. All rights reserved.
@@ -54,12 +52,7 @@
54 */ 52 */
55 53
56#if defined(LIBC_SCCS) && !defined(lint) 54#if defined(LIBC_SCCS) && !defined(lint)
57#if 0 55static char rcsid[] = "$OpenBSD: gethostnamadr.c,v 1.55 2003/03/04 00:29:17 itojun Exp $";
58static char sccsid[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93";
59static char rcsid[] = "$Id: gethnamaddr.c,v 4.9.1.1 1993/05/02 22:43:03 vixie Rel ";
60#else
61static char rcsid[] = "$NetBSD: gethostnamadr.c,v 1.13 1995/05/21 16:21:14 mycroft Exp $";
62#endif
63#endif /* LIBC_SCCS and not lint */ 56#endif /* LIBC_SCCS and not lint */
64 57
65#include <sys/param.h> 58#include <sys/param.h>
@@ -73,11 +66,17 @@ static char rcsid[] = "$NetBSD: gethostnamadr.c,v 1.13 1995/05/21 16:21:14 mycro
73#include <ctype.h> 66#include <ctype.h>
74#include <errno.h> 67#include <errno.h>
75#include <string.h> 68#include <string.h>
69#include <syslog.h>
70#include <stdlib.h>
76#ifdef YP 71#ifdef YP
77#include <rpc/rpc.h> 72#include <rpc/rpc.h>
78#include <rpcsvc/yp_prot.h> 73#include <rpcsvc/yp.h>
79#include <rpcsvc/ypclnt.h> 74#include <rpcsvc/ypclnt.h>
75#include "ypinternal.h"
80#endif 76#endif
77#include "thread_private.h"
78
79#define MULTI_PTRS_ARE_ALIASES 1 /* XXX - experimental */
81 80
82#define MAXALIASES 35 81#define MAXALIASES 35
83#define MAXADDRS 35 82#define MAXADDRS 35
@@ -91,47 +90,109 @@ static char *__ypdomain;
91static struct hostent host; 90static struct hostent host;
92static char *host_aliases[MAXALIASES]; 91static char *host_aliases[MAXALIASES];
93static char hostbuf[BUFSIZ+1]; 92static char hostbuf[BUFSIZ+1];
94static struct in_addr host_addr; 93static union {
94 struct in_addr _host_in_addr;
95 u_char _host_addr[16]; /* IPv4 or IPv6 */
96} _host_addr_u;
97#define host_addr _host_addr_u._host_addr
95static FILE *hostf = NULL; 98static FILE *hostf = NULL;
96static int stayopen = 0; 99static int stayopen = 0;
97 100
98#if PACKETSZ > 1024 101static void map_v4v6_address(const char *src, char *dst);
99#define MAXPACKET PACKETSZ 102static void map_v4v6_hostent(struct hostent *hp, char **bp, char *);
100#else 103
101#define MAXPACKET 1024 104#ifdef RESOLVSORT
105static void addrsort(char **, int);
102#endif 106#endif
103 107
108int _hokchar(const char *);
109
110static const char AskedForGot[] =
111 "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
112
113#define MAXPACKET (64*1024)
114
104typedef union { 115typedef union {
105 HEADER hdr; 116 HEADER hdr;
106 u_char buf[MAXPACKET]; 117 u_char buf[MAXPACKET];
107} querybuf; 118} querybuf;
108 119
109typedef union { 120typedef union {
110 int32_t al; 121 int32_t al;
111 char ac; 122 char ac;
112} align; 123} align;
113 124
114static int qcomp __P((struct in_addr **, struct in_addr **)); 125static struct hostent *getanswer(const querybuf *, int, const char *, int);
115static struct hostent *getanswer __P((querybuf *, int, int));
116 126
117extern int h_errno; 127extern int h_errno;
118 128
129int
130_hokchar(p)
131 const char *p;
132{
133 char c;
134
135 /*
136 * Many people do not obey RFC 822 and 1035. The valid
137 * characters are a-z, A-Z, 0-9, '-' and . But the others
138 * tested for below can happen, and we must be more permissive
139 * than the resolver until those idiots clean up their act.
140 * We let '/' through, but not '..'
141 */
142 while ((c = *p++)) {
143 if (('a' <= c && c <= 'z') ||
144 ('A' <= c && c <= 'Z') ||
145 ('0' <= c && c <= '9'))
146 continue;
147 if (strchr("-_/", c))
148 continue;
149 if (c == '.' && *p != '.')
150 continue;
151 return 0;
152 }
153 return 1;
154}
155
119static struct hostent * 156static struct hostent *
120getanswer(answer, anslen, iquery) 157getanswer(answer, anslen, qname, qtype)
121 querybuf *answer; 158 const querybuf *answer;
122 int anslen; 159 int anslen;
123 int iquery; 160 const char *qname;
161 int qtype;
124{ 162{
125 register HEADER *hp; 163 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
126 register u_char *cp; 164 register const HEADER *hp;
165 register const u_char *cp;
127 register int n; 166 register int n;
128 u_char *eom; 167 const u_char *eom;
129 char *bp, **ap; 168 char *bp, **ap, **hap, *ep;
130 int type, class, buflen, ancount, qdcount; 169 int type, class, ancount, qdcount;
131 int haveanswer, getclass = C_ANY; 170 int haveanswer, had_error;
132 char **hap; 171 int toobig = 0;
172 char tbuf[MAXDNAME];
173 const char *tname;
174 int (*name_ok)(const char *);
133 175
176 tname = qname;
177 host.h_name = NULL;
134 eom = answer->buf + anslen; 178 eom = answer->buf + anslen;
179 switch (qtype) {
180 case T_A:
181 case T_AAAA:
182#ifdef USE_RESOLV_NAME_OK
183 name_ok = res_hnok;
184 break;
185#endif
186 case T_PTR:
187#ifdef USE_RESOLV_NAME_OK
188 name_ok = res_dnok;
189#else
190 name_ok = _hokchar;
191#endif
192 break;
193 default:
194 return (NULL);
195 }
135 /* 196 /*
136 * find first satisfactory answer 197 * find first satisfactory answer
137 */ 198 */
@@ -139,31 +200,28 @@ getanswer(answer, anslen, iquery)
139 ancount = ntohs(hp->ancount); 200 ancount = ntohs(hp->ancount);
140 qdcount = ntohs(hp->qdcount); 201 qdcount = ntohs(hp->qdcount);
141 bp = hostbuf; 202 bp = hostbuf;
142 buflen = sizeof(hostbuf); 203 ep = hostbuf + sizeof hostbuf;
143 cp = answer->buf + sizeof(HEADER); 204 cp = answer->buf + HFIXEDSZ;
144 if (qdcount) { 205 if (qdcount != 1) {
145 if (iquery) { 206 h_errno = NO_RECOVERY;
146 if ((n = dn_expand((u_char *)answer->buf, 207 return (NULL);
147 (u_char *)eom, (u_char *)cp, (u_char *)bp, 208 }
148 buflen)) < 0) { 209 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
149 h_errno = NO_RECOVERY; 210 if ((n < 0) || !(*name_ok)(bp)) {
150 return ((struct hostent *) NULL); 211 h_errno = NO_RECOVERY;
151 } 212 return (NULL);
152 cp += n + QFIXEDSZ; 213 }
153 host.h_name = bp; 214 cp += n + QFIXEDSZ;
154 n = strlen(bp) + 1; 215 if (qtype == T_A || qtype == T_AAAA) {
155 bp += n; 216 /* res_send() has already verified that the query name is the
156 buflen -= n; 217 * same as the one we sent; this just gets the expanded name
157 } else 218 * (i.e., with the succeeding search-domain tacked on).
158 cp += __dn_skipname(cp, eom) + QFIXEDSZ; 219 */
159 while (--qdcount > 0) 220 n = strlen(bp) + 1; /* for the \0 */
160 cp += __dn_skipname(cp, eom) + QFIXEDSZ; 221 host.h_name = bp;
161 } else if (iquery) { 222 bp += n;
162 if (hp->aa) 223 /* The qname can be abbreviated, but h_name is now absolute. */
163 h_errno = HOST_NOT_FOUND; 224 qname = host.h_name;
164 else
165 h_errno = TRY_AGAIN;
166 return ((struct hostent *) NULL);
167 } 225 }
168 ap = host_aliases; 226 ap = host_aliases;
169 *ap = NULL; 227 *ap = NULL;
@@ -172,104 +230,325 @@ getanswer(answer, anslen, iquery)
172 *hap = NULL; 230 *hap = NULL;
173 host.h_addr_list = h_addr_ptrs; 231 host.h_addr_list = h_addr_ptrs;
174 haveanswer = 0; 232 haveanswer = 0;
175 while (--ancount >= 0 && cp < eom) { 233 had_error = 0;
176 if ((n = dn_expand((u_char *)answer->buf, (u_char *)eom, 234 while (ancount-- > 0 && cp < eom && !had_error) {
177 (u_char *)cp, (u_char *)bp, buflen)) < 0) 235 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
178 break; 236 if ((n < 0) || !(*name_ok)(bp)) {
179 cp += n; 237 had_error++;
238 continue;
239 }
240 cp += n; /* name */
180 type = _getshort(cp); 241 type = _getshort(cp);
181 cp += sizeof(u_int16_t); 242 cp += INT16SZ; /* type */
182 class = _getshort(cp); 243 class = _getshort(cp);
183 cp += sizeof(u_int16_t) + sizeof(u_int32_t); 244 cp += INT16SZ + INT32SZ; /* class, TTL */
184 n = _getshort(cp); 245 n = _getshort(cp);
185 cp += sizeof(u_int16_t); 246 cp += INT16SZ; /* len */
186 if (type == T_CNAME) { 247 if (type == T_SIG) {
248 /* XXX - ignore signatures as we don't use them yet */
187 cp += n; 249 cp += n;
250 continue;
251 }
252 if (class != C_IN) {
253 /* XXX - debug? syslog? */
254 cp += n;
255 continue; /* XXX - had_error++ ? */
256 }
257 if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) {
188 if (ap >= &host_aliases[MAXALIASES-1]) 258 if (ap >= &host_aliases[MAXALIASES-1])
189 continue; 259 continue;
260 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
261 if ((n < 0) || !(*name_ok)(tbuf)) {
262 had_error++;
263 continue;
264 }
265 cp += n;
266 /* Store alias. */
190 *ap++ = bp; 267 *ap++ = bp;
191 n = strlen(bp) + 1; 268 n = strlen(bp) + 1; /* for the \0 */
192 bp += n; 269 bp += n;
193 buflen -= n; 270 /* Get canonical name. */
194 continue; 271 n = strlen(tbuf) + 1; /* for the \0 */
195 } 272 if (n > ep - bp) {
196 if (iquery && type == T_PTR) { 273 had_error++;
197 if ((n = dn_expand((u_char *)answer->buf, 274 continue;
198 (u_char *)eom, (u_char *)cp, (u_char *)bp, 275 }
199 buflen)) < 0) 276 strlcpy(bp, tbuf, ep - bp);
200 break;
201 cp += n;
202 host.h_name = bp; 277 host.h_name = bp;
203 return(&host); 278 bp += n;
279 continue;
204 } 280 }
205 if (iquery || type != T_A) { 281 if (qtype == T_PTR && type == T_CNAME) {
206#ifdef DEBUG 282 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
207 if (_res.options & RES_DEBUG) 283#ifdef USE_RESOLV_NAME_OK
208 printf("unexpected answer type %d, size %d\n", 284 if ((n < 0) || !res_hnok(tbuf)) {
209 type, n); 285#else
286 if ((n < 0) || !_hokchar(tbuf)) {
210#endif 287#endif
288 had_error++;
289 continue;
290 }
211 cp += n; 291 cp += n;
292 /* Get canonical name. */
293 n = strlen(tbuf) + 1; /* for the \0 */
294 if (n > ep - bp) {
295 had_error++;
296 continue;
297 }
298 strlcpy(bp, tbuf, ep - bp);
299 tname = bp;
300 bp += n;
212 continue; 301 continue;
213 } 302 }
214 if (haveanswer) { 303 if (type != qtype) {
215 if (n != host.h_length) { 304 syslog(LOG_NOTICE|LOG_AUTH,
305 "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
306 qname, p_class(C_IN), p_type(qtype),
307 p_type(type));
308 cp += n;
309 continue; /* XXX - had_error++ ? */
310 }
311 switch (type) {
312 case T_PTR:
313 if (strcasecmp(tname, bp) != 0) {
314 syslog(LOG_NOTICE|LOG_AUTH,
315 AskedForGot, qname, bp);
216 cp += n; 316 cp += n;
217 continue; 317 continue; /* XXX - had_error++ ? */
318 }
319 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
320#ifdef USE_RESOLV_NAME_OK
321 if ((n < 0) || !res_hnok(bp)) {
322#else
323 if ((n < 0) || !_hokchar(bp)) {
324#endif
325 had_error++;
326 break;
327 }
328#if MULTI_PTRS_ARE_ALIASES
329 cp += n;
330 if (!haveanswer)
331 host.h_name = bp;
332 else if (ap < &host_aliases[MAXALIASES-1])
333 *ap++ = bp;
334 else
335 n = -1;
336 if (n != -1) {
337 n = strlen(bp) + 1; /* for the \0 */
338 bp += n;
339 }
340 break;
341#else
342 host.h_name = bp;
343 if (_resp->options & RES_USE_INET6) {
344 n = strlen(bp) + 1; /* for the \0 */
345 bp += n;
346 map_v4v6_hostent(&host, &bp, ep);
347 }
348 h_errno = NETDB_SUCCESS;
349 return (&host);
350#endif
351 case T_A:
352 case T_AAAA:
353 if (strcasecmp(host.h_name, bp) != 0) {
354 syslog(LOG_NOTICE|LOG_AUTH,
355 AskedForGot, host.h_name, bp);
356 cp += n;
357 continue; /* XXX - had_error++ ? */
218 } 358 }
219 if (class != getclass) { 359 if (n != host.h_length) {
220 cp += n; 360 cp += n;
221 continue; 361 continue;
222 } 362 }
223 } else { 363 if (type == T_AAAA) {
224 host.h_length = n; 364 struct in6_addr in6;
225 getclass = class; 365 memcpy(&in6, cp, IN6ADDRSZ);
226 host.h_addrtype = (class == C_IN) ? AF_INET : AF_UNSPEC; 366 if (IN6_IS_ADDR_V4MAPPED(&in6)) {
227 if (!iquery) { 367 cp += n;
368 continue;
369 }
370 }
371 if (!haveanswer) {
372 register int nn;
373
228 host.h_name = bp; 374 host.h_name = bp;
229 bp += strlen(bp) + 1; 375 nn = strlen(bp) + 1; /* for the \0 */
376 bp += nn;
230 } 377 }
231 }
232 378
233 bp += sizeof(align) - ((u_long)bp % sizeof(align)); 379 bp += sizeof(align) - ((u_long)bp % sizeof(align));
234 380
235 if (bp + n >= &hostbuf[sizeof(hostbuf)]) { 381 if (bp + n >= &hostbuf[sizeof hostbuf]) {
236#ifdef DEBUG 382#ifdef DEBUG
237 if (_res.options & RES_DEBUG) 383 if (_resp->options & RES_DEBUG)
238 printf("size (%d) too big\n", n); 384 printf("size (%d) too big\n", n);
239#endif 385#endif
386 had_error++;
387 continue;
388 }
389 if (hap >= &h_addr_ptrs[MAXADDRS-1]) {
390 if (!toobig++)
391#ifdef DEBUG
392 if (_resp->options & RES_DEBUG)
393 printf("Too many addresses (%d)\n", MAXADDRS);
394#endif
395 cp += n;
396 continue;
397 }
398 bcopy(cp, *hap++ = bp, n);
399 bp += n;
400 cp += n;
240 break; 401 break;
241 } 402 }
242 bcopy(cp, *hap++ = bp, n); 403 if (!had_error)
243 bp +=n; 404 haveanswer++;
244 cp += n;
245 haveanswer++;
246 } 405 }
247 if (haveanswer) { 406 if (haveanswer) {
248 *ap = NULL; 407 *ap = NULL;
249 *hap = NULL; 408 *hap = NULL;
250 if (_res.nsort) { 409# if defined(RESOLVSORT)
251 qsort(host.h_addr_list, haveanswer, 410 /*
252 sizeof(struct in_addr), 411 * Note: we sort even if host can take only one address
253 (int (*)__P((const void *, const void *)))qcomp); 412 * in its return structures - should give it the "best"
413 * address in that case, not some random one
414 */
415 if (_resp->nsort && haveanswer > 1 && qtype == T_A)
416 addrsort(h_addr_ptrs, haveanswer);
417# endif /*RESOLVSORT*/
418 if (!host.h_name) {
419 n = strlen(qname) + 1; /* for the \0 */
420 if (n > ep - bp)
421 goto try_again;
422 strlcpy(bp, qname, ep - bp);
423 host.h_name = bp;
424 bp += n;
254 } 425 }
426 if (_resp->options & RES_USE_INET6)
427 map_v4v6_hostent(&host, &bp, ep);
428 h_errno = NETDB_SUCCESS;
255 return (&host); 429 return (&host);
256 } else {
257 h_errno = TRY_AGAIN;
258 return ((struct hostent *) NULL);
259 } 430 }
431 try_again:
432 h_errno = TRY_AGAIN;
433 return (NULL);
434}
435
436#ifdef notyet
437/*
438 * XXX This is an extremely bogus implementation.
439 *
440 * FreeBSD has this interface:
441 * int gethostbyaddr_r(const char *addr, int len, int type,
442 * struct hostent *result, struct hostent_data *buffer)
443 */
444
445struct hostent *
446gethostbyname_r(name, hp, buf, buflen, errorp)
447 const char * name;
448 struct hostent * hp;
449 char * buf;
450 int buflen;
451 int * errorp;
452{
453 struct hostent *res;
454
455 res = gethostbyname(name);
456 *errorp = h_errno;
457 if (res == NULL)
458 return NULL;
459 memcpy(hp, res, sizeof *hp); /* XXX not sufficient */
460 return hp;
461}
462
463/*
464 * XXX This is an extremely bogus implementation.
465 */
466struct hostent *
467gethostbyaddr_r(addr, len, af, he, buf, buflen, errorp)
468 const char *addr; /* XXX should have been def'd as u_char! */
469 int len, af;
470 struct hostent * he;
471 char * buf;
472 int buflen;
473 int * errorp;
474{
475 struct hostent * res;
476
477 res = gethostbyaddr(addr, len, af);
478 *errorp = h_errno;
479 if (res == NULL)
480 return NULL;
481 memcpy(he, res, sizeof *he); /* XXX not sufficient */
482 return he;
260} 483}
261 484
485/* XXX RFC2133 expects a gethostbyname2_r() -- unimplemented */
486#endif
487
262struct hostent * 488struct hostent *
263gethostbyname(name) 489gethostbyname(name)
264 const char *name; 490 const char *name;
265{ 491{
266 querybuf buf; 492 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
493 struct hostent *hp;
494 extern struct hostent *_gethtbyname2();
495
496 if ((_resp->options & RES_INIT) == 0 && res_init() == -1)
497 hp = _gethtbyname2(name, AF_INET);
498
499 else if (_resp->options & RES_USE_INET6) {
500 hp = gethostbyname2(name, AF_INET6);
501 if (hp == NULL)
502 hp = gethostbyname2(name, AF_INET);
503 }
504 else
505 hp = gethostbyname2(name, AF_INET);
506 return hp;
507}
508
509struct hostent *
510gethostbyname2(name, af)
511 const char *name;
512 int af;
513{
514 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
515 querybuf *buf;
267 register const char *cp; 516 register const char *cp;
268 int n, i; 517 char *bp, *ep;
269 extern struct hostent *_gethtbyname(), *_yp_gethtbyname(); 518 int n, size, type, i;
519 extern struct hostent *_gethtbyname2(), *_yp_gethtbyname();
270 register struct hostent *hp; 520 register struct hostent *hp;
271 char lookups[MAXDNSLUS]; 521 char lookups[MAXDNSLUS];
272 522
523 if ((_resp->options & RES_INIT) == 0 && res_init() == -1)
524 return (_gethtbyname2(name, af));
525
526 switch (af) {
527 case AF_INET:
528 size = INADDRSZ;
529 type = T_A;
530 break;
531 case AF_INET6:
532 size = IN6ADDRSZ;
533 type = T_AAAA;
534 break;
535 default:
536 h_errno = NETDB_INTERNAL;
537 errno = EAFNOSUPPORT;
538 return (NULL);
539 }
540
541 host.h_addrtype = af;
542 host.h_length = size;
543
544 /*
545 * if there aren't any dots, it could be a user-level alias.
546 * this is also done in res_query() since we are not the only
547 * function that looks up host names.
548 */
549 if (!strchr(name, '.') && (cp = __hostalias(name)))
550 name = cp;
551
273 /* 552 /*
274 * disallow names consisting only of digits/dots, unless 553 * disallow names consisting only of digits/dots, unless
275 * they end in a dot. 554 * they end in a dot.
@@ -284,116 +563,230 @@ gethostbyname(name)
284 * Fake up a hostent as if we'd actually 563 * Fake up a hostent as if we'd actually
285 * done a lookup. 564 * done a lookup.
286 */ 565 */
287 if (!inet_aton(name, &host_addr)) { 566 if (inet_pton(af, name, host_addr) <= 0) {
288 h_errno = HOST_NOT_FOUND; 567 h_errno = HOST_NOT_FOUND;
289 return((struct hostent *) NULL); 568 return (NULL);
290 } 569 }
291 host.h_name = (char *)name; 570 strlcpy(hostbuf, name, MAXHOSTNAMELEN);
571 bp = hostbuf + MAXHOSTNAMELEN;
572 ep = hostbuf + sizeof(hostbuf);
573 host.h_name = hostbuf;
292 host.h_aliases = host_aliases; 574 host.h_aliases = host_aliases;
293 host_aliases[0] = NULL; 575 host_aliases[0] = NULL;
294 host.h_addrtype = AF_INET; 576 h_addr_ptrs[0] = (char *)host_addr;
295 host.h_length = sizeof(u_int32_t);
296 h_addr_ptrs[0] = (char *)&host_addr;
297 h_addr_ptrs[1] = NULL; 577 h_addr_ptrs[1] = NULL;
298 host.h_addr_list = h_addr_ptrs; 578 host.h_addr_list = h_addr_ptrs;
579 if (_resp->options & RES_USE_INET6)
580 map_v4v6_hostent(&host, &bp, ep);
581 h_errno = NETDB_SUCCESS;
299 return (&host); 582 return (&host);
300 } 583 }
301 if (!isdigit(*cp) && *cp != '.') 584 if (!isdigit(*cp) && *cp != '.')
302 break; 585 break;
303 } 586 }
587 if ((isxdigit(name[0]) && strchr(name, ':') != NULL) ||
588 name[0] == ':')
589 for (cp = name;; ++cp) {
590 if (!*cp) {
591 if (*--cp == '.')
592 break;
593 /*
594 * All-IPv6-legal, no dot at the end.
595 * Fake up a hostent as if we'd actually
596 * done a lookup.
597 */
598 if (inet_pton(af, name, host_addr) <= 0) {
599 h_errno = HOST_NOT_FOUND;
600 return (NULL);
601 }
602 strlcpy(hostbuf, name, MAXHOSTNAMELEN);
603 bp = hostbuf + MAXHOSTNAMELEN;
604 ep = hostbuf + sizeof(hostbuf);
605 host.h_name = hostbuf;
606 host.h_aliases = host_aliases;
607 host_aliases[0] = NULL;
608 h_addr_ptrs[0] = (char *)host_addr;
609 h_addr_ptrs[1] = NULL;
610 host.h_addr_list = h_addr_ptrs;
611 h_errno = NETDB_SUCCESS;
612 return (&host);
613 }
614 if (!isxdigit(*cp) && *cp != ':' && *cp != '.')
615 break;
616 }
304 617
305 if ((_res.options & RES_INIT) == 0 && res_init() == -1) 618 bcopy(_resp->lookups, lookups, sizeof lookups);
306 return (_gethtbyname(name));
307
308 bcopy(_res.lookups, lookups, sizeof lookups);
309 if (lookups[0] == '\0') 619 if (lookups[0] == '\0')
310 strncpy(lookups, "bf", sizeof lookups); 620 strlcpy(lookups, "bf", sizeof lookups);
311 621
312 hp = (struct hostent *)NULL; 622 hp = (struct hostent *)NULL;
313 for (i = 0; i < MAXDNSLUS && hp == NULL && lookups[i]; i++) { 623 for (i = 0; i < MAXDNSLUS && hp == NULL && lookups[i]; i++) {
314 switch (lookups[i]) { 624 switch (lookups[i]) {
315#ifdef YP 625#ifdef YP
316 case 'y': 626 case 'y':
317 hp = _yp_gethtbyname(name); 627 /* YP only supports AF_INET. */
628 if (af == AF_INET)
629 hp = _yp_gethtbyname(name);
318 break; 630 break;
319#endif 631#endif
320 case 'b': 632 case 'b':
321 if ((n = res_search(name, C_IN, T_A, buf.buf, 633 buf = malloc(sizeof(*buf));
322 sizeof(buf))) < 0) { 634 if (buf == NULL)
635 break;
636 if ((n = res_search(name, C_IN, type, buf->buf,
637 sizeof(buf->buf))) < 0) {
638 free(buf);
323#ifdef DEBUG 639#ifdef DEBUG
324 if (_res.options & RES_DEBUG) 640 if (_resp->options & RES_DEBUG)
325 printf("res_search failed\n"); 641 printf("res_search failed\n");
326#endif 642#endif
327 break; 643 break;
328 } 644 }
329 hp = getanswer(&buf, n, 0); 645 hp = getanswer(buf, n, name, type);
646 free(buf);
330 break; 647 break;
331 case 'f': 648 case 'f':
332 hp = _gethtbyname(name); 649 hp = _gethtbyname2(name, af);
333 break; 650 break;
334 } 651 }
335 } 652 }
653 /* XXX h_errno not correct in all cases... */
336 return (hp); 654 return (hp);
337} 655}
338 656
339struct hostent * 657struct hostent *
340gethostbyaddr(addr, len, type) 658gethostbyaddr(addr, len, af)
341 const char *addr; 659 const char *addr; /* XXX should have been def'd as u_char! */
342 int len, type; 660 int len, af;
343{ 661{
344 int n, i; 662 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
345 querybuf buf; 663 const u_char *uaddr = (const u_char *)addr;
664 int n, size, i;
665 querybuf *buf;
346 register struct hostent *hp; 666 register struct hostent *hp;
347 char qbuf[MAXDNAME]; 667 char qbuf[MAXDNAME+1], *qp, *ep;
348 extern struct hostent *_gethtbyaddr(), *_yp_gethtbyaddr(); 668 extern struct hostent *_gethtbyaddr(), *_yp_gethtbyaddr();
349 char lookups[MAXDNSLUS]; 669 char lookups[MAXDNSLUS];
670 struct hostent *res;
350 671
351 if (type != AF_INET) 672 if ((_resp->options & RES_INIT) == 0 && res_init() == -1) {
352 return ((struct hostent *) NULL); 673 res = _gethtbyaddr(addr, len, af);
353 (void)sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa", 674 return (res);
354 ((unsigned)addr[3] & 0xff), 675 }
355 ((unsigned)addr[2] & 0xff), 676
356 ((unsigned)addr[1] & 0xff), 677 if (af == AF_INET6 && len == IN6ADDRSZ &&
357 ((unsigned)addr[0] & 0xff)); 678 (IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)uaddr) ||
358 679 IN6_IS_ADDR_SITELOCAL((struct in6_addr *)uaddr))) {
359 if ((_res.options & RES_INIT) == 0 && res_init() == -1) 680 h_errno = HOST_NOT_FOUND;
360 return (_gethtbyaddr(addr, len, type)); 681 return (NULL);
361 682 }
362 bcopy(_res.lookups, lookups, sizeof lookups); 683 if (af == AF_INET6 && len == IN6ADDRSZ &&
684 (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)uaddr) ||
685 IN6_IS_ADDR_V4COMPAT((struct in6_addr *)uaddr))) {
686 /* Unmap. */
687 addr += IN6ADDRSZ - INADDRSZ;
688 uaddr += IN6ADDRSZ - INADDRSZ;
689 af = AF_INET;
690 len = INADDRSZ;
691 }
692 switch (af) {
693 case AF_INET:
694 size = INADDRSZ;
695 break;
696 case AF_INET6:
697 size = IN6ADDRSZ;
698 break;
699 default:
700 errno = EAFNOSUPPORT;
701 h_errno = NETDB_INTERNAL;
702 return (NULL);
703 }
704 if (size != len) {
705 errno = EINVAL;
706 h_errno = NETDB_INTERNAL;
707 return (NULL);
708 }
709 ep = qbuf + sizeof(qbuf);
710 switch (af) {
711 case AF_INET:
712 (void) snprintf(qbuf, sizeof qbuf, "%u.%u.%u.%u.in-addr.arpa",
713 (uaddr[3] & 0xff), (uaddr[2] & 0xff),
714 (uaddr[1] & 0xff), (uaddr[0] & 0xff));
715 break;
716 case AF_INET6:
717 qp = qbuf;
718 for (n = IN6ADDRSZ - 1; n >= 0; n--) {
719 i = snprintf(qp, ep - qp, "%x.%x.",
720 uaddr[n] & 0xf, (uaddr[n] >> 4) & 0xf);
721 if (i <= 0) {
722 errno = EINVAL;
723 h_errno = NETDB_INTERNAL;
724 return (NULL);
725 }
726 qp += i;
727 }
728 break;
729 }
730
731 bcopy(_resp->lookups, lookups, sizeof lookups);
363 if (lookups[0] == '\0') 732 if (lookups[0] == '\0')
364 strncpy(lookups, "bf", sizeof lookups); 733 strlcpy(lookups, "bf", sizeof lookups);
365 734
366 hp = (struct hostent *)NULL; 735 hp = (struct hostent *)NULL;
367 for (i = 0; i < MAXDNSLUS && hp == NULL && lookups[i]; i++) { 736 for (i = 0; i < MAXDNSLUS && hp == NULL && lookups[i]; i++) {
368 switch (lookups[i]) { 737 switch (lookups[i]) {
369#ifdef YP 738#ifdef YP
370 case 'y': 739 case 'y':
371 hp = _yp_gethtbyaddr(addr, len, type); 740 /* YP only supports AF_INET. */
741 if (af == AF_INET)
742 hp = _yp_gethtbyaddr(addr);
372 break; 743 break;
373#endif 744#endif
374 case 'b': 745 case 'b':
375 n = res_query(qbuf, C_IN, T_PTR, (char *)&buf, sizeof(buf)); 746 if (af == AF_INET6)
747 strlcpy(qp, "ip6.arpa", ep - qp);
748 buf = malloc(sizeof(*buf));
749 if (!buf)
750 break;
751 n = res_query(qbuf, C_IN, T_PTR, buf->buf,
752 sizeof(buf->buf));
753 if (n < 0 && af == AF_INET6) {
754 strlcpy(qp, "ip6.int", ep - qp);
755 n = res_query(qbuf, C_IN, T_PTR,
756 buf->buf, sizeof(buf->buf));
757 }
376 if (n < 0) { 758 if (n < 0) {
759 free(buf);
377#ifdef DEBUG 760#ifdef DEBUG
378 if (_res.options & RES_DEBUG) 761 if (_resp->options & RES_DEBUG)
379 printf("res_query failed\n"); 762 printf("res_query failed\n");
380#endif 763#endif
381 break; 764 break;
382 } 765 }
383 hp = getanswer(&buf, n, 1); 766 if (!(hp = getanswer(buf, n, qbuf, T_PTR))) {
384 if (hp == NULL) 767 free(buf);
385 break; 768 break;
386 hp->h_addrtype = type; 769 }
770 free(buf);
771 hp->h_addrtype = af;
387 hp->h_length = len; 772 hp->h_length = len;
388 h_addr_ptrs[0] = (char *)&host_addr; 773 bcopy(addr, host_addr, len);
389 h_addr_ptrs[1] = (char *)0; 774 h_addr_ptrs[0] = (char *)host_addr;
390 host_addr = *(struct in_addr *)addr; 775 h_addr_ptrs[1] = NULL;
776 if (af == AF_INET && (_resp->options & RES_USE_INET6)) {
777 map_v4v6_address((char*)host_addr,
778 (char*)host_addr);
779 hp->h_addrtype = AF_INET6;
780 hp->h_length = IN6ADDRSZ;
781 }
782 h_errno = NETDB_SUCCESS;
391 break; 783 break;
392 case 'f': 784 case 'f':
393 hp = _gethtbyaddr(addr, len, type); 785 hp = _gethtbyaddr(addr, len, af);
394 break; 786 break;
395 } 787 }
396 } 788 }
789 /* XXX h_errno not correct in all cases... */
397 return (hp); 790 return (hp);
398} 791}
399 792
@@ -420,37 +813,64 @@ _endhtent()
420struct hostent * 813struct hostent *
421_gethtent() 814_gethtent()
422{ 815{
816 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
423 char *p; 817 char *p;
424 register char *cp, **q; 818 register char *cp, **q;
819 int af;
820 size_t len;
425 821
426 if (hostf == NULL && (hostf = fopen(_PATH_HOSTS, "r" )) == NULL) 822 if (!hostf && !(hostf = fopen(_PATH_HOSTS, "r" ))) {
823 h_errno = NETDB_INTERNAL;
427 return (NULL); 824 return (NULL);
428again: 825 }
429 if ((p = fgets(hostbuf, BUFSIZ, hostf)) == NULL) 826 again:
827 if ((p = fgetln(hostf, &len)) == NULL) {
828 h_errno = HOST_NOT_FOUND;
430 return (NULL); 829 return (NULL);
830 }
831 if (p[len-1] == '\n')
832 len--;
833 if (len >= sizeof(hostbuf) || len == 0)
834 goto again;
835 p = memcpy(hostbuf, p, len);
836 hostbuf[len] = '\0';
431 if (*p == '#') 837 if (*p == '#')
432 goto again; 838 goto again;
433 cp = strpbrk(p, "#\n"); 839 if ((cp = strchr(p, '#')))
434 if (cp == NULL) 840 *cp = '\0';
435 goto again; 841 if (!(cp = strpbrk(p, " \t")))
436 *cp = '\0';
437 cp = strpbrk(p, " \t");
438 if (cp == NULL)
439 goto again; 842 goto again;
440 *cp++ = '\0'; 843 *cp++ = '\0';
441 /* THIS STUFF IS INTERNET SPECIFIC */ 844 if (inet_pton(AF_INET6, p, host_addr) > 0) {
442 h_addr_ptrs[0] = (char *)&host_addr; 845 af = AF_INET6;
846 len = IN6ADDRSZ;
847 } else if (inet_pton(AF_INET, p, host_addr) > 0) {
848 if (_resp->options & RES_USE_INET6) {
849 map_v4v6_address((char*)host_addr, (char*)host_addr);
850 af = AF_INET6;
851 len = IN6ADDRSZ;
852 } else {
853 af = AF_INET;
854 len = INADDRSZ;
855 }
856 } else {
857 goto again;
858 }
859 /* if this is not something we're looking for, skip it. */
860 if (host.h_addrtype != af)
861 goto again;
862 if (host.h_length != len)
863 goto again;
864 h_addr_ptrs[0] = (char *)host_addr;
443 h_addr_ptrs[1] = NULL; 865 h_addr_ptrs[1] = NULL;
444 (void) inet_aton(p, &host_addr);
445 host.h_addr_list = h_addr_ptrs; 866 host.h_addr_list = h_addr_ptrs;
446 host.h_length = sizeof(u_int32_t); 867 host.h_length = len;
447 host.h_addrtype = AF_INET; 868 host.h_addrtype = af;
448 while (*cp == ' ' || *cp == '\t') 869 while (*cp == ' ' || *cp == '\t')
449 cp++; 870 cp++;
450 host.h_name = cp; 871 host.h_name = cp;
451 q = host.h_aliases = host_aliases; 872 q = host.h_aliases = host_aliases;
452 cp = strpbrk(cp, " \t"); 873 if ((cp = strpbrk(cp, " \t")))
453 if (cp != NULL)
454 *cp++ = '\0'; 874 *cp++ = '\0';
455 while (cp && *cp) { 875 while (cp && *cp) {
456 if (*cp == ' ' || *cp == '\t') { 876 if (*cp == ' ' || *cp == '\t') {
@@ -459,70 +879,77 @@ again:
459 } 879 }
460 if (q < &host_aliases[MAXALIASES - 1]) 880 if (q < &host_aliases[MAXALIASES - 1])
461 *q++ = cp; 881 *q++ = cp;
462 cp = strpbrk(cp, " \t"); 882 if ((cp = strpbrk(cp, " \t")))
463 if (cp != NULL)
464 *cp++ = '\0'; 883 *cp++ = '\0';
465 } 884 }
466 *q = NULL; 885 *q = NULL;
886 if (_resp->options & RES_USE_INET6) {
887 char *bp = hostbuf;
888 char *ep = hostbuf + sizeof hostbuf;
889
890 map_v4v6_hostent(&host, &bp, ep);
891 }
892 h_errno = NETDB_SUCCESS;
467 return (&host); 893 return (&host);
468} 894}
469 895
470struct hostent * 896struct hostent *
471_gethtbyname(name) 897_gethtbyname(name)
472 char *name; 898 const char *name;
899{
900 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
901 extern struct hostent *_gethtbyname2();
902 struct hostent *hp;
903
904 if (_resp->options & RES_USE_INET6) {
905 hp = _gethtbyname2(name, AF_INET6);
906 if (hp)
907 return (hp);
908 }
909 return (_gethtbyname2(name, AF_INET));
910}
911
912struct hostent *
913_gethtbyname2(name, af)
914 const char *name;
915 int af;
473{ 916{
474 register struct hostent *p; 917 register struct hostent *p;
475 register char **cp; 918 register char **cp;
476 919
477 _sethtent(0); 920 _sethtent(0);
478 while (p = _gethtent()) { 921 while ((p = _gethtent())) {
922 if (p->h_addrtype != af)
923 continue;
479 if (strcasecmp(p->h_name, name) == 0) 924 if (strcasecmp(p->h_name, name) == 0)
480 break; 925 break;
481 for (cp = p->h_aliases; *cp != 0; cp++) 926 for (cp = p->h_aliases; *cp != 0; cp++)
482 if (strcasecmp(*cp, name) == 0) 927 if (strcasecmp(*cp, name) == 0)
483 goto found; 928 goto found;
484 } 929 }
485found: 930 found:
486 _endhtent(); 931 _endhtent();
487 if (p==NULL)
488 h_errno = HOST_NOT_FOUND;
489 return (p); 932 return (p);
490} 933}
491 934
492struct hostent * 935struct hostent *
493_gethtbyaddr(addr, len, type) 936_gethtbyaddr(addr, len, af)
494 const char *addr; 937 const char *addr;
495 int len, type; 938 int len, af;
496{ 939{
497 register struct hostent *p; 940 register struct hostent *p;
498 941
942 host.h_length = len;
943 host.h_addrtype = af;
944
499 _sethtent(0); 945 _sethtent(0);
500 while (p = _gethtent()) 946 while ((p = _gethtent()))
501 if (p->h_addrtype == type && !bcmp(p->h_addr, addr, len)) 947 if (p->h_addrtype == af && !bcmp(p->h_addr, addr, len))
502 break; 948 break;
503 _endhtent(); 949 _endhtent();
504 if (p==NULL)
505 h_errno = HOST_NOT_FOUND;
506 return (p); 950 return (p);
507} 951}
508 952
509static int
510qcomp(a1, a2)
511 struct in_addr **a1, **a2;
512{
513 int pos1, pos2;
514
515 for (pos1 = 0; pos1 < _res.nsort; pos1++)
516 if (_res.sort_list[pos1].addr.s_addr ==
517 ((*a1)->s_addr & _res.sort_list[pos1].mask))
518 break;
519 for (pos2 = 0; pos2 < _res.nsort; pos2++)
520 if (_res.sort_list[pos2].addr.s_addr ==
521 ((*a2)->s_addr & _res.sort_list[pos2].mask))
522 break;
523 return pos1 - pos2;
524}
525
526#ifdef YP 953#ifdef YP
527struct hostent * 954struct hostent *
528_yphostent(line) 955_yphostent(line)
@@ -537,21 +964,21 @@ _yphostent(line)
537 964
538 host.h_name = NULL; 965 host.h_name = NULL;
539 host.h_addr_list = h_addr_ptrs; 966 host.h_addr_list = h_addr_ptrs;
540 host.h_length = sizeof(u_int32_t); 967 host.h_length = INADDRSZ;
541 host.h_addrtype = AF_INET; 968 host.h_addrtype = AF_INET;
542 hap = h_addr_ptrs; 969 hap = h_addr_ptrs;
543 buf = host_addrs; 970 buf = host_addrs;
544 q = host.h_aliases = host_aliases; 971 q = host.h_aliases = host_aliases;
545 972
546nextline: 973nextline:
974 /* check for host_addrs overflow */
975 if (buf >= &host_addrs[sizeof(host_addrs) / sizeof(host_addrs[0])])
976 goto done;
977
547 more = 0; 978 more = 0;
548 cp = strpbrk(p, " \t"); 979 cp = strpbrk(p, " \t");
549 if (cp == NULL) { 980 if (cp == NULL)
550 if (host.h_name == NULL) 981 goto done;
551 return (NULL);
552 else
553 goto done;
554 }
555 *cp++ = '\0'; 982 *cp++ = '\0';
556 983
557 *hap++ = (char *)buf; 984 *hap++ = (char *)buf;
@@ -592,30 +1019,29 @@ nextline:
592 *cp++ = '\0'; 1019 *cp++ = '\0';
593 } 1020 }
594done: 1021done:
1022 if (host.h_name == NULL)
1023 return (NULL);
595 *q = NULL; 1024 *q = NULL;
596 *hap = NULL; 1025 *hap = NULL;
597 return (&host); 1026 return (&host);
598} 1027}
599 1028
600struct hostent * 1029struct hostent *
601_yp_gethtbyaddr(addr, len, type) 1030_yp_gethtbyaddr(addr)
602 const char *addr; 1031 const char *addr;
603 int len, type;
604{ 1032{
605 struct hostent *hp = (struct hostent *)NULL; 1033 struct hostent *hp = (struct hostent *)NULL;
606 static char *__ypcurrent; 1034 static char *__ypcurrent;
607 int __ypcurrentlen, r; 1035 int __ypcurrentlen, r;
608 char name[sizeof("xxx.xxx.xxx.xxx") + 1]; 1036 char name[sizeof("xxx.xxx.xxx.xxx")];
609 1037
610 if (!__ypdomain) { 1038 if (!__ypdomain) {
611 if (_yp_check(&__ypdomain) == 0) 1039 if (_yp_check(&__ypdomain) == 0)
612 return (hp); 1040 return (hp);
613 } 1041 }
614 sprintf(name, "%u.%u.%u.%u", 1042 snprintf(name, sizeof name, "%u.%u.%u.%u",
615 ((unsigned)addr[0] & 0xff), 1043 ((unsigned)addr[0] & 0xff), ((unsigned)addr[1] & 0xff),
616 ((unsigned)addr[1] & 0xff), 1044 ((unsigned)addr[2] & 0xff), ((unsigned)addr[3] & 0xff));
617 ((unsigned)addr[2] & 0xff),
618 ((unsigned)addr[3] & 0xff));
619 if (__ypcurrent) 1045 if (__ypcurrent)
620 free(__ypcurrent); 1046 free(__ypcurrent);
621 __ypcurrent = NULL; 1047 __ypcurrent = NULL;
@@ -636,6 +1062,8 @@ _yp_gethtbyname(name)
636 static char *__ypcurrent; 1062 static char *__ypcurrent;
637 int __ypcurrentlen, r; 1063 int __ypcurrentlen, r;
638 1064
1065 if (strlen(name) >= MAXHOSTNAMELEN)
1066 return (NULL);
639 if (!__ypdomain) { 1067 if (!__ypdomain) {
640 if (_yp_check(&__ypdomain) == 0) 1068 if (_yp_check(&__ypdomain) == 0)
641 return (hp); 1069 return (hp);
@@ -645,10 +1073,108 @@ _yp_gethtbyname(name)
645 __ypcurrent = NULL; 1073 __ypcurrent = NULL;
646 r = yp_match(__ypdomain, "hosts.byname", name, 1074 r = yp_match(__ypdomain, "hosts.byname", name,
647 strlen(name), &__ypcurrent, &__ypcurrentlen); 1075 strlen(name), &__ypcurrent, &__ypcurrentlen);
648 if (r==0) 1076 if (r == 0)
649 hp = _yphostent(__ypcurrent); 1077 hp = _yphostent(__ypcurrent);
650 if (hp==NULL) 1078 if (hp == NULL)
651 h_errno = HOST_NOT_FOUND; 1079 h_errno = HOST_NOT_FOUND;
652 return (hp); 1080 return (hp);
653} 1081}
654#endif 1082#endif
1083
1084static void
1085map_v4v6_address(src, dst)
1086 const char *src;
1087 char *dst;
1088{
1089 u_char *p = (u_char *)dst;
1090 char tmp[INADDRSZ];
1091 int i;
1092
1093 /* Stash a temporary copy so our caller can update in place. */
1094 bcopy(src, tmp, INADDRSZ);
1095 /* Mark this ipv6 addr as a mapped ipv4. */
1096 for (i = 0; i < 10; i++)
1097 *p++ = 0x00;
1098 *p++ = 0xff;
1099 *p++ = 0xff;
1100 /* Retrieve the saved copy and we're done. */
1101 bcopy(tmp, (void*)p, INADDRSZ);
1102}
1103
1104static void
1105map_v4v6_hostent(hp, bpp, ep)
1106 struct hostent *hp;
1107 char **bpp;
1108 char *ep;
1109{
1110 char **ap;
1111
1112 if (hp->h_addrtype != AF_INET || hp->h_length != INADDRSZ)
1113 return;
1114 hp->h_addrtype = AF_INET6;
1115 hp->h_length = IN6ADDRSZ;
1116 for (ap = hp->h_addr_list; *ap; ap++) {
1117 int i = sizeof(align) - ((u_long)*bpp % sizeof(align));
1118
1119 if (ep - *bpp < (i + IN6ADDRSZ)) {
1120 /* Out of memory. Truncate address list here. XXX */
1121 *ap = NULL;
1122 return;
1123 }
1124 *bpp += i;
1125 map_v4v6_address(*ap, *bpp);
1126 *ap = *bpp;
1127 *bpp += IN6ADDRSZ;
1128 }
1129}
1130
1131struct hostent *
1132gethostent()
1133{
1134 return (_gethtent());
1135}
1136
1137#ifdef RESOLVSORT
1138static void
1139addrsort(ap, num)
1140 char **ap;
1141 int num;
1142{
1143 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
1144 int i, j;
1145 char **p;
1146 short aval[MAXADDRS];
1147 int needsort = 0;
1148
1149 p = ap;
1150 for (i = 0; i < num; i++, p++) {
1151 for (j = 0 ; (unsigned)j < _resp->nsort; j++)
1152 if (_resp->sort_list[j].addr.s_addr ==
1153 (((struct in_addr *)(*p))->s_addr & _resp->sort_list[j].mask))
1154 break;
1155 aval[i] = j;
1156 if (needsort == 0 && i > 0 && j < aval[i-1])
1157 needsort = i;
1158 }
1159 if (!needsort)
1160 return;
1161
1162 while (needsort < num) {
1163 for (j = needsort - 1; j >= 0; j--) {
1164 if (aval[j] > aval[j+1]) {
1165 char *hp;
1166
1167 i = aval[j];
1168 aval[j] = aval[j+1];
1169 aval[j+1] = i;
1170
1171 hp = ap[j];
1172 ap[j] = ap[j+1];
1173 ap[j+1] = hp;
1174 } else
1175 break;
1176 }
1177 needsort++;
1178 }
1179}
1180#endif
diff --git a/src/lib/libc/net/getifaddrs.3 b/src/lib/libc/net/getifaddrs.3
new file mode 100644
index 0000000000..03064689cd
--- /dev/null
+++ b/src/lib/libc/net/getifaddrs.3
@@ -0,0 +1,159 @@
1.\" $OpenBSD: getifaddrs.3,v 1.9 2003/03/06 04:07:37 david Exp $
2.\" BSDI getifaddrs.3,v 2.5 2000/02/23 14:51:59 dab Exp
3.\"
4.\" Copyright (c) 1995, 1999
5.\" Berkeley Software Design, Inc. All rights reserved.
6.\"
7.\" Redistribution and use in source and binary forms, with or without
8.\" modification, are permitted provided that the following conditions
9.\" are met:
10.\" 1. Redistributions of source code must retain the above copyright
11.\" notice, this list of conditions and the following disclaimer.
12.\"
13.\" THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
14.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16.\" ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
17.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23.\" SUCH DAMAGE.
24.Dd October 12, 1995
25.Dt GETIFADDRS 3
26.Os
27.Sh NAME
28.Nm getifaddrs
29.Nd get interface addresses
30.Sh SYNOPSIS
31.Fd #include <sys/types.h>
32.Fd #include <sys/socket.h>
33.Fd #include <ifaddrs.h>
34.Ft int
35.Fn getifaddrs "struct ifaddrs **ifap"
36.Ft void
37.Fn freeifaddrs "struct ifaddrs *ifap"
38.Sh DESCRIPTION
39The
40.Fn getifaddrs
41function stores a reference to a linked list of the network interfaces
42on the local machine in the memory referenced by
43.Fa ifap .
44The list consists of
45.Nm ifaddrs
46structures, as defined in the include file
47.Aq Pa ifaddrs.h .
48The
49.Nm ifaddrs
50structure contains at least the following entries:
51.Bd -literal
52 struct ifaddrs *ifa_next; /* Pointer to next struct */
53 char *ifa_name; /* Interface name */
54 u_int ifa_flags; /* Interface flags */
55 struct sockaddr *ifa_addr; /* Interface address */
56 struct sockaddr *ifa_netmask; /* Interface netmask */
57 struct sockaddr *ifa_broadaddr; /* Interface broadcast address */
58 struct sockaddr *ifa_dstaddr; /* P2P interface destination */
59 void *ifa_data; /* Address specific data */
60.Ed
61.Pp
62.Bl -tag -width Ds
63.It Fa ifa_next
64Contains a pointer to the next structure on the list.
65This field is set to
66.Dv NULL
67in last structure on the list.
68.It Fa ifa_name
69Contains the interface name.
70.It Fa ifa_flags
71Contains the interface flags, as set by
72.Xr ifconfig 8 .
73.It Fa ifa_addr
74References either the address of the interface or the link level
75address of the interface, if one exists, otherwise it is
76.Dv NULL .
77(The
78.Fa sa_family
79field of the
80.Fa ifa_addr
81field should be consulted to determine the format of the
82.Fa ifa_addr
83address.)
84.It Fa ifa_netmask
85References the netmask associated with
86.Fa ifa_addr ,
87if one is set, otherwise it is
88.Dv NULL .
89.It Fa ifa_broadaddr
90This field, which should only be referenced for non-P2P interfaces,
91references the broadcast address associated with
92.Fa ifa_addr ,
93if one exists, otherwise it is
94.Dv NULL .
95.It Fa ifa_dstaddr
96References the destination address on a P2P interface,
97if one exists, otherwise it is
98.Dv NULL .
99.It Fa ifa_data
100References address family specific data.
101For
102.Dv AF_LINK
103addresses it contains a pointer to the
104.Li struct if_data
105(as defined in include file
106.Aq Pa net/if.h )
107which contains various interface attributes and statistics.
108For all other address families, it contains a pointer to the
109.Li struct ifa_data
110(as defined in include file
111.Aq Pa net/if.h )
112which contains per-address interface statistics.
113.El
114.Pp
115The data returned by
116.Fn getifaddrs
117is dynamically allocated and should be freed using
118.Fn freeifaddrs
119when no longer needed.
120.Sh RETURN VALUES
121Upon successful completion, a value of 0 is returned.
122Otherwise, a value of \-1 is returned and
123.Va errno
124is set to indicate the error.
125.Sh ERRORS
126The
127.Fn getifaddrs
128may fail and set
129.Va errno
130for any of the errors specified for the library routines
131.Xr ioctl 2 ,
132.Xr socket 2 ,
133.Xr malloc 3 ,
134or
135.Xr sysctl 3 .
136.Sh BUGS
137If both
138.Aq Pa net/if.h
139and
140.Aq Pa ifaddrs.h
141are being included,
142.Aq Pa net/if.h
143.Em must
144be included before
145.Aq Pa ifaddrs.h .
146.Sh SEE ALSO
147.Xr ioctl 2 ,
148.Xr socket 2 ,
149.Xr sysctl 3 ,
150.Xr networking 4 ,
151.Xr ifconfig 8
152.Sh HISTORY
153The
154.Fn getifaddrs
155function first appeared in BSDI BSD/OS.
156The function is supplied on
157.Ox
158since
159.Ox 2.7 .
diff --git a/src/lib/libc/net/getifaddrs.c b/src/lib/libc/net/getifaddrs.c
new file mode 100644
index 0000000000..0db89f6c19
--- /dev/null
+++ b/src/lib/libc/net/getifaddrs.c
@@ -0,0 +1,277 @@
1/* $OpenBSD: getifaddrs.c,v 1.9 2002/08/09 06:12:25 itojun Exp $ */
2
3/*
4 * Copyright (c) 1995, 1999
5 * Berkeley Software Design, Inc. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 *
25 * BSDI getifaddrs.c,v 2.12 2000/02/23 14:51:59 dab Exp
26 */
27
28#include <sys/types.h>
29#include <sys/ioctl.h>
30#include <sys/socket.h>
31#include <net/if.h>
32#include <sys/param.h>
33#include <net/route.h>
34#include <sys/sysctl.h>
35#include <net/if_dl.h>
36
37#include <errno.h>
38#include <ifaddrs.h>
39#include <stdlib.h>
40#include <string.h>
41#include <unistd.h>
42
43#define SALIGN (sizeof(long) - 1)
44#define SA_RLEN(sa) ((sa)->sa_len ? (((sa)->sa_len + SALIGN) & ~SALIGN) : (SALIGN + 1))
45
46int
47getifaddrs(struct ifaddrs **pif)
48{
49 int icnt = 1;
50 int dcnt = 0;
51 int ncnt = 0;
52 int mib[6];
53 size_t needed;
54 char *buf;
55 char *next;
56 struct ifaddrs *cif = 0;
57 char *p, *p0;
58 struct rt_msghdr *rtm;
59 struct if_msghdr *ifm;
60 struct ifa_msghdr *ifam;
61 struct sockaddr_dl *dl;
62 struct sockaddr *sa;
63 u_short index = 0;
64 size_t len, alen;
65 struct ifaddrs *ifa, *ift;
66 int i;
67 char *data;
68 char *names;
69
70 mib[0] = CTL_NET;
71 mib[1] = PF_ROUTE;
72 mib[2] = 0; /* protocol */
73 mib[3] = 0; /* wildcard address family */
74 mib[4] = NET_RT_IFLIST;
75 mib[5] = 0; /* no flags */
76 if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
77 return (-1);
78 if ((buf = malloc(needed)) == NULL)
79 return (-1);
80 if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
81 free(buf);
82 return (-1);
83 }
84
85 for (next = buf; next < buf + needed; next += rtm->rtm_msglen) {
86 rtm = (struct rt_msghdr *)next;
87 if (rtm->rtm_version != RTM_VERSION)
88 continue;
89 switch (rtm->rtm_type) {
90 case RTM_IFINFO:
91 ifm = (struct if_msghdr *)rtm;
92 if (ifm->ifm_addrs & RTA_IFP) {
93 index = ifm->ifm_index;
94 ++icnt;
95 dl = (struct sockaddr_dl *)(ifm + 1);
96 dcnt += SA_RLEN((struct sockaddr *)dl) +
97 ALIGNBYTES;
98 dcnt += sizeof(ifm->ifm_data);
99 ncnt += dl->sdl_nlen + 1;
100 } else
101 index = 0;
102 break;
103
104 case RTM_NEWADDR:
105 ifam = (struct ifa_msghdr *)rtm;
106 if (index && ifam->ifam_index != index)
107 abort(); /* XXX abort illegal in library */
108
109#define RTA_MASKS (RTA_NETMASK | RTA_IFA | RTA_BRD)
110 if (index == 0 || (ifam->ifam_addrs & RTA_MASKS) == 0)
111 break;
112 p = (char *)(ifam + 1);
113 ++icnt;
114 /* Scan to look for length of address */
115 alen = 0;
116 for (p0 = p, i = 0; i < RTAX_MAX; i++) {
117 if ((RTA_MASKS & ifam->ifam_addrs & (1 << i))
118 == 0)
119 continue;
120 sa = (struct sockaddr *)p;
121 len = SA_RLEN(sa);
122 if (i == RTAX_IFA) {
123 alen = len;
124 break;
125 }
126 p += len;
127 }
128 for (p = p0, i = 0; i < RTAX_MAX; i++) {
129 if ((RTA_MASKS & ifam->ifam_addrs & (1 << i))
130 == 0)
131 continue;
132 sa = (struct sockaddr *)p;
133 len = SA_RLEN(sa);
134 if (i == RTAX_NETMASK && sa->sa_len == 0)
135 dcnt += alen;
136 else
137 dcnt += len;
138 p += len;
139 }
140 break;
141 }
142 }
143
144 if (icnt + dcnt + ncnt == 1) {
145 *pif = NULL;
146 free(buf);
147 return (0);
148 }
149 data = malloc(sizeof(struct ifaddrs) * icnt + dcnt + ncnt);
150 if (data == NULL) {
151 free(buf);
152 return(-1);
153 }
154
155 ifa = (struct ifaddrs *)data;
156 data += sizeof(struct ifaddrs) * icnt;
157 names = data + dcnt;
158
159 memset(ifa, 0, sizeof(struct ifaddrs) * icnt);
160 ift = ifa;
161
162 index = 0;
163 for (next = buf; next < buf + needed; next += rtm->rtm_msglen) {
164 rtm = (struct rt_msghdr *)next;
165 if (rtm->rtm_version != RTM_VERSION)
166 continue;
167 switch (rtm->rtm_type) {
168 case RTM_IFINFO:
169 ifm = (struct if_msghdr *)rtm;
170 if (ifm->ifm_addrs & RTA_IFP) {
171 index = ifm->ifm_index;
172 dl = (struct sockaddr_dl *)(ifm + 1);
173
174 cif = ift;
175 ift->ifa_name = names;
176 ift->ifa_flags = (int)ifm->ifm_flags;
177 memcpy(names, dl->sdl_data, dl->sdl_nlen);
178 names[dl->sdl_nlen] = 0;
179 names += dl->sdl_nlen + 1;
180
181 ift->ifa_addr = (struct sockaddr *)data;
182 memcpy(data, dl,
183 ((struct sockaddr *)dl)->sa_len);
184 data += SA_RLEN((struct sockaddr *)dl);
185
186 /* ifm_data needs to be aligned */
187 ift->ifa_data = data = (void *)ALIGN(data);
188 memcpy(data, &ifm->ifm_data, sizeof(ifm->ifm_data));
189 data += sizeof(ifm->ifm_data);
190
191 ift = (ift->ifa_next = ift + 1);
192 } else
193 index = 0;
194 break;
195
196 case RTM_NEWADDR:
197 ifam = (struct ifa_msghdr *)rtm;
198 if (index && ifam->ifam_index != index)
199 abort(); /* XXX abort illegal in library */
200
201 if (index == 0 || (ifam->ifam_addrs & RTA_MASKS) == 0)
202 break;
203 ift->ifa_name = cif->ifa_name;
204 ift->ifa_flags = cif->ifa_flags;
205 ift->ifa_data = NULL;
206 p = (char *)(ifam + 1);
207 /* Scan to look for length of address */
208 alen = 0;
209 for (p0 = p, i = 0; i < RTAX_MAX; i++) {
210 if ((RTA_MASKS & ifam->ifam_addrs & (1 << i))
211 == 0)
212 continue;
213 sa = (struct sockaddr *)p;
214 len = SA_RLEN(sa);
215 if (i == RTAX_IFA) {
216 alen = len;
217 break;
218 }
219 p += len;
220 }
221 for (p = p0, i = 0; i < RTAX_MAX; i++) {
222 if ((RTA_MASKS & ifam->ifam_addrs & (1 << i))
223 == 0)
224 continue;
225 sa = (struct sockaddr *)p;
226 len = SA_RLEN(sa);
227 switch (i) {
228 case RTAX_IFA:
229 ift->ifa_addr = (struct sockaddr *)data;
230 memcpy(data, p, len);
231 data += len;
232 break;
233
234 case RTAX_NETMASK:
235 ift->ifa_netmask =
236 (struct sockaddr *)data;
237 if (sa->sa_len == 0) {
238 memset(data, 0, alen);
239 data += alen;
240 break;
241 }
242 memcpy(data, p, len);
243 data += len;
244 break;
245
246 case RTAX_BRD:
247 ift->ifa_broadaddr =
248 (struct sockaddr *)data;
249 memcpy(data, p, len);
250 data += len;
251 break;
252 }
253 p += len;
254 }
255
256
257 ift = (ift->ifa_next = ift + 1);
258 break;
259 }
260 }
261
262 free(buf);
263 if (--ift >= ifa) {
264 ift->ifa_next = NULL;
265 *pif = ifa;
266 } else {
267 *pif = NULL;
268 free(ifa);
269 }
270 return (0);
271}
272
273void
274freeifaddrs(struct ifaddrs *ifp)
275{
276 free(ifp);
277}
diff --git a/src/lib/libc/net/getnameinfo.3 b/src/lib/libc/net/getnameinfo.3
new file mode 100644
index 0000000000..24fb89d838
--- /dev/null
+++ b/src/lib/libc/net/getnameinfo.3
@@ -0,0 +1,297 @@
1.\" $OpenBSD: getnameinfo.3,v 1.19 2003/05/03 20:05:07 jmc Exp $
2.\" $KAME: getnameinfo.3,v 1.20 2001/01/05 13:37:37 itojun Exp $
3.\"
4.\" Copyright (c) 1983, 1987, 1991, 1993
5.\" The Regents of the University of California. All rights reserved.
6.\"
7.\" Redistribution and use in source and binary forms, with or without
8.\" modification, are permitted provided that the following conditions
9.\" are met:
10.\" 1. Redistributions of source code must retain the above copyright
11.\" notice, this list of conditions and the following disclaimer.
12.\" 2. Redistributions in binary form must reproduce the above copyright
13.\" notice, this list of conditions and the following disclaimer in the
14.\" documentation and/or other materials provided with the distribution.
15.\" 3. All advertising materials mentioning features or use of this software
16.\" must display the following acknowledgement:
17.\" This product includes software developed by the University of
18.\" California, Berkeley and its contributors.
19.\" 4. Neither the name of the University nor the names of its contributors
20.\" may be used to endorse or promote products derived from this software
21.\" without specific prior written permission.
22.\"
23.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33.\" SUCH DAMAGE.
34.\"
35.\" From: @(#)gethostbyname.3 8.4 (Berkeley) 5/25/95
36.\"
37.Dd May 25, 1995
38.Dt GETNAMEINFO 3
39.Os
40.\"
41.Sh NAME
42.Nm getnameinfo
43.Nd address-to-nodename translation in protocol-independent manner
44.\"
45.Sh SYNOPSIS
46.Fd #include <sys/types.h>
47.Fd #include <sys/socket.h>
48.Fd #include <netdb.h>
49.Ft int
50.Fn getnameinfo "const struct sockaddr *sa" "socklen_t salen" \
51"char *host" "size_t hostlen" "char *serv" "size_t servlen" "int flags"
52.\"
53.Sh DESCRIPTION
54The
55.Fn getnameinfo
56function is defined for protocol-independent address-to-nodename translation.
57Its functionality is a reverse conversion of
58.Xr getaddrinfo 3 ,
59and implements similar functionality to
60.Xr gethostbyaddr 3
61and
62.Xr getservbyport 3
63in a more sophisticated manner.
64.Pp
65This function looks up an IP address and port number provided by the
66caller in the DNS and system-specific database, and returns text
67strings for both in buffers provided by the caller.
68The function indicates successful completion by a zero return value;
69a non-zero return value indicates failure.
70.Pp
71The first argument,
72.Fa sa ,
73points to either a
74.Li sockaddr_in
75structure (for IPv4) or a
76.Li sockaddr_in6
77structure (for IPv6) that holds the IP address and port number.
78The
79.Fa salen
80argument gives the length of the
81.Li sockaddr_in
82or
83.Li sockaddr_in6
84structure.
85.Pp
86The function returns the nodename associated with the IP address in
87the buffer pointed to by the
88.Fa host
89argument.
90The caller provides the size of this buffer via the
91.Fa hostlen
92argument.
93The service name associated with the port number is returned in the buffer
94pointed to by
95.Fa serv ,
96and the
97.Fa servlen
98argument gives the length of this buffer.
99The caller specifies not to return either string by providing a zero
100value for the
101.Fa hostlen
102or
103.Fa servlen
104arguments.
105Otherwise, the caller must provide buffers large enough to hold the
106nodename and the service name, including the terminating null characters.
107.Pp
108Unfortunately most systems do not provide constants that specify the
109maximum size of either a fully-qualified domain name or a service name.
110Therefore to aid the application in allocating buffers for these two
111returned strings the following constants are defined in
112.Aq Pa netdb.h :
113.Bd -literal -offset
114#define NI_MAXHOST MAXHOSTNAMELEN
115#define NI_MAXSERV 32
116.Ed
117.Pp
118The first value is actually defined as the constant
119.Dv MAXDNAME
120in recent versions of BIND's
121.Aq Pa arpa/nameser.h
122header (older versions of BIND define this constant to be 256)
123and the second is a guess based on the services listed in the current
124Assigned Numbers RFC.
125.Pp
126The final argument is a
127.Fa flag
128that changes the default actions of this function.
129By default the fully-qualified domain name (FQDN) for the host is
130looked up in the DNS and returned.
131If the flag bit
132.Dv NI_NOFQDN
133is set, only the nodename portion of the FQDN is returned for local hosts.
134.Pp
135If the
136.Fa flag
137bit
138.Dv NI_NUMERICHOST
139is set, or if the host's name cannot be located in the DNS,
140the numeric form of the host's address is returned instead of its name
141.Po
142e.g., by calling
143.Fn inet_ntop
144instead of
145.Fn gethostbyaddr
146.Pc .
147If the
148.Fa flag
149bit
150.Dv NI_NAMEREQD
151is set, an error is returned if the host's name cannot be located in the DNS.
152.Pp
153If the flag bit
154.Dv NI_NUMERICSERV
155is set, the numeric form of the service address is returned
156.Pq e.g., its port number
157instead of its name.
158The two
159.Dv NI_NUMERICxxx
160flags are required to support the
161.Fl n
162flag that many commands provide.
163.Pp
164A fifth flag bit,
165.Dv NI_DGRAM ,
166specifies that the service is a datagram service, and causes
167.Fn getservbyport
168to be called with a second argument of
169.Qq udp
170instead of its default of
171.Qq tcp .
172This is required for the few ports (512-514)
173that have different services for UDP and TCP.
174.Pp
175These
176.Dv NI_xxx
177flags are defined in
178.Aq Pa netdb.h .
179.\"
180.Ss Extension for scoped IPv6 address
181The implementation allows experimental numeric IPv6 address notation with
182scope identifier.
183IPv6 link-local address will appear as a string like
184.Dq Li fe80::1%ne0 .
185Refer to
186.Xr getaddrinfo 3
187for the notation.
188.\"
189.Sh EXAMPLES
190The following code tries to get a numeric hostname, and service name,
191for given socket address.
192Observe that there is no hardcoded reference to a particular address family.
193.Bd -literal -offset indent
194struct sockaddr *sa; /* input */
195char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
196
197if (getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), sbuf,
198 sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV)) {
199 errx(1, "could not get numeric hostname");
200 /*NOTREACHED*/
201}
202printf("host=%s, serv=%s\en", hbuf, sbuf);
203.Ed
204.Pp
205The following version checks if the socket address has reverse address mapping.
206.Bd -literal -offset indent
207struct sockaddr *sa; /* input */
208char hbuf[NI_MAXHOST];
209
210if (getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), NULL, 0,
211 NI_NAMEREQD)) {
212 errx(1, "could not resolve hostname");
213 /*NOTREACHED*/
214}
215printf("host=%s\en", hbuf);
216.Ed
217.\"
218.Sh DIAGNOSTICS
219The function indicates successful completion by a zero return value;
220a non-zero return value indicates failure.
221Error codes are as below:
222.Bl -tag -width Er
223.It Dv EAI_AGAIN
224The name could not be resolved at this time.
225Future attempts may succeed.
226.It Dv EAI_BADFLAGS
227The flags had an invalid value.
228.It Dv EAI_FAIL
229A non-recoverable error occurred.
230.It Dv EAI_FAMILY
231The address family was not recognized or the address length was invalid
232for the specified family.
233.It Dv EAI_MEMORY
234There was a memory allocation failure.
235.It Dv EAI_NONAME
236The name does not resolve for the supplied parameters.
237.Dv NI_NAMEREQD
238is set and the host's name cannot be located,
239or both nodename and servname were null.
240.It Dv EAI_SYSTEM
241A system error occurred.
242The error code can be found in errno.
243.El
244.\"
245.Sh SEE ALSO
246.Xr getaddrinfo 3 ,
247.Xr gethostbyaddr 3 ,
248.Xr getservbyport 3 ,
249.Xr hosts 5 ,
250.Xr resolv.conf 5 ,
251.Xr services 5 ,
252.Xr hostname 7 ,
253.Xr named 8
254.Rs
255.%A R. Gilligan
256.%A S. Thomson
257.%A J. Bound
258.%A W. Stevens
259.%T Basic Socket Interface Extensions for IPv6
260.%R RFC2553
261.%D March 1999
262.Re
263.Rs
264.%A Tatsuya Jinmei
265.%A Atsushi Onoe
266.%T "An Extension of Format for IPv6 Scoped Addresses"
267.%R internet draft
268.%N draft-ietf-ipngwg-scopedaddr-format-02.txt
269.%O work in progress material
270.Re
271.Rs
272.%A Craig Metz
273.%T Protocol Independence Using the Sockets API
274.%B "Proceedings of the freenix track: 2000 USENIX annual technical conference"
275.%D June 2000
276.Re
277.\"
278.Sh HISTORY
279The implementation first appeared in WIDE Hydrangea IPv6 protocol stack kit.
280.\"
281.Sh STANDARDS
282The
283.Fn getnameinfo
284function is defined in IEEE POSIX 1003.1g draft specification,
285and documented in
286.Dq Basic Socket Interface Extensions for IPv6
287.Pq RFC2553 .
288.\"
289.Sh BUGS
290The current implementation is not thread-safe.
291.Pp
292The text was shamelessly copied from RFC2553.
293.Pp
294.Ox
295intentionally uses a different
296.Dv NI_MAXHOST
297value from what RFC2553 suggests, to avoid buffer length handling mistakes.
diff --git a/src/lib/libc/net/getnameinfo.c b/src/lib/libc/net/getnameinfo.c
new file mode 100644
index 0000000000..d3a9678cbd
--- /dev/null
+++ b/src/lib/libc/net/getnameinfo.c
@@ -0,0 +1,368 @@
1/* $OpenBSD: getnameinfo.c,v 1.26 2003/01/28 04:58:00 marc Exp $ */
2/* $KAME: getnameinfo.c,v 1.45 2000/09/25 22:43:56 itojun Exp $ */
3
4/*
5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the project nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33/*
34 * Issues to be discussed:
35 * - Thread safe-ness must be checked
36 * - RFC2553 says that we should raise error on short buffer. X/Open says
37 * we need to truncate the result. We obey RFC2553 (and X/Open should be
38 * modified). ipngwg rough consensus seems to follow RFC2553.
39 * - What is "local" in NI_FQDN?
40 * - NI_NAMEREQD and NI_NUMERICHOST conflict with each other.
41 * - (KAME extension) always attach textual scopeid (fe80::1%lo0), if
42 * sin6_scope_id is filled - standardization status?
43 * XXX breaks backward compat for code that expects no scopeid.
44 * beware on merge.
45 */
46
47#ifndef INET6
48#define INET6
49#endif
50
51#include <sys/types.h>
52#include <sys/socket.h>
53#include <net/if.h>
54#include <netinet/in.h>
55#include <arpa/inet.h>
56#include <arpa/nameser.h>
57#include <netdb.h>
58#include <resolv.h>
59#include <string.h>
60#include <stddef.h>
61
62#include "thread_private.h"
63
64static const struct afd {
65 int a_af;
66 int a_addrlen;
67 int a_socklen;
68 int a_off;
69} afdl [] = {
70#ifdef INET6
71 {PF_INET6, sizeof(struct in6_addr), sizeof(struct sockaddr_in6),
72 offsetof(struct sockaddr_in6, sin6_addr)},
73#endif
74 {PF_INET, sizeof(struct in_addr), sizeof(struct sockaddr_in),
75 offsetof(struct sockaddr_in, sin_addr)},
76 {0, 0, 0},
77};
78
79struct sockinet {
80 u_char si_len;
81 u_char si_family;
82 u_short si_port;
83};
84
85#ifdef INET6
86static int ip6_parsenumeric(const struct sockaddr *, const char *, char *,
87 size_t, int);
88static int ip6_sa2str(const struct sockaddr_in6 *, char *, size_t, int);
89#endif
90
91int
92getnameinfo(sa, salen, host, hostlen, serv, servlen, flags)
93 const struct sockaddr *sa;
94 socklen_t salen;
95 char *host;
96 size_t hostlen;
97 char *serv;
98 size_t servlen;
99 int flags;
100{
101 const struct afd *afd;
102 struct servent *sp;
103 struct hostent *hp;
104 u_short port;
105 int family, i;
106 const char *addr;
107 u_int32_t v4a;
108 int h_error;
109 char numserv[512];
110 char numaddr[512];
111 _THREAD_PRIVATE_MUTEX(serv_mutex);
112
113 if (sa == NULL)
114 return EAI_FAIL;
115
116 if (sa->sa_len != salen)
117 return EAI_FAIL;
118
119 family = sa->sa_family;
120 for (i = 0; afdl[i].a_af; i++)
121 if (afdl[i].a_af == family) {
122 afd = &afdl[i];
123 goto found;
124 }
125 return EAI_FAMILY;
126
127 found:
128 if (salen != afd->a_socklen)
129 return EAI_FAIL;
130
131 /* network byte order */
132 port = ((const struct sockinet *)sa)->si_port;
133 addr = (const char *)sa + afd->a_off;
134
135 if (serv == NULL || servlen == 0) {
136 /*
137 * do nothing in this case.
138 * in case you are wondering if "&&" is more correct than
139 * "||" here: rfc2553bis-03 says that serv == NULL OR
140 * servlen == 0 means that the caller does not want the result.
141 */
142 } else {
143 if (flags & NI_NUMERICSERV)
144 sp = NULL;
145 else {
146 _THREAD_PRIVATE_MUTEX_LOCK(serv_mutex);
147 sp = getservbyport(port,
148 (flags & NI_DGRAM) ? "udp" : "tcp");
149 _THREAD_PRIVATE_MUTEX_UNLOCK(serv_mutex);
150 }
151 if (sp) {
152 if (strlen(sp->s_name) + 1 > servlen)
153 return EAI_MEMORY;
154 strlcpy(serv, sp->s_name, servlen);
155 } else {
156 snprintf(numserv, sizeof(numserv), "%u", ntohs(port));
157 if (strlen(numserv) + 1 > servlen)
158 return EAI_MEMORY;
159 strlcpy(serv, numserv, servlen);
160 }
161 }
162
163 switch (sa->sa_family) {
164 case AF_INET:
165 v4a = (u_int32_t)
166 ntohl(((const struct sockaddr_in *)sa)->sin_addr.s_addr);
167 if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
168 flags |= NI_NUMERICHOST;
169 v4a >>= IN_CLASSA_NSHIFT;
170 if (v4a == 0)
171 flags |= NI_NUMERICHOST;
172 break;
173#ifdef INET6
174 case AF_INET6:
175 {
176 const struct sockaddr_in6 *sin6;
177 sin6 = (const struct sockaddr_in6 *)sa;
178 switch (sin6->sin6_addr.s6_addr[0]) {
179 case 0x00:
180 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr))
181 ;
182 else if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr))
183 ;
184 else
185 flags |= NI_NUMERICHOST;
186 break;
187 default:
188 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
189 flags |= NI_NUMERICHOST;
190 }
191 else if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
192 flags |= NI_NUMERICHOST;
193 break;
194 }
195 }
196 break;
197#endif
198 }
199 if (host == NULL || hostlen == 0) {
200 /*
201 * do nothing in this case.
202 * in case you are wondering if "&&" is more correct than
203 * "||" here: rfc2553bis-03 says that host == NULL or
204 * hostlen == 0 means that the caller does not want the result.
205 */
206 } else if (flags & NI_NUMERICHOST) {
207 int numaddrlen;
208
209 /* NUMERICHOST and NAMEREQD conflicts with each other */
210 if (flags & NI_NAMEREQD)
211 return EAI_NONAME;
212
213 switch(afd->a_af) {
214#ifdef INET6
215 case AF_INET6:
216 {
217 int error;
218
219 if ((error = ip6_parsenumeric(sa, addr, host,
220 hostlen, flags)) != 0)
221 return(error);
222 break;
223 }
224#endif
225 default:
226 if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
227 == NULL)
228 return EAI_SYSTEM;
229 numaddrlen = strlen(numaddr);
230 if (numaddrlen + 1 > hostlen) /* don't forget terminator */
231 return EAI_MEMORY;
232 strlcpy(host, numaddr, hostlen);
233 break;
234 }
235 } else {
236 _THREAD_PRIVATE_MUTEX_LOCK(serv_mutex);
237 hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af);
238 _THREAD_PRIVATE_MUTEX_UNLOCK(serv_mutex);
239 h_error = h_errno;
240
241 if (hp) {
242#if 0
243 /*
244 * commented out, since "for local host" is not
245 * implemented here - see RFC2553 p30
246 */
247 if (flags & NI_NOFQDN) {
248 char *p;
249 p = strchr(hp->h_name, '.');
250 if (p)
251 *p = '\0';
252 }
253#endif
254 if (strlen(hp->h_name) + 1 > hostlen) {
255 return EAI_MEMORY;
256 }
257 strlcpy(host, hp->h_name, hostlen);
258 } else {
259 if (flags & NI_NAMEREQD)
260 return EAI_NONAME;
261 switch(afd->a_af) {
262#ifdef INET6
263 case AF_INET6:
264 {
265 int error;
266
267 if ((error = ip6_parsenumeric(sa, addr, host,
268 hostlen,
269 flags)) != 0)
270 return(error);
271 break;
272 }
273#endif
274 default:
275 if (inet_ntop(afd->a_af, addr, host,
276 hostlen) == NULL)
277 return EAI_SYSTEM;
278 break;
279 }
280 }
281 }
282 return(0);
283}
284
285#ifdef INET6
286static int
287ip6_parsenumeric(sa, addr, host, hostlen, flags)
288 const struct sockaddr *sa;
289 const char *addr;
290 char *host;
291 size_t hostlen;
292 int flags;
293{
294 int numaddrlen;
295 char numaddr[512];
296
297 if (inet_ntop(AF_INET6, addr, numaddr, sizeof(numaddr)) == NULL)
298 return EAI_SYSTEM;
299
300 numaddrlen = strlen(numaddr);
301 if (numaddrlen + 1 > hostlen) /* don't forget terminator */
302 return EAI_MEMORY;
303 strlcpy(host, numaddr, hostlen);
304
305 if (((const struct sockaddr_in6 *)sa)->sin6_scope_id) {
306 char zonebuf[MAXHOSTNAMELEN];
307 int zonelen;
308
309 zonelen = ip6_sa2str(
310 (const struct sockaddr_in6 *)(const void *)sa,
311 zonebuf, sizeof(zonebuf), flags);
312 if (zonelen < 0)
313 return EAI_MEMORY;
314 if (zonelen + 1 + numaddrlen + 1 > hostlen)
315 return EAI_MEMORY;
316
317 /* construct <numeric-addr><delim><zoneid> */
318 memcpy(host + numaddrlen + 1, zonebuf,
319 (size_t)zonelen);
320 host[numaddrlen] = SCOPE_DELIMITER;
321 host[numaddrlen + 1 + zonelen] = '\0';
322 }
323
324 return 0;
325}
326
327/* ARGSUSED */
328static int
329ip6_sa2str(sa6, buf, bufsiz, flags)
330 const struct sockaddr_in6 *sa6;
331 char *buf;
332 size_t bufsiz;
333 int flags;
334{
335 unsigned int ifindex;
336 const struct in6_addr *a6;
337 int n;
338
339 ifindex = (unsigned int)sa6->sin6_scope_id;
340 a6 = &sa6->sin6_addr;
341
342#ifdef notdef
343 if ((flags & NI_NUMERICSCOPE) != 0) {
344 n = snprintf(buf, bufsiz, "%u", sa6->sin6_scope_id);
345 if (n < 0 || n >= bufsiz)
346 return -1;
347 else
348 return n;
349 }
350#endif
351
352 /* if_indextoname() does not take buffer size. not a good api... */
353 if ((IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6)) &&
354 bufsiz >= IF_NAMESIZE) {
355 char *p = if_indextoname(ifindex, buf);
356 if (p) {
357 return(strlen(p));
358 }
359 }
360
361 /* last resort */
362 n = snprintf(buf, bufsiz, "%u", sa6->sin6_scope_id);
363 if (n < 0 || n >= bufsiz)
364 return -1;
365 else
366 return n;
367}
368#endif /* INET6 */
diff --git a/src/lib/libc/net/getnetbyaddr.c b/src/lib/libc/net/getnetbyaddr.c
index c193860e36..925d1d5895 100644
--- a/src/lib/libc/net/getnetbyaddr.c
+++ b/src/lib/libc/net/getnetbyaddr.c
@@ -1,5 +1,3 @@
1/* $NetBSD: getnetbyaddr.c,v 1.4 1995/02/25 06:20:30 cgd Exp $ */
2
3/* 1/*
4 * Copyright (c) 1983, 1993 2 * Copyright (c) 1983, 1993
5 * The Regents of the University of California. All rights reserved. 3 * The Regents of the University of California. All rights reserved.
@@ -34,11 +32,7 @@
34 */ 32 */
35 33
36#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
37#if 0 35static char rcsid[] = "$OpenBSD: getnetbyaddr.c,v 1.5 1997/07/09 01:08:28 millert Exp $";
38static char sccsid[] = "@(#)getnetbyaddr.c 8.1 (Berkeley) 6/4/93";
39#else
40static char rcsid[] = "$NetBSD: getnetbyaddr.c,v 1.4 1995/02/25 06:20:30 cgd Exp $";
41#endif
42#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
43 37
44#include <netdb.h> 38#include <netdb.h>
@@ -46,14 +40,14 @@ static char rcsid[] = "$NetBSD: getnetbyaddr.c,v 1.4 1995/02/25 06:20:30 cgd Exp
46extern int _net_stayopen; 40extern int _net_stayopen;
47 41
48struct netent * 42struct netent *
49getnetbyaddr(net, type) 43_getnetbyaddr(net, type)
50 register long net; 44 register in_addr_t net;
51 register int type; 45 register int type;
52{ 46{
53 register struct netent *p; 47 register struct netent *p;
54 48
55 setnetent(_net_stayopen); 49 setnetent(_net_stayopen);
56 while (p = getnetent()) 50 while ((p = getnetent()))
57 if (p->n_addrtype == type && p->n_net == net) 51 if (p->n_addrtype == type && p->n_net == net)
58 break; 52 break;
59 if (!_net_stayopen) 53 if (!_net_stayopen)
diff --git a/src/lib/libc/net/getnetbyname.c b/src/lib/libc/net/getnetbyname.c
index 93a2e1256c..4e39cf6860 100644
--- a/src/lib/libc/net/getnetbyname.c
+++ b/src/lib/libc/net/getnetbyname.c
@@ -1,5 +1,3 @@
1/* $NetBSD: getnetbyname.c,v 1.4 1995/02/25 06:20:31 cgd Exp $ */
2
3/* 1/*
4 * Copyright (c) 1983, 1993 2 * Copyright (c) 1983, 1993
5 * The Regents of the University of California. All rights reserved. 3 * The Regents of the University of California. All rights reserved.
@@ -34,11 +32,7 @@
34 */ 32 */
35 33
36#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
37#if 0 35static char rcsid[] = "$OpenBSD: getnetbyname.c,v 1.5 1997/07/09 01:08:29 millert Exp $";
38static char sccsid[] = "@(#)getnetbyname.c 8.1 (Berkeley) 6/4/93";
39#else
40static char rcsid[] = "$NetBSD: getnetbyname.c,v 1.4 1995/02/25 06:20:31 cgd Exp $";
41#endif
42#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
43 37
44#include <netdb.h> 38#include <netdb.h>
@@ -47,18 +41,18 @@ static char rcsid[] = "$NetBSD: getnetbyname.c,v 1.4 1995/02/25 06:20:31 cgd Exp
47extern int _net_stayopen; 41extern int _net_stayopen;
48 42
49struct netent * 43struct netent *
50getnetbyname(name) 44_getnetbyname(name)
51 register const char *name; 45 register const char *name;
52{ 46{
53 register struct netent *p; 47 register struct netent *p;
54 register char **cp; 48 register char **cp;
55 49
56 setnetent(_net_stayopen); 50 setnetent(_net_stayopen);
57 while (p = getnetent()) { 51 while ((p = getnetent())) {
58 if (strcmp(p->n_name, name) == 0) 52 if (strcasecmp(p->n_name, name) == 0)
59 break; 53 break;
60 for (cp = p->n_aliases; *cp != 0; cp++) 54 for (cp = p->n_aliases; *cp != 0; cp++)
61 if (strcmp(*cp, name) == 0) 55 if (strcasecmp(*cp, name) == 0)
62 goto found; 56 goto found;
63 } 57 }
64found: 58found:
diff --git a/src/lib/libc/net/getnetent.3 b/src/lib/libc/net/getnetent.3
index d4f0bedbf9..0c401c74ff 100644
--- a/src/lib/libc/net/getnetent.3
+++ b/src/lib/libc/net/getnetent.3
@@ -1,4 +1,4 @@
1.\" $NetBSD: getnetent.3,v 1.3 1995/02/25 06:20:32 cgd Exp $ 1.\" $OpenBSD: getnetent.3,v 1.11 2000/12/24 00:30:56 aaron Exp $
2.\" 2.\"
3.\" Copyright (c) 1983, 1991, 1993 3.\" Copyright (c) 1983, 1991, 1993
4.\" The Regents of the University of California. All rights reserved. 4.\" The Regents of the University of California. All rights reserved.
@@ -31,11 +31,9 @@
31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32.\" SUCH DAMAGE. 32.\" SUCH DAMAGE.
33.\" 33.\"
34.\" @(#)getnetent.3 8.1 (Berkeley) 6/4/93 34.Dd March 13, 1997
35.\"
36.Dd June 4, 1993
37.Dt GETNETENT 3 35.Dt GETNETENT 3
38.Os BSD 4.2 36.Os
39.Sh NAME 37.Sh NAME
40.Nm getnetent , 38.Nm getnetent ,
41.Nm getnetbyaddr , 39.Nm getnetbyaddr ,
@@ -46,31 +44,30 @@
46.Sh SYNOPSIS 44.Sh SYNOPSIS
47.Fd #include <netdb.h> 45.Fd #include <netdb.h>
48.Ft struct netent * 46.Ft struct netent *
49.Fn getnetent 47.Fn getnetent "void"
50.Ft struct netent * 48.Ft struct netent *
51.Fn getnetbyname "char *name" 49.Fn getnetbyname "char *name"
52.Ft struct netent * 50.Ft struct netent *
53.Fn getnetbyaddr "long net" "int type" 51.Fn getnetbyaddr "in_addr_t net" "int type"
52.Ft void
54.Fn setnetent "int stayopen" 53.Fn setnetent "int stayopen"
55.Fn endnetent 54.Ft void
55.Fn endnetent "void"
56.Sh DESCRIPTION 56.Sh DESCRIPTION
57The 57The
58.Fn getnetent , 58.Fn getnetent ,
59.Fn getnetbyname , 59.Fn getnetbyname ,
60and 60and
61.Fn getnetbyaddr 61.Fn getnetbyaddr
62functions 62functions each return a pointer to an object with the following structure
63each return a pointer to an object with the 63containing the broken-out fields of a line in the network database,
64following structure
65containing the broken-out
66fields of a line in the network data base,
67.Pa /etc/networks . 64.Pa /etc/networks .
68.Bd -literal -offset indent 65.Bd -literal -offset indent
69struct netent { 66struct netent {
70 char *n_name; /* official name of net */ 67 char *n_name; /* official name of net */
71 char **n_aliases; /* alias list */ 68 char **n_aliases; /* alias list */
72 int n_addrtype; /* net number type */ 69 int n_addrtype; /* net number type */
73 unsigned long n_net; /* net number */ 70 in_addr_t n_net; /* net number */
74}; 71};
75.Ed 72.Ed
76.Pp 73.Pp
@@ -79,45 +76,42 @@ The members of this structure are:
79.It Fa n_name 76.It Fa n_name
80The official name of the network. 77The official name of the network.
81.It Fa n_aliases 78.It Fa n_aliases
82A zero terminated list of alternate names for the network. 79A zero-terminated list of alternate names for the network.
83.It Fa n_addrtype 80.It Fa n_addrtype
84The type of the network number returned; currently only AF_INET. 81The type of the network number returned; currently only
82.Dv AF_INET .
85.It Fa n_net 83.It Fa n_net
86The network number. Network numbers are returned in machine byte 84The network number.
87order. 85Network numbers are returned in machine byte order.
88.El 86.El
89.Pp 87.Pp
90The 88The
91.Fn getnetent 89.Fn getnetent
92function 90function reads the next line of the file, opening the file if necessary.
93reads the next line of the file, opening the file if necessary.
94.Pp 91.Pp
95The 92The
96.Fn setnetent 93.Fn setnetent
97function 94function opens and rewinds the file.
98opens and rewinds the file. If the 95If the
99.Fa stayopen 96.Fa stayopen
100flag is non-zero, 97flag is non-zero,
101the net data base will not be closed after each call to 98the net database will not be closed after each call to
102.Fn getnetbyname 99.Fn getnetbyname
103or 100or
104.Fn getnetbyaddr . 101.Fn getnetbyaddr .
105.Pp 102.Pp
106The 103The
107.Fn endnetent 104.Fn endnetent
108function 105function closes the file.
109closes the file.
110.Pp 106.Pp
111The 107The
112.Fn getnetbyname 108.Fn getnetbyname
113function
114and 109and
115.Fn getnetbyaddr 110.Fn getnetbyaddr
116sequentially search from the beginning 111functions search the domain name server if the system is configured to use one.
117of the file until a matching 112If the search fails, or no name server is configured, they sequentially
118net name or 113search from the beginning of the file until a matching net name or
119net address and type is found, 114net address and type is found, or until
120or until
121.Dv EOF 115.Dv EOF
122is encountered. 116is encountered.
123Network numbers are supplied in host order. 117Network numbers are supplied in host order.
@@ -126,11 +120,11 @@ Network numbers are supplied in host order.
126.It Pa /etc/networks 120.It Pa /etc/networks
127.El 121.El
128.Sh DIAGNOSTICS 122.Sh DIAGNOSTICS
129Null pointer 123Null pointer (0) returned on
130(0) returned on
131.Dv EOF 124.Dv EOF
132or error. 125or error.
133.Sh SEE ALSO 126.Sh SEE ALSO
127.Xr resolver 3 ,
134.Xr networks 5 128.Xr networks 5
135.Sh HISTORY 129.Sh HISTORY
136The 130The
@@ -140,14 +134,11 @@ The
140.Fn setnetent , 134.Fn setnetent ,
141and 135and
142.Fn endnetent 136.Fn endnetent
143functions appeared in 137functions appeared in
144.Bx 4.2 . 138.Bx 4.2 .
145.Sh BUGS 139.Sh BUGS
146The data space used by 140The data space used by these functions is static; if future use
147these functions is static; if future use requires the data, it should be 141requires the data, it should be copied before any subsequent calls
148copied before any subsequent calls to these functions overwrite it. 142to these functions overwrite it.
149Only Internet network 143Only Internet network numbers are currently understood.
150numbers are currently understood. 144Expecting network numbers to fit in no more than 32 bits is naive.
151Expecting network numbers to fit
152in no more than 32 bits is probably
153naive.
diff --git a/src/lib/libc/net/getnetent.c b/src/lib/libc/net/getnetent.c
index b4e16b8f5d..8f618a1d5e 100644
--- a/src/lib/libc/net/getnetent.c
+++ b/src/lib/libc/net/getnetent.c
@@ -1,5 +1,3 @@
1/* $NetBSD: getnetent.c,v 1.4 1995/02/25 06:20:33 cgd Exp $ */
2
3/* 1/*
4 * Copyright (c) 1983, 1993 2 * Copyright (c) 1983, 1993
5 * The Regents of the University of California. All rights reserved. 3 * The Regents of the University of California. All rights reserved.
@@ -34,11 +32,7 @@
34 */ 32 */
35 33
36#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
37#if 0 35static char rcsid[] = "$OpenBSD: getnetent.c,v 1.8 1998/03/16 05:06:57 millert Exp $";
38static char sccsid[] = "@(#)getnetent.c 8.1 (Berkeley) 6/4/93";
39#else
40static char rcsid[] = "$NetBSD: getnetent.c,v 1.4 1995/02/25 06:20:33 cgd Exp $";
41#endif
42#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
43 37
44#include <sys/types.h> 38#include <sys/types.h>
@@ -81,22 +75,27 @@ endnetent()
81struct netent * 75struct netent *
82getnetent() 76getnetent()
83{ 77{
84 char *p; 78 char *p, *cp, **q;
85 register char *cp, **q; 79 size_t len;
86 80
87 if (netf == NULL && (netf = fopen(_PATH_NETWORKS, "r" )) == NULL) 81 if (netf == NULL && (netf = fopen(_PATH_NETWORKS, "r" )) == NULL)
88 return (NULL); 82 return (NULL);
89again: 83again:
90 p = fgets(line, BUFSIZ, netf); 84 if ((p = fgetln(netf, &len)) == NULL)
91 if (p == NULL)
92 return (NULL); 85 return (NULL);
93 if (*p == '#') 86 if (p[len-1] == '\n')
87 len--;
88 if (len >= sizeof(line) || len == 0)
94 goto again; 89 goto again;
95 cp = strpbrk(p, "#\n"); 90 p = memcpy(line, p, len);
96 if (cp == NULL) 91 line[len] = '\0';
92 if (*p == '#')
97 goto again; 93 goto again;
98 *cp = '\0'; 94 if ((cp = strchr(p, '#')) != NULL)
95 *cp = '\0';
99 net.n_name = p; 96 net.n_name = p;
97 if (strlen(net.n_name) >= MAXHOSTNAMELEN-1)
98 net.n_name[MAXHOSTNAMELEN-1] = '\0';
100 cp = strpbrk(p, " \t"); 99 cp = strpbrk(p, " \t");
101 if (cp == NULL) 100 if (cp == NULL)
102 goto again; 101 goto again;
@@ -116,8 +115,11 @@ again:
116 cp++; 115 cp++;
117 continue; 116 continue;
118 } 117 }
119 if (q < &net_aliases[MAXALIASES - 1]) 118 if (q < &net_aliases[MAXALIASES - 1]) {
120 *q++ = cp; 119 *q++ = cp;
120 if (strlen(cp) >= MAXHOSTNAMELEN-1)
121 cp[MAXHOSTNAMELEN-1] = '\0';
122 }
121 cp = strpbrk(cp, " \t"); 123 cp = strpbrk(cp, " \t");
122 if (cp != NULL) 124 if (cp != NULL)
123 *cp++ = '\0'; 125 *cp++ = '\0';
diff --git a/src/lib/libc/net/getnetnamadr.c b/src/lib/libc/net/getnetnamadr.c
new file mode 100644
index 0000000000..1be874209f
--- /dev/null
+++ b/src/lib/libc/net/getnetnamadr.c
@@ -0,0 +1,411 @@
1/* $OpenBSD: getnetnamadr.c,v 1.21 2003/04/05 00:43:19 tdeval Exp $ */
2
3/*
4 * Copyright (c) 1997, Jason Downs. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by Jason Downs for the
17 * OpenBSD system.
18 * 4. Neither the name(s) of the author(s) nor the name OpenBSD
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS
23 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT,
26 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34/* Copyright (c) 1993 Carlos Leandro and Rui Salgueiro
35 * Dep. Matematica Universidade de Coimbra, Portugal, Europe
36 *
37 * Permission to use, copy, modify, and distribute this software for any
38 * purpose with or without fee is hereby granted, provided that the above
39 * copyright notice and this permission notice appear in all copies.
40 */
41/*
42 * Copyright (c) 1983, 1993
43 * The Regents of the University of California. All rights reserved.
44 *
45 * Redistribution and use in source and binary forms, with or without
46 * modification, are permitted provided that the following conditions
47 * are met:
48 * 1. Redistributions of source code must retain the above copyright
49 * notice, this list of conditions and the following disclaimer.
50 * 2. Redistributions in binary form must reproduce the above copyright
51 * notice, this list of conditions and the following disclaimer in the
52 * documentation and/or other materials provided with the distribution.
53 * 3. All advertising materials mentioning features or use of this software
54 * must display the following acknowledgement:
55 * This product includes software developed by the University of
56 * California, Berkeley and its contributors.
57 * 4. Neither the name of the University nor the names of its contributors
58 * may be used to endorse or promote products derived from this software
59 * without specific prior written permission.
60 *
61 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
62 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
63 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
64 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
65 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
66 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
67 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
68 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
69 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
70 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
71 * SUCH DAMAGE.
72 */
73
74#if defined(LIBC_SCCS) && !defined(lint)
75#if 0
76static char sccsid[] = "@(#)getnetbyaddr.c 8.1 (Berkeley) 6/4/93";
77static char sccsid_[] = "from getnetnamadr.c 1.4 (Coimbra) 93/06/03";
78static char rcsid[] = "$From: getnetnamadr.c,v 8.7 1996/08/05 08:31:35 vixie Exp $";
79#else
80static char rcsid[] = "$OpenBSD: getnetnamadr.c,v 1.21 2003/04/05 00:43:19 tdeval Exp $";
81#endif
82#endif /* LIBC_SCCS and not lint */
83
84#include <sys/types.h>
85#include <sys/param.h>
86#include <sys/socket.h>
87#include <netinet/in.h>
88#include <arpa/inet.h>
89#include <arpa/nameser.h>
90
91#include <stdio.h>
92#include <netdb.h>
93#include <resolv.h>
94#include <ctype.h>
95#include <errno.h>
96#include <string.h>
97#include <stdlib.h>
98
99#include "thread_private.h"
100
101extern int h_errno;
102
103struct netent *_getnetbyaddr(in_addr_t net, int type);
104struct netent *_getnetbyname(const char *name);
105
106int _hokchar(const char *);
107
108#define BYADDR 0
109#define BYNAME 1
110#define MAXALIASES 35
111
112#define MAXPACKET (64*1024)
113
114typedef union {
115 HEADER hdr;
116 u_char buf[MAXPACKET];
117} querybuf;
118
119typedef union {
120 long al;
121 char ac;
122} align;
123
124static struct netent *
125getnetanswer(answer, anslen, net_i)
126 querybuf *answer;
127 int anslen;
128 int net_i;
129{
130
131 register HEADER *hp;
132 register u_char *cp;
133 register int n;
134 u_char *eom;
135 int type, class, ancount, qdcount, haveanswer, i, nchar;
136 char aux1[MAXHOSTNAMELEN], aux2[MAXHOSTNAMELEN], ans[MAXHOSTNAMELEN];
137 char *in, *st, *pauxt, *bp, **ap, *ep;
138 char *paux1 = &aux1[0], *paux2 = &aux2[0];
139 static struct netent net_entry;
140 static char *net_aliases[MAXALIASES], netbuf[BUFSIZ+1];
141
142 /*
143 * find first satisfactory answer
144 *
145 * answer --> +------------+ ( MESSAGE )
146 * | Header |
147 * +------------+
148 * | Question | the question for the name server
149 * +------------+
150 * | Answer | RRs answering the question
151 * +------------+
152 * | Authority | RRs pointing toward an authority
153 * | Additional | RRs holding additional information
154 * +------------+
155 */
156 eom = answer->buf + anslen;
157 hp = &answer->hdr;
158 ancount = ntohs(hp->ancount); /* #/records in the answer section */
159 qdcount = ntohs(hp->qdcount); /* #/entries in the question section */
160 bp = netbuf;
161 ep = netbuf + sizeof(netbuf);
162 cp = answer->buf + HFIXEDSZ;
163 if (!qdcount) {
164 if (hp->aa)
165 h_errno = HOST_NOT_FOUND;
166 else
167 h_errno = TRY_AGAIN;
168 return (NULL);
169 }
170 while (qdcount-- > 0) {
171 n = __dn_skipname(cp, eom);
172 if (n < 0 || (cp + n + QFIXEDSZ) > eom) {
173 h_errno = NO_RECOVERY;
174 return(NULL);
175 }
176 cp += n + QFIXEDSZ;
177 }
178 ap = net_aliases;
179 *ap = NULL;
180 net_entry.n_aliases = net_aliases;
181 haveanswer = 0;
182 while (--ancount >= 0 && cp < eom) {
183 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
184#ifdef USE_RESOLV_NAME_OK
185 if ((n < 0) || !res_dnok(bp))
186#else
187 if ((n < 0) || !_hokchar(bp))
188#endif
189 break;
190 cp += n;
191 ans[0] = '\0';
192 strlcpy(&ans[0], bp, sizeof ans);
193 GETSHORT(type, cp);
194 GETSHORT(class, cp);
195 cp += INT32SZ; /* TTL */
196 GETSHORT(n, cp);
197 if (class == C_IN && type == T_PTR) {
198 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
199#ifdef USE_RESOLV_NAME_OK
200 if ((n < 0) || !res_hnok(bp))
201#else
202 if ((n < 0) || !_hokchar(bp))
203#endif
204 {
205 cp += n;
206 return (NULL);
207 }
208 cp += n;
209 if ((ap + 2) < &net_aliases[MAXALIASES]) {
210 *ap++ = bp;
211 bp += strlen(bp) + 1;
212 net_entry.n_addrtype =
213 (class == C_IN) ? AF_INET : AF_UNSPEC;
214 haveanswer++;
215 }
216 }
217 }
218 if (haveanswer) {
219 *ap = NULL;
220 switch (net_i) {
221 case BYADDR:
222 net_entry.n_name = *net_entry.n_aliases;
223 net_entry.n_net = 0L;
224 break;
225 case BYNAME:
226 ap = net_entry.n_aliases;
227 next_alias:
228 in = *ap++;
229 if (in == NULL) {
230 h_errno = HOST_NOT_FOUND;
231 return (NULL);
232 }
233 net_entry.n_name = ans;
234 aux2[0] = '\0';
235 for (i = 0; i < 4; i++) {
236 for (st = in, nchar = 0;
237 isdigit((unsigned char)*st);
238 st++, nchar++)
239 ;
240 if (*st != '.' || nchar == 0 || nchar > 3)
241 goto next_alias;
242 if (i != 0)
243 nchar++;
244 strlcpy(paux1, in, nchar+1);
245 strlcat(paux1, paux2, MAXHOSTNAMELEN);
246 pauxt = paux2;
247 paux2 = paux1;
248 paux1 = pauxt;
249 in = ++st;
250 }
251 if (strcasecmp(in, "IN-ADDR.ARPA") != 0)
252 goto next_alias;
253 net_entry.n_net = inet_network(paux2);
254 break;
255 }
256 net_entry.n_aliases++;
257 return (&net_entry);
258 }
259 h_errno = TRY_AGAIN;
260 return (NULL);
261}
262
263struct netent *
264getnetbyaddr(net, net_type)
265 register in_addr_t net;
266 register int net_type;
267{
268 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
269 unsigned int netbr[4];
270 int nn, anslen;
271 querybuf *buf;
272 char qbuf[MAXDNAME];
273 in_addr_t net2;
274 struct netent *net_entry = NULL;
275 char lookups[MAXDNSLUS];
276 int i;
277
278 if ((_resp->options & RES_INIT) == 0 && res_init() == -1)
279 return(_getnetbyaddr(net, net_type));
280
281 bcopy(_resp->lookups, lookups, sizeof lookups);
282 if (lookups[0] == '\0')
283 strlcpy(lookups, "bf", sizeof lookups);
284
285 for (i = 0; i < MAXDNSLUS && lookups[i]; i++) {
286 switch (lookups[i]) {
287#ifdef YP
288 case 'y':
289 /* There is no YP support. */
290 break;
291#endif /* YP */
292 case 'b':
293 if (net_type != AF_INET)
294 break; /* DNS only supports AF_INET? */
295
296 for (nn = 4, net2 = net; net2; net2 >>= 8)
297 netbr[--nn] = net2 & 0xff;
298 switch (nn) {
299 case 3: /* Class A */
300 snprintf(qbuf, sizeof(qbuf),
301 "0.0.0.%u.in-addr.arpa", netbr[3]);
302 break;
303 case 2: /* Class B */
304 snprintf(qbuf, sizeof(qbuf),
305 "0.0.%u.%u.in-addr.arpa",
306 netbr[3], netbr[2]);
307 break;
308 case 1: /* Class C */
309 snprintf(qbuf, sizeof(qbuf),
310 "0.%u.%u.%u.in-addr.arpa",
311 netbr[3], netbr[2], netbr[1]);
312 break;
313 case 0: /* Class D - E */
314 snprintf(qbuf, sizeof(qbuf),
315 "%u.%u.%u.%u.in-addr.arpa",
316 netbr[3], netbr[2], netbr[1], netbr[0]);
317 break;
318 }
319 buf = malloc(sizeof(*buf));
320 if (buf == NULL)
321 break;
322 anslen = res_query(qbuf, C_IN, T_PTR, buf->buf,
323 sizeof(buf->buf));
324 if (anslen < 0) {
325 free(buf);
326#ifdef DEBUG
327 if (_resp->options & RES_DEBUG)
328 printf("res_query failed\n");
329#endif
330 break;
331 }
332 net_entry = getnetanswer(buf, anslen, BYADDR);
333 free(buf);
334 if (net_entry != NULL) {
335 unsigned u_net = net; /* maybe net should be unsigned ? */
336
337 /* Strip trailing zeros */
338 while ((u_net & 0xff) == 0 && u_net != 0)
339 u_net >>= 8;
340 net_entry->n_net = u_net;
341 return (net_entry);
342 }
343 break;
344 case 'f':
345 net_entry = _getnetbyaddr(net, net_type);
346 if (net_entry != NULL)
347 return (net_entry);
348 }
349 }
350
351 /* Nothing matched. */
352 return (NULL);
353}
354
355struct netent *
356getnetbyname(net)
357 register const char *net;
358{
359 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
360 int anslen;
361 querybuf *buf;
362 char qbuf[MAXDNAME];
363 struct netent *net_entry = NULL;
364 char lookups[MAXDNSLUS];
365 int i;
366
367 if ((_resp->options & RES_INIT) == 0 && res_init() == -1)
368 return (_getnetbyname(net));
369
370 bcopy(_resp->lookups, lookups, sizeof lookups);
371 if (lookups[0] == '\0')
372 strlcpy(lookups, "bf", sizeof lookups);
373
374 for (i = 0; i < MAXDNSLUS && lookups[i]; i++) {
375 switch (lookups[i]) {
376#ifdef YP
377 case 'y':
378 /* There is no YP support. */
379 break;
380#endif /* YP */
381 case 'b':
382 strlcpy(qbuf, net, sizeof qbuf);
383 buf = malloc(sizeof(*buf));
384 if (buf == NULL)
385 break;
386 anslen = res_search(qbuf, C_IN, T_PTR, buf->buf,
387 sizeof(buf->buf));
388 if (anslen < 0) {
389 free(buf);
390#ifdef DEBUG
391 if (_resp->options & RES_DEBUG)
392 printf("res_query failed\n");
393#endif
394 break;
395 }
396 net_entry = getnetanswer(buf, anslen, BYNAME);
397 free(buf);
398 if (net_entry != NULL)
399 return (net_entry);
400 break;
401 case 'f':
402 net_entry = _getnetbyname(net);
403 if (net_entry != NULL)
404 return (net_entry);
405 break;
406 }
407 }
408
409 /* Nothing matched. */
410 return (NULL);
411}
diff --git a/src/lib/libc/net/getproto.c b/src/lib/libc/net/getproto.c
index 49c09b0806..474d8d9427 100644
--- a/src/lib/libc/net/getproto.c
+++ b/src/lib/libc/net/getproto.c
@@ -1,5 +1,3 @@
1/* $NetBSD: getproto.c,v 1.4 1995/02/25 06:20:33 cgd Exp $ */
2
3/* 1/*
4 * Copyright (c) 1983, 1993 2 * Copyright (c) 1983, 1993
5 * The Regents of the University of California. All rights reserved. 3 * The Regents of the University of California. All rights reserved.
@@ -34,11 +32,7 @@
34 */ 32 */
35 33
36#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
37#if 0 35static char rcsid[] = "$OpenBSD: getproto.c,v 1.3 1997/07/09 01:08:31 millert Exp $";
38static char sccsid[] = "@(#)getproto.c 8.1 (Berkeley) 6/4/93";
39#else
40static char rcsid[] = "$NetBSD: getproto.c,v 1.4 1995/02/25 06:20:33 cgd Exp $";
41#endif
42#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
43 37
44#include <netdb.h> 38#include <netdb.h>
@@ -52,7 +46,7 @@ getprotobynumber(proto)
52 register struct protoent *p; 46 register struct protoent *p;
53 47
54 setprotoent(_proto_stayopen); 48 setprotoent(_proto_stayopen);
55 while (p = getprotoent()) 49 while ((p = getprotoent()))
56 if (p->p_proto == proto) 50 if (p->p_proto == proto)
57 break; 51 break;
58 if (!_proto_stayopen) 52 if (!_proto_stayopen)
diff --git a/src/lib/libc/net/getprotoent.3 b/src/lib/libc/net/getprotoent.3
index 8d607199ef..1f95529532 100644
--- a/src/lib/libc/net/getprotoent.3
+++ b/src/lib/libc/net/getprotoent.3
@@ -1,4 +1,4 @@
1.\" $NetBSD: getprotoent.3,v 1.3 1995/02/25 06:20:34 cgd Exp $ 1.\" $OpenBSD: getprotoent.3,v 1.8 2000/12/24 00:30:56 aaron Exp $
2.\" 2.\"
3.\" Copyright (c) 1983, 1991, 1993 3.\" Copyright (c) 1983, 1991, 1993
4.\" The Regents of the University of California. All rights reserved. 4.\" The Regents of the University of California. All rights reserved.
@@ -31,11 +31,9 @@
31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32.\" SUCH DAMAGE. 32.\" SUCH DAMAGE.
33.\" 33.\"
34.\" @(#)getprotoent.3 8.1 (Berkeley) 6/4/93
35.\"
36.Dd June 4, 1993 34.Dd June 4, 1993
37.Dt GETPROTOENT 3 35.Dt GETPROTOENT 3
38.Os BSD 4.2 36.Os
39.Sh NAME 37.Sh NAME
40.Nm getprotoent , 38.Nm getprotoent ,
41.Nm getprotobynumber , 39.Nm getprotobynumber ,
@@ -46,24 +44,23 @@
46.Sh SYNOPSIS 44.Sh SYNOPSIS
47.Fd #include <netdb.h> 45.Fd #include <netdb.h>
48.Ft struct protoent * 46.Ft struct protoent *
49.Fn getprotoent 47.Fn getprotoent "void"
50.Ft struct protoent * 48.Ft struct protoent *
51.Fn getprotobyname "char *name" 49.Fn getprotobyname "char *name"
52.Ft struct protoent * 50.Ft struct protoent *
53.Fn getprotobynumber "int proto" 51.Fn getprotobynumber "int proto"
52.Ft void
54.Fn setprotoent "int stayopen" 53.Fn setprotoent "int stayopen"
55.Fn endprotoent 54.Ft void
55.Fn endprotoent "void"
56.Sh DESCRIPTION 56.Sh DESCRIPTION
57The 57The
58.Fn getprotoent , 58.Fn getprotoent ,
59.Fn getprotobyname , 59.Fn getprotobyname ,
60and 60and
61.Fn getprotobynumber 61.Fn getprotobynumber
62functions 62functions each return a pointer to an object with the following structure
63each return a pointer to an object with the 63containing the broken-out fields of a line in the network protocol database,
64following structure
65containing the broken-out
66fields of a line in the network protocol data base,
67.Pa /etc/protocols . 64.Pa /etc/protocols .
68.Bd -literal -offset indent 65.Bd -literal -offset indent
69.Pp 66.Pp
@@ -79,47 +76,40 @@ The members of this structure are:
79.It Fa p_name 76.It Fa p_name
80The official name of the protocol. 77The official name of the protocol.
81.It Fa p_aliases 78.It Fa p_aliases
82A zero terminated list of alternate names for the protocol. 79A zero-terminated list of alternate names for the protocol.
83.It Fa p_proto 80.It Fa p_proto
84The protocol number. 81The protocol number.
85.El 82.El
86.Pp 83.Pp
87The 84The
88.Fn getprotoent 85.Fn getprotoent
89function 86function reads the next line of the file, opening the file if necessary.
90reads the next line of the file, opening the file if necessary.
91.Pp 87.Pp
92The 88The
93.Fn setprotoent 89.Fn setprotoent
94function 90function opens and rewinds the file.
95opens and rewinds the file. If the 91If the
96.Fa stayopen 92.Fa stayopen
97flag is non-zero, 93flag is non-zero,
98the net data base will not be closed after each call to 94the net database will not be closed after each call to
99.Fn getprotobyname 95.Fn getprotobyname
100or 96or
101.Fn getprotobynumber . 97.Fn getprotobynumber .
102.Pp 98.Pp
103The 99The
104.Fn endprotoent 100.Fn endprotoent
105function 101function closes the file.
106closes the file.
107.Pp 102.Pp
108The 103The
109.Fn getprotobyname 104.Fn getprotobyname
110function
111and 105and
112.Fn getprotobynumber 106.Fn getprotobynumber
113sequentially search from the beginning 107functions sequentially search from the beginning of the file until a
114of the file until a matching 108matching protocol name or protocol number is found, or until
115protocol name or
116protocol number is found,
117or until
118.Dv EOF 109.Dv EOF
119is encountered. 110is encountered.
120.Sh RETURN VALUES 111.Sh RETURN VALUES
121Null pointer 112Null pointer (0) returned on
122(0) returned on
123.Dv EOF 113.Dv EOF
124or error. 114or error.
125.Sh FILES 115.Sh FILES
@@ -136,11 +126,9 @@ The
136.Fn setprotoent , 126.Fn setprotoent ,
137and 127and
138.Fn endprotoent 128.Fn endprotoent
139functions appeared in 129functions appeared in
140.Bx 4.2 . 130.Bx 4.2 .
141.Sh BUGS 131.Sh BUGS
142These functions use a static data space; 132These functions use a static data space; if the data is needed for future use,
143if the data is needed for future use, it should be 133it should be copied before any subsequent calls overwrite it.
144copied before any subsequent calls overwrite it. 134Only the Internet protocols are currently understood.
145Only the Internet
146protocols are currently understood.
diff --git a/src/lib/libc/net/getprotoent.c b/src/lib/libc/net/getprotoent.c
index 1179b9029b..2f8b267611 100644
--- a/src/lib/libc/net/getprotoent.c
+++ b/src/lib/libc/net/getprotoent.c
@@ -1,5 +1,3 @@
1/* $NetBSD: getprotoent.c,v 1.4 1995/02/25 06:20:35 cgd Exp $ */
2
3/* 1/*
4 * Copyright (c) 1983, 1993 2 * Copyright (c) 1983, 1993
5 * The Regents of the University of California. All rights reserved. 3 * The Regents of the University of California. All rights reserved.
@@ -34,11 +32,7 @@
34 */ 32 */
35 33
36#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
37#if 0 35static char rcsid[] = "$OpenBSD: getprotoent.c,v 1.4 1999/09/03 16:23:18 millert Exp $";
38static char sccsid[] = "@(#)getprotoent.c 8.1 (Berkeley) 6/4/93";
39#else
40static char rcsid[] = "$NetBSD: getprotoent.c,v 1.4 1995/02/25 06:20:35 cgd Exp $";
41#endif
42#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
43 37
44#include <sys/types.h> 38#include <sys/types.h>
@@ -80,20 +74,25 @@ endprotoent()
80struct protoent * 74struct protoent *
81getprotoent() 75getprotoent()
82{ 76{
83 char *p; 77 char *p, *cp, **q, *endp;
84 register char *cp, **q; 78 long l;
79 size_t len;
85 80
86 if (protof == NULL && (protof = fopen(_PATH_PROTOCOLS, "r" )) == NULL) 81 if (protof == NULL && (protof = fopen(_PATH_PROTOCOLS, "r" )) == NULL)
87 return (NULL); 82 return (NULL);
88again: 83again:
89 if ((p = fgets(line, BUFSIZ, protof)) == NULL) 84 if ((p = fgetln(protof, &len)) == NULL)
90 return (NULL); 85 return (NULL);
91 if (*p == '#') 86 if (p[len-1] == '\n')
87 len--;
88 if (len >= sizeof(line) || len == 0)
92 goto again; 89 goto again;
93 cp = strpbrk(p, "#\n"); 90 p = memcpy(line, p, len);
94 if (cp == NULL) 91 line[len] = '\0';
92 if (*p == '#')
95 goto again; 93 goto again;
96 *cp = '\0'; 94 if ((cp = strchr(p, '#')) != NULL)
95 *cp = '\0';
97 proto.p_name = p; 96 proto.p_name = p;
98 cp = strpbrk(p, " \t"); 97 cp = strpbrk(p, " \t");
99 if (cp == NULL) 98 if (cp == NULL)
@@ -104,7 +103,10 @@ again:
104 p = strpbrk(cp, " \t"); 103 p = strpbrk(cp, " \t");
105 if (p != NULL) 104 if (p != NULL)
106 *p++ = '\0'; 105 *p++ = '\0';
107 proto.p_proto = atoi(cp); 106 l = strtol(cp, &endp, 10);
107 if (endp == cp || *endp != '\0' || l < 0 || l >= INT_MAX)
108 goto again;
109 proto.p_proto = l;
108 q = proto.p_aliases = proto_aliases; 110 q = proto.p_aliases = proto_aliases;
109 if (p != NULL) { 111 if (p != NULL) {
110 cp = p; 112 cp = p;
diff --git a/src/lib/libc/net/getprotoname.c b/src/lib/libc/net/getprotoname.c
index 4f8cf21c3f..7a4e5fede5 100644
--- a/src/lib/libc/net/getprotoname.c
+++ b/src/lib/libc/net/getprotoname.c
@@ -1,5 +1,3 @@
1/* $NetBSD: getprotoname.c,v 1.4 1995/02/25 06:20:36 cgd Exp $ */
2
3/* 1/*
4 * Copyright (c) 1983, 1993 2 * Copyright (c) 1983, 1993
5 * The Regents of the University of California. All rights reserved. 3 * The Regents of the University of California. All rights reserved.
@@ -34,11 +32,7 @@
34 */ 32 */
35 33
36#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
37#if 0 35static char rcsid[] = "$OpenBSD: getprotoname.c,v 1.3 1997/07/09 01:08:32 millert Exp $";
38static char sccsid[] = "@(#)getprotoname.c 8.1 (Berkeley) 6/4/93";
39#else
40static char rcsid[] = "$NetBSD: getprotoname.c,v 1.4 1995/02/25 06:20:36 cgd Exp $";
41#endif
42#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
43 37
44#include <netdb.h> 38#include <netdb.h>
@@ -54,7 +48,7 @@ getprotobyname(name)
54 register char **cp; 48 register char **cp;
55 49
56 setprotoent(_proto_stayopen); 50 setprotoent(_proto_stayopen);
57 while (p = getprotoent()) { 51 while ((p = getprotoent())) {
58 if (strcmp(p->p_name, name) == 0) 52 if (strcmp(p->p_name, name) == 0)
59 break; 53 break;
60 for (cp = p->p_aliases; *cp != 0; cp++) 54 for (cp = p->p_aliases; *cp != 0; cp++)
diff --git a/src/lib/libc/net/getrrsetbyname.3 b/src/lib/libc/net/getrrsetbyname.3
new file mode 100644
index 0000000000..5ff45cbbe3
--- /dev/null
+++ b/src/lib/libc/net/getrrsetbyname.3
@@ -0,0 +1,166 @@
1.\" $OpenBSD: getrrsetbyname.3,v 1.10 2003/05/01 19:04:02 jmc Exp $
2.\"
3.\" Copyright (C) 2000, 2001 Internet Software Consortium.
4.\"
5.\" Permission to use, copy, modify, and distribute this software for any
6.\" purpose with or without fee is hereby granted, provided that the above
7.\" copyright notice and this permission notice appear in all copies.
8.\"
9.\" THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
10.\" DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
11.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
12.\" INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
13.\" INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
14.\" FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
15.\" NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
16.\" WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17.\"
18.Dd October 18, 2000
19.Dt GETRRSETBYNAME 3
20.Os
21.Sh NAME
22.Nm getrrsetbyname
23.Nd retrieve DNS records
24.Sh SYNOPSIS
25.Fd #include <netdb.h>
26.Ft int
27.Fn getrrsetbyname "const char *hostname" "unsigned int rdclass" \
28"unsigned int rdtype" "unsigned int flags" "struct rrsetinfo **res"
29.Ft int
30.Fn freerrset "struct rrsetinfo **rrset"
31.Sh DESCRIPTION
32.Fn getrrsetbyname
33gets a set of resource records associated with a
34.Fa hostname ,
35.Fa class
36and
37.Fa type .
38.Fa hostname
39is a pointer a to null-terminated string.
40The
41.Fa flags
42field is currently unused and must be zero.
43.Pp
44After a successful call to
45.Fn getrrsetbyname ,
46.Fa *res
47is a pointer to an
48.Li rrsetinfo
49structure, containing a list of one or more
50.Li rdatainfo
51structures containing resource records and potentially another list of
52.Li rdatainfo
53structures containing SIG resource records associated with those records.
54The members
55.Li rri_rdclass
56and
57.Li rri_rdtype
58are copied from the parameters.
59.Li rri_ttl
60and
61.Li rri_name
62are properties of the obtained rrset.
63The resource records contained in
64.Li rri_rdatas
65and
66.Li rri_sigs
67are in uncompressed DNS wire format.
68Properties of the rdataset are represented in the
69.Li rri_flags
70bitfield.
71If the
72.Dv RRSET_VALIDATED
73bit is set, the data has been DNSSEC
74validated and the signatures verified.
75.Pp
76The following structures are used:
77.Bd -literal -offset
78struct rdatainfo {
79 unsigned int rdi_length; /* length of data */
80 unsigned char *rdi_data; /* record data */
81};
82
83struct rrsetinfo {
84 unsigned int rri_flags; /* RRSET_VALIDATED ... */
85 unsigned int rri_rdclass; /* class number */
86 unsigned int rri_rdtype; /* RR type number */
87 unsigned int rri_ttl; /* time to live */
88 unsigned int rri_nrdatas; /* size of rdatas array */
89 unsigned int rri_nsigs; /* size of sigs array */
90 char *rri_name; /* canonical name */
91 struct rdatainfo *rri_rdatas; /* individual records */
92 struct rdatainfo *rri_sigs; /* individual signatures */
93};
94.Ed
95.Pp
96All of the information returned by
97.Fn getrrsetbyname
98is dynamically allocated: the
99.Li rrsetinfo
100and
101.Li rdatainfo
102structures,
103and the canonical host name strings pointed to by the
104.Li rrsetinfo
105structure.
106Memory allocated for the dynamically allocated structures created by
107a successful call to
108.Fn getrrsetbyname
109is released by
110.Fn freerrset .
111.Li rrset
112is a pointer to a
113.Li struct rrset
114created by a call to
115.Fn getrrsetbyname .
116.Pp
117If the EDNS0 option is activated in
118.Xr resolv.conf 5 ,
119.Fn getrrsetbyname
120will request DNSSEC authentication using the EDNS0 DNSSEC OK (DO) bit.
121.Sh "RETURN VALUES"
122.Fn getrrsetbyname
123returns zero on success, and one of the following error
124codes if an error occurred:
125.Pp
126.Bl -tag -width ERRSET_NOMEMORY -compact
127.It Dv ERRSET_NONAME
128the name does not exist
129.It Dv ERRSET_NODATA
130the name exists, but does not have data of the desired type
131.It Dv ERRSET_NOMEMORY
132memory could not be allocated
133.It Dv ERRSET_INVAL
134a parameter is invalid
135.It Dv ERRSET_FAIL
136other failure
137.El
138.Sh SEE ALSO
139.Xr resolver 3 ,
140.Xr resolv.conf 5 ,
141.Xr named 8
142.Sh AUTHORS
143Jakob Schlyter
144.Aq jakob@openbsd.org
145.Sh HISTORY
146.Fn getrrsetbyname
147first appeared in
148.Ox 3.0 .
149The API first appeared in ISC BIND version 9.
150.Sh BUGS
151The data in
152.Li *rdi_data
153should be returned in uncompressed wire format.
154Currently, the data is in compressed format and the caller can't
155uncompress since it doesn't have the full message.
156.Sh CAVEATS
157The
158.Dv RRSET_VALIDATED
159flag in
160.Li rri_flags
161is set if the AD (authenticated data) bit in the DNS answer is
162set.
163This flag
164.Em should not
165be trusted unless the transport between the nameserver and the resolver
166is secure (e.g. IPsec, trusted network, loopback communication).
diff --git a/src/lib/libc/net/getrrsetbyname.c b/src/lib/libc/net/getrrsetbyname.c
new file mode 100644
index 0000000000..f00ac2b021
--- /dev/null
+++ b/src/lib/libc/net/getrrsetbyname.c
@@ -0,0 +1,512 @@
1/* $OpenBSD: getrrsetbyname.c,v 1.7 2003/03/07 07:34:14 itojun Exp $ */
2
3/*
4 * Copyright (c) 2001 Jakob Schlyter. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/*
30 * Portions Copyright (c) 1999-2001 Internet Software Consortium.
31 *
32 * Permission to use, copy, modify, and distribute this software for any
33 * purpose with or without fee is hereby granted, provided that the above
34 * copyright notice and this permission notice appear in all copies.
35 *
36 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
37 * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
38 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
39 * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
40 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
41 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
42 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
43 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
44 */
45
46#include <sys/types.h>
47#include <netinet/in.h>
48#include <arpa/nameser.h>
49#include <netdb.h>
50#include <resolv.h>
51#include <stdlib.h>
52#include <string.h>
53
54#include "thread_private.h"
55
56#define ANSWER_BUFFER_SIZE 1024*64
57
58struct dns_query {
59 char *name;
60 u_int16_t type;
61 u_int16_t class;
62 struct dns_query *next;
63};
64
65struct dns_rr {
66 char *name;
67 u_int16_t type;
68 u_int16_t class;
69 u_int16_t ttl;
70 u_int16_t size;
71 void *rdata;
72 struct dns_rr *next;
73};
74
75struct dns_response {
76 HEADER header;
77 struct dns_query *query;
78 struct dns_rr *answer;
79 struct dns_rr *authority;
80 struct dns_rr *additional;
81};
82
83static struct dns_response *parse_dns_response(const u_char *, int);
84static struct dns_query *parse_dns_qsection(const u_char *, int,
85 const u_char **, int);
86static struct dns_rr *parse_dns_rrsection(const u_char *, int, const u_char **,
87 int);
88
89static void free_dns_query(struct dns_query *);
90static void free_dns_rr(struct dns_rr *);
91static void free_dns_response(struct dns_response *);
92
93static int count_dns_rr(struct dns_rr *, u_int16_t, u_int16_t);
94
95int
96getrrsetbyname(const char *hostname, unsigned int rdclass,
97 unsigned int rdtype, unsigned int flags,
98 struct rrsetinfo **res)
99{
100 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
101 int result;
102 struct rrsetinfo *rrset = NULL;
103 struct dns_response *response;
104 struct dns_rr *rr;
105 struct rdatainfo *rdata;
106 int length;
107 unsigned int index_ans, index_sig;
108 u_char answer[ANSWER_BUFFER_SIZE];
109
110 /* check for invalid class and type */
111 if (rdclass > 0xffff || rdtype > 0xffff) {
112 result = ERRSET_INVAL;
113 goto fail;
114 }
115
116 /* don't allow queries of class or type ANY */
117 if (rdclass == 0xff || rdtype == 0xff) {
118 result = ERRSET_INVAL;
119 goto fail;
120 }
121
122 /* don't allow flags yet, unimplemented */
123 if (flags) {
124 result = ERRSET_INVAL;
125 goto fail;
126 }
127
128 /* initialize resolver */
129 if ((_resp->options & RES_INIT) == 0 && res_init() == -1) {
130 result = ERRSET_FAIL;
131 goto fail;
132 }
133
134#ifdef DEBUG
135 _resp->options |= RES_DEBUG;
136#endif /* DEBUG */
137
138#ifdef RES_USE_DNSSEC
139 /* turn on DNSSEC if EDNS0 is configured */
140 if (_resp->options & RES_USE_EDNS0)
141 _resp->options |= RES_USE_DNSSEC;
142#endif /* RES_USE_DNSEC */
143
144 /* make query */
145 length = res_query(hostname, (signed int) rdclass, (signed int) rdtype,
146 answer, sizeof(answer));
147 if (length < 0) {
148 switch(h_errno) {
149 case HOST_NOT_FOUND:
150 result = ERRSET_NONAME;
151 goto fail;
152 case NO_DATA:
153 result = ERRSET_NODATA;
154 goto fail;
155 default:
156 result = ERRSET_FAIL;
157 goto fail;
158 }
159 }
160
161 /* parse result */
162 response = parse_dns_response(answer, length);
163 if (response == NULL) {
164 result = ERRSET_FAIL;
165 goto fail;
166 }
167
168 if (response->header.qdcount != 1) {
169 result = ERRSET_FAIL;
170 goto fail;
171 }
172
173 /* initialize rrset */
174 rrset = calloc(1, sizeof(struct rrsetinfo));
175 if (rrset == NULL) {
176 result = ERRSET_NOMEMORY;
177 goto fail;
178 }
179 rrset->rri_rdclass = response->query->class;
180 rrset->rri_rdtype = response->query->type;
181 rrset->rri_ttl = response->answer->ttl;
182 rrset->rri_nrdatas = response->header.ancount;
183
184 /* check for authenticated data */
185 if (response->header.ad == 1)
186 rrset->rri_flags |= RRSET_VALIDATED;
187
188 /* copy name from answer section */
189 length = strlen(response->answer->name);
190 rrset->rri_name = malloc(length + 1);
191 if (rrset->rri_name == NULL) {
192 result = ERRSET_NOMEMORY;
193 goto fail;
194 }
195 strlcpy(rrset->rri_name, response->answer->name, length + 1);
196
197 /* count answers */
198 rrset->rri_nrdatas = count_dns_rr(response->answer, rrset->rri_rdclass,
199 rrset->rri_rdtype);
200 rrset->rri_nsigs = count_dns_rr(response->answer, rrset->rri_rdclass,
201 T_SIG);
202
203 /* allocate memory for answers */
204 rrset->rri_rdatas = calloc(rrset->rri_nrdatas,
205 sizeof(struct rdatainfo));
206 if (rrset->rri_rdatas == NULL) {
207 result = ERRSET_NOMEMORY;
208 goto fail;
209 }
210
211 /* allocate memory for signatures */
212 rrset->rri_sigs = calloc(rrset->rri_nsigs, sizeof(struct rdatainfo));
213 if (rrset->rri_sigs == NULL) {
214 result = ERRSET_NOMEMORY;
215 goto fail;
216 }
217
218 /* copy answers & signatures */
219 for (rr = response->answer, index_ans = 0, index_sig = 0;
220 rr; rr = rr->next) {
221
222 rdata = NULL;
223
224 if (rr->class == rrset->rri_rdclass &&
225 rr->type == rrset->rri_rdtype)
226 rdata = &rrset->rri_rdatas[index_ans++];
227
228 if (rr->class == rrset->rri_rdclass &&
229 rr->type == T_SIG)
230 rdata = &rrset->rri_sigs[index_sig++];
231
232 if (rdata) {
233 rdata->rdi_length = rr->size;
234 rdata->rdi_data = malloc(rr->size);
235
236 if (rdata->rdi_data == NULL) {
237 result = ERRSET_NOMEMORY;
238 goto fail;
239 }
240 memcpy(rdata->rdi_data, rr->rdata, rr->size);
241 }
242 }
243
244 *res = rrset;
245 return (ERRSET_SUCCESS);
246
247fail:
248 if (rrset != NULL)
249 freerrset(rrset);
250 return (result);
251}
252
253void
254freerrset(struct rrsetinfo *rrset)
255{
256 u_int16_t i;
257
258 if (rrset == NULL)
259 return;
260
261 if (rrset->rri_rdatas) {
262 for (i = 0; i < rrset->rri_nrdatas; i++) {
263 if (rrset->rri_rdatas[i].rdi_data == NULL)
264 break;
265 free(rrset->rri_rdatas[i].rdi_data);
266 }
267 free(rrset->rri_rdatas);
268 }
269
270 if (rrset->rri_sigs) {
271 for (i = 0; i < rrset->rri_nsigs; i++) {
272 if (rrset->rri_sigs[i].rdi_data == NULL)
273 break;
274 free(rrset->rri_sigs[i].rdi_data);
275 }
276 free(rrset->rri_sigs);
277 }
278
279 if (rrset->rri_name)
280 free(rrset->rri_name);
281 free(rrset);
282}
283
284/*
285 * DNS response parsing routines
286 */
287static struct dns_response *
288parse_dns_response(const u_char *answer, int size)
289{
290 struct dns_response *resp;
291 const u_char *cp;
292
293 /* allocate memory for the response */
294 resp = calloc(1, sizeof(*resp));
295 if (resp == NULL)
296 return (NULL);
297
298 /* initialize current pointer */
299 cp = answer;
300
301 /* copy header */
302 memcpy(&resp->header, cp, HFIXEDSZ);
303 cp += HFIXEDSZ;
304
305 /* fix header byte order */
306 resp->header.qdcount = ntohs(resp->header.qdcount);
307 resp->header.ancount = ntohs(resp->header.ancount);
308 resp->header.nscount = ntohs(resp->header.nscount);
309 resp->header.arcount = ntohs(resp->header.arcount);
310
311 /* there must be at least one query */
312 if (resp->header.qdcount < 1) {
313 free_dns_response(resp);
314 return (NULL);
315 }
316
317 /* parse query section */
318 resp->query = parse_dns_qsection(answer, size, &cp,
319 resp->header.qdcount);
320 if (resp->header.qdcount && resp->query == NULL) {
321 free_dns_response(resp);
322 return (NULL);
323 }
324
325 /* parse answer section */
326 resp->answer = parse_dns_rrsection(answer, size, &cp,
327 resp->header.ancount);
328 if (resp->header.ancount && resp->answer == NULL) {
329 free_dns_response(resp);
330 return (NULL);
331 }
332
333 /* parse authority section */
334 resp->authority = parse_dns_rrsection(answer, size, &cp,
335 resp->header.nscount);
336 if (resp->header.nscount && resp->authority == NULL) {
337 free_dns_response(resp);
338 return (NULL);
339 }
340
341 /* parse additional section */
342 resp->additional = parse_dns_rrsection(answer, size, &cp,
343 resp->header.arcount);
344 if (resp->header.arcount && resp->additional == NULL) {
345 free_dns_response(resp);
346 return (NULL);
347 }
348
349 return (resp);
350}
351
352static struct dns_query *
353parse_dns_qsection(const u_char *answer, int size, const u_char **cp, int count)
354{
355 struct dns_query *head, *curr, *prev;
356 int i, length;
357 char name[MAXDNAME];
358
359 for (i = 1, head = NULL, prev = NULL; i <= count; i++, prev = curr) {
360
361 /* allocate and initialize struct */
362 curr = calloc(1, sizeof(struct dns_query));
363 if (curr == NULL) {
364 free_dns_query(head);
365 return (NULL);
366 }
367 if (head == NULL)
368 head = curr;
369 if (prev != NULL)
370 prev->next = curr;
371
372 /* name */
373 length = dn_expand(answer, answer + size, *cp, name,
374 sizeof(name));
375 if (length < 0) {
376 free_dns_query(head);
377 return (NULL);
378 }
379 curr->name = strdup(name);
380 if (curr->name == NULL) {
381 free_dns_query(head);
382 return (NULL);
383 }
384 *cp += length;
385
386 /* type */
387 curr->type = _getshort(*cp);
388 *cp += INT16SZ;
389
390 /* class */
391 curr->class = _getshort(*cp);
392 *cp += INT16SZ;
393 }
394
395 return (head);
396}
397
398static struct dns_rr *
399parse_dns_rrsection(const u_char *answer, int size, const u_char **cp, int count)
400{
401 struct dns_rr *head, *curr, *prev;
402 int i, length;
403 char name[MAXDNAME];
404
405 for (i = 1, head = NULL, prev = NULL; i <= count; i++, prev = curr) {
406
407 /* allocate and initialize struct */
408 curr = calloc(1, sizeof(struct dns_rr));
409 if (curr == NULL) {
410 free_dns_rr(head);
411 return (NULL);
412 }
413 if (head == NULL)
414 head = curr;
415 if (prev != NULL)
416 prev->next = curr;
417
418 /* name */
419 length = dn_expand(answer, answer + size, *cp, name,
420 sizeof(name));
421 if (length < 0) {
422 free_dns_rr(head);
423 return (NULL);
424 }
425 curr->name = strdup(name);
426 if (curr->name == NULL) {
427 free_dns_rr(head);
428 return (NULL);
429 }
430 *cp += length;
431
432 /* type */
433 curr->type = _getshort(*cp);
434 *cp += INT16SZ;
435
436 /* class */
437 curr->class = _getshort(*cp);
438 *cp += INT16SZ;
439
440 /* ttl */
441 curr->ttl = _getlong(*cp);
442 *cp += INT32SZ;
443
444 /* rdata size */
445 curr->size = _getshort(*cp);
446 *cp += INT16SZ;
447
448 /* rdata itself */
449 curr->rdata = malloc(curr->size);
450 if (curr->rdata == NULL) {
451 free_dns_rr(head);
452 return (NULL);
453 }
454 memcpy(curr->rdata, *cp, curr->size);
455 *cp += curr->size;
456 }
457
458 return (head);
459}
460
461static void
462free_dns_query(struct dns_query *p)
463{
464 if (p == NULL)
465 return;
466
467 if (p->name)
468 free(p->name);
469 free_dns_query(p->next);
470 free(p);
471}
472
473static void
474free_dns_rr(struct dns_rr *p)
475{
476 if (p == NULL)
477 return;
478
479 if (p->name)
480 free(p->name);
481 if (p->rdata)
482 free(p->rdata);
483 free_dns_rr(p->next);
484 free(p);
485}
486
487static void
488free_dns_response(struct dns_response *p)
489{
490 if (p == NULL)
491 return;
492
493 free_dns_query(p->query);
494 free_dns_rr(p->answer);
495 free_dns_rr(p->authority);
496 free_dns_rr(p->additional);
497 free(p);
498}
499
500static int
501count_dns_rr(struct dns_rr *p, u_int16_t class, u_int16_t type)
502{
503 int n = 0;
504
505 while(p) {
506 if (p->class == class && p->type == type)
507 n++;
508 p = p->next;
509 }
510
511 return (n);
512}
diff --git a/src/lib/libc/net/getservbyname.c b/src/lib/libc/net/getservbyname.c
index b4a6311966..16602cc3a6 100644
--- a/src/lib/libc/net/getservbyname.c
+++ b/src/lib/libc/net/getservbyname.c
@@ -1,5 +1,3 @@
1/* $NetBSD: getservbyname.c,v 1.4 1995/02/25 06:20:36 cgd Exp $ */
2
3/* 1/*
4 * Copyright (c) 1983, 1993 2 * Copyright (c) 1983, 1993
5 * The Regents of the University of California. All rights reserved. 3 * The Regents of the University of California. All rights reserved.
@@ -34,27 +32,30 @@
34 */ 32 */
35 33
36#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
37#if 0 35static char rcsid[] = "$OpenBSD: getservbyname.c,v 1.5 2000/01/06 08:24:17 d Exp $";
38static char sccsid[] = "@(#)getservbyname.c 8.1 (Berkeley) 6/4/93";
39#else
40static char rcsid[] = "$NetBSD: getservbyname.c,v 1.4 1995/02/25 06:20:36 cgd Exp $";
41#endif
42#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
43 37
44#include <netdb.h> 38#include <netdb.h>
45#include <string.h> 39#include <string.h>
40#include "thread_private.h"
46 41
47extern int _serv_stayopen; 42extern int _serv_stayopen;
48 43
44_THREAD_PRIVATE_MUTEX(getservbyname_r);
45
49struct servent * 46struct servent *
50getservbyname(name, proto) 47getservbyname_r(name, proto, se, buf, buflen)
51 const char *name, *proto; 48 const char *name, *proto;
49 struct servent *se;
50 char *buf;
51 int buflen;
52{ 52{
53 register struct servent *p; 53 register struct servent *p;
54 register char **cp; 54 register char **cp;
55 55
56 _THREAD_PRIVATE_MUTEX_LOCK(getservbyname_r);
56 setservent(_serv_stayopen); 57 setservent(_serv_stayopen);
57 while (p = getservent()) { 58 while ((p = getservent())) {
58 if (strcmp(name, p->s_name) == 0) 59 if (strcmp(name, p->s_name) == 0)
59 goto gotname; 60 goto gotname;
60 for (cp = p->s_aliases; *cp; cp++) 61 for (cp = p->s_aliases; *cp; cp++)
@@ -67,5 +68,20 @@ gotname:
67 } 68 }
68 if (!_serv_stayopen) 69 if (!_serv_stayopen)
69 endservent(); 70 endservent();
71 _THREAD_PRIVATE_MUTEX_UNLOCK(getservbyname_r);
70 return (p); 72 return (p);
71} 73}
74
75struct servent *getservbyname(name, proto)
76 const char *name, *proto;
77{
78 _THREAD_PRIVATE_KEY(getservbyname);
79 static char buf[4096];
80 char *bufp = (char*)_THREAD_PRIVATE(getservbyname, buf, NULL);
81
82 if (bufp == NULL)
83 return (NULL);
84 return getservbyname_r(name, proto, (struct servent*) bufp,
85 bufp + sizeof(struct servent),
86 sizeof buf - sizeof(struct servent) );
87}
diff --git a/src/lib/libc/net/getservbyport.c b/src/lib/libc/net/getservbyport.c
index c34790737b..4b063760d2 100644
--- a/src/lib/libc/net/getservbyport.c
+++ b/src/lib/libc/net/getservbyport.c
@@ -1,5 +1,3 @@
1/* $NetBSD: getservbyport.c,v 1.4 1995/02/25 06:20:37 cgd Exp $ */
2
3/* 1/*
4 * Copyright (c) 1983, 1993 2 * Copyright (c) 1983, 1993
5 * The Regents of the University of California. All rights reserved. 3 * The Regents of the University of California. All rights reserved.
@@ -34,11 +32,7 @@
34 */ 32 */
35 33
36#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
37#if 0 35static char rcsid[] = "$OpenBSD: getservbyport.c,v 1.3 1997/07/09 01:08:35 millert Exp $";
38static char sccsid[] = "@(#)getservbyport.c 8.1 (Berkeley) 6/4/93";
39#else
40static char rcsid[] = "$NetBSD: getservbyport.c,v 1.4 1995/02/25 06:20:37 cgd Exp $";
41#endif
42#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
43 37
44#include <netdb.h> 38#include <netdb.h>
@@ -54,7 +48,7 @@ getservbyport(port, proto)
54 register struct servent *p; 48 register struct servent *p;
55 49
56 setservent(_serv_stayopen); 50 setservent(_serv_stayopen);
57 while (p = getservent()) { 51 while ((p = getservent())) {
58 if (p->s_port != port) 52 if (p->s_port != port)
59 continue; 53 continue;
60 if (proto == 0 || strcmp(p->s_proto, proto) == 0) 54 if (proto == 0 || strcmp(p->s_proto, proto) == 0)
diff --git a/src/lib/libc/net/getservent.3 b/src/lib/libc/net/getservent.3
index 9e0656be00..85e0d65352 100644
--- a/src/lib/libc/net/getservent.3
+++ b/src/lib/libc/net/getservent.3
@@ -1,4 +1,4 @@
1.\" $NetBSD: getservent.3,v 1.3 1995/02/25 06:20:38 cgd Exp $ 1.\" $OpenBSD: getservent.3,v 1.11 2000/12/24 00:30:56 aaron Exp $
2.\" 2.\"
3.\" Copyright (c) 1983, 1991, 1993 3.\" Copyright (c) 1983, 1991, 1993
4.\" The Regents of the University of California. All rights reserved. 4.\" The Regents of the University of California. All rights reserved.
@@ -31,11 +31,9 @@
31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32.\" SUCH DAMAGE. 32.\" SUCH DAMAGE.
33.\" 33.\"
34.\" @(#)getservent.3 8.3 (Berkeley) 1/12/94
35.\"
36.Dd January 12, 1994 34.Dd January 12, 1994
37.Dt GETSERVENT 3 35.Dt GETSERVENT 3
38.Os BSD 4.2 36.Os
39.Sh NAME 37.Sh NAME
40.Nm getservent , 38.Nm getservent ,
41.Nm getservbyport , 39.Nm getservbyport ,
@@ -46,26 +44,23 @@
46.Sh SYNOPSIS 44.Sh SYNOPSIS
47.Fd #include <netdb.h> 45.Fd #include <netdb.h>
48.Ft struct servent * 46.Ft struct servent *
49.Fn getservent 47.Fn getservent "void"
50.Ft struct servent * 48.Ft struct servent *
51.Fn getservbyname "char *name" "char *proto" 49.Fn getservbyname "char *name" "char *proto"
52.Ft struct servent * 50.Ft struct servent *
53.Fn getservbyport "int port" proto 51.Fn getservbyport "int port" "char *proto"
54.Ft void 52.Ft void
55.Fn setservent "int stayopen" 53.Fn setservent "int stayopen"
56.Ft void 54.Ft void
57.Fn endservent void 55.Fn endservent "void"
58.Sh DESCRIPTION 56.Sh DESCRIPTION
59The 57The
60.Fn getservent , 58.Fn getservent ,
61.Fn getservbyname , 59.Fn getservbyname ,
62and 60and
63.Fn getservbyport 61.Fn getservbyport
64functions 62functions each return a pointer to an object with the following structure
65each return a pointer to an object with the 63containing the broken-out fields of a line in the network services database,
66following structure
67containing the broken-out
68fields of a line in the network services data base,
69.Pa /etc/services . 64.Pa /etc/services .
70.Bd -literal -offset indent 65.Bd -literal -offset indent
71struct servent { 66struct servent {
@@ -81,59 +76,50 @@ The members of this structure are:
81.It Fa s_name 76.It Fa s_name
82The official name of the service. 77The official name of the service.
83.It Fa s_aliases 78.It Fa s_aliases
84A zero terminated list of alternate names for the service. 79A zero-terminated list of alternate names for the service.
85.It Fa s_port 80.It Fa s_port
86The port number at which the service resides. 81The port number at which the service resides.
87Port numbers are returned in network byte order. 82Port numbers are returned in network byte order.
88.It Fa s_proto 83.It Fa s_proto
89The name of the protocol to use when contacting the 84The name of the protocol to use when contacting the service.
90service.
91.El 85.El
92.Pp 86.Pp
93The 87The
94.Fn getservent 88.Fn getservent
95function 89function reads the next line of the file, opening the file if necessary.
96reads the next line of the file, opening the file if necessary.
97.Pp 90.Pp
98The 91The
99.Fn setservent 92.Fn setservent
100function 93function opens and rewinds the file.
101opens and rewinds the file. If the 94If the
102.Fa stayopen 95.Fa stayopen
103flag is non-zero, 96flag is non-zero,
104the net data base will not be closed after each call to 97the net database will not be closed after each call to
105.Fn getservbyname 98.Fn getservbyname
106or 99or
107.Fn getservbyport . 100.Fn getservbyport .
108.Pp 101.Pp
109The 102The
110.Fn endservent 103.Fn endservent
111function 104function closes the file.
112closes the file.
113.Pp 105.Pp
114The 106The
115.Fn getservbyname 107.Fn getservbyname
116and 108and
117.Fn getservbyport 109.Fn getservbyport
118functions 110functions sequentially search from the beginning of the file until a
119sequentially search from the beginning 111matching protocol name or port number (specified in network byte order)
120of the file until a matching 112is found, or until
121protocol name or
122port number is found,
123or until
124.Dv EOF 113.Dv EOF
125is encountered. 114is encountered.
126If a protocol name is also supplied (non- 115If a protocol name is also supplied (non-null),
127.Dv NULL ) ,
128searches must also match the protocol. 116searches must also match the protocol.
129.ne 1i
130.Sh FILES 117.Sh FILES
131.Bl -tag -width /etc/services -compact 118.Bl -tag -width /etc/services -compact
132.It Pa /etc/services 119.It Pa /etc/services
133.El 120.El
134.Sh DIAGNOSTICS 121.Sh DIAGNOSTICS
135Null pointer 122Null pointer (0) returned on
136(0) returned on
137.Dv EOF 123.Dv EOF
138or error. 124or error.
139.Sh SEE ALSO 125.Sh SEE ALSO
@@ -147,11 +133,9 @@ The
147.Fn setservent , 133.Fn setservent ,
148and 134and
149.Fn endservent 135.Fn endservent
150functions appeared in 136functions appeared in
151.Bx 4.2 . 137.Bx 4.2 .
152.Sh BUGS 138.Sh BUGS
153These functions use static data storage; 139These functions use static data storage; if the data is needed for future use,
154if the data is needed for future use, it should be 140it should be copied before any subsequent calls overwrite it.
155copied before any subsequent calls overwrite it. 141Expecting port numbers to fit in a 32-bit quantity is probably naive.
156Expecting port numbers to fit in a 32 bit
157quantity is probably naive.
diff --git a/src/lib/libc/net/getservent.c b/src/lib/libc/net/getservent.c
index 316891450e..ff6bf1e57f 100644
--- a/src/lib/libc/net/getservent.c
+++ b/src/lib/libc/net/getservent.c
@@ -1,5 +1,3 @@
1/* $NetBSD: getservent.c,v 1.4 1995/02/25 06:20:38 cgd Exp $ */
2
3/* 1/*
4 * Copyright (c) 1983, 1993 2 * Copyright (c) 1983, 1993
5 * The Regents of the University of California. All rights reserved. 3 * The Regents of the University of California. All rights reserved.
@@ -34,11 +32,7 @@
34 */ 32 */
35 33
36#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
37#if 0 35static char rcsid[] = "$OpenBSD: getservent.c,v 1.5 1999/09/03 16:23:19 millert Exp $";
38static char sccsid[] = "@(#)getservent.c 8.1 (Berkeley) 6/4/93";
39#else
40static char rcsid[] = "$NetBSD: getservent.c,v 1.4 1995/02/25 06:20:38 cgd Exp $";
41#endif
42#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
43 37
44#include <sys/types.h> 38#include <sys/types.h>
@@ -80,20 +74,25 @@ endservent()
80struct servent * 74struct servent *
81getservent() 75getservent()
82{ 76{
83 char *p; 77 char *p, *cp, **q, *endp;
84 register char *cp, **q; 78 long l;
79 size_t len;
85 80
86 if (servf == NULL && (servf = fopen(_PATH_SERVICES, "r" )) == NULL) 81 if (servf == NULL && (servf = fopen(_PATH_SERVICES, "r" )) == NULL)
87 return (NULL); 82 return (NULL);
88again: 83again:
89 if ((p = fgets(line, BUFSIZ, servf)) == NULL) 84 if ((p = fgetln(servf, &len)) == NULL)
90 return (NULL); 85 return (NULL);
91 if (*p == '#') 86 if (p[len-1] == '\n')
87 len--;
88 if (len >= sizeof(line) || len == 0)
92 goto again; 89 goto again;
93 cp = strpbrk(p, "#\n"); 90 p = memcpy(line, p, len);
94 if (cp == NULL) 91 line[len] = '\0';
92 if (*p == '#')
95 goto again; 93 goto again;
96 *cp = '\0'; 94 if ((cp = strchr(p, '#')) != NULL)
95 *cp = '\0';
97 serv.s_name = p; 96 serv.s_name = p;
98 p = strpbrk(p, " \t"); 97 p = strpbrk(p, " \t");
99 if (p == NULL) 98 if (p == NULL)
@@ -105,7 +104,10 @@ again:
105 if (cp == NULL) 104 if (cp == NULL)
106 goto again; 105 goto again;
107 *cp++ = '\0'; 106 *cp++ = '\0';
108 serv.s_port = htons((u_short)atoi(p)); 107 l = strtol(p, &endp, 10);
108 if (endp == p || *endp != '\0' || l < 0 || l > USHRT_MAX)
109 goto again;
110 serv.s_port = htons((in_port_t)l);
109 serv.s_proto = cp; 111 serv.s_proto = cp;
110 q = serv.s_aliases = serv_aliases; 112 q = serv.s_aliases = serv_aliases;
111 cp = strpbrk(cp, " \t"); 113 cp = strpbrk(cp, " \t");
diff --git a/src/lib/libc/net/herror.c b/src/lib/libc/net/herror.c
index 41adbf1055..737bb115a7 100644
--- a/src/lib/libc/net/herror.c
+++ b/src/lib/libc/net/herror.c
@@ -1,9 +1,11 @@
1/* $NetBSD: herror.c,v 1.5 1995/02/25 06:20:39 cgd Exp $ */ 1/* $OpenBSD: herror.c,v 1.4 1997/03/13 19:07:28 downsj Exp $ */
2 2
3/*- 3/*
4 * ++Copyright++ 1987, 1993
5 * -
4 * Copyright (c) 1987, 1993 6 * Copyright (c) 1987, 1993
5 * The Regents of the University of California. All rights reserved. 7 * The Regents of the University of California. All rights reserved.
6 * 8 *
7 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
9 * are met: 11 * are met:
@@ -14,12 +16,12 @@
14 * documentation and/or other materials provided with the distribution. 16 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software 17 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement: 18 * must display the following acknowledgement:
17 * This product includes software developed by the University of 19 * This product includes software developed by the University of
18 * California, Berkeley and its contributors. 20 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors 21 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software 22 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission. 23 * without specific prior written permission.
22 * 24 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -56,26 +58,27 @@
56#if defined(LIBC_SCCS) && !defined(lint) 58#if defined(LIBC_SCCS) && !defined(lint)
57#if 0 59#if 0
58static char sccsid[] = "@(#)herror.c 8.1 (Berkeley) 6/4/93"; 60static char sccsid[] = "@(#)herror.c 8.1 (Berkeley) 6/4/93";
59static char rcsid[] = "$Id: herror.c,v 4.9.1.1 1993/05/02 23:14:35 vixie Rel "; 61static char rcsid[] = "$From: herror.c,v 8.3 1996/08/05 08:31:35 vixie Exp $";
60#else 62#else
61static char rcsid[] = "$NetBSD: herror.c,v 1.5 1995/02/25 06:20:39 cgd Exp $"; 63static char rcsid[] = "$OpenBSD: herror.c,v 1.4 1997/03/13 19:07:28 downsj Exp $";
62#endif 64#endif
63#endif /* LIBC_SCCS and not lint */ 65#endif /* LIBC_SCCS and not lint */
64 66
65#include <sys/types.h> 67#include <sys/types.h>
68#include <sys/param.h>
66#include <sys/uio.h> 69#include <sys/uio.h>
67#include <netdb.h> 70#include <netdb.h>
68#include <unistd.h> 71#include <unistd.h>
69#include <string.h> 72#include <string.h>
70 73
71char *h_errlist[] = { 74const char *h_errlist[] = {
72 "Error 0", 75 "Resolver Error 0 (no error)",
73 "Unknown host", /* 1 HOST_NOT_FOUND */ 76 "Unknown host", /* 1 HOST_NOT_FOUND */
74 "Host name lookup failure", /* 2 TRY_AGAIN */ 77 "Host name lookup failure", /* 2 TRY_AGAIN */
75 "Unknown server error", /* 3 NO_RECOVERY */ 78 "Unknown server error", /* 3 NO_RECOVERY */
76 "No address associated with name", /* 4 NO_ADDRESS */ 79 "No address associated with name", /* 4 NO_ADDRESS */
77}; 80};
78int h_nerr = { sizeof(h_errlist)/sizeof(h_errlist[0]) }; 81int h_nerr = { sizeof h_errlist / sizeof h_errlist[0] };
79 82
80extern int h_errno; 83extern int h_errno;
81 84
@@ -98,8 +101,7 @@ herror(s)
98 v->iov_len = 2; 101 v->iov_len = 2;
99 v++; 102 v++;
100 } 103 }
101 v->iov_base = (u_int)h_errno < h_nerr ? 104 v->iov_base = (char *)hstrerror(h_errno);
102 h_errlist[h_errno] : "Unknown error";
103 v->iov_len = strlen(v->iov_base); 105 v->iov_len = strlen(v->iov_base);
104 v++; 106 v++;
105 v->iov_base = "\n"; 107 v->iov_base = "\n";
@@ -107,9 +109,13 @@ herror(s)
107 writev(STDERR_FILENO, iov, (v - iov) + 1); 109 writev(STDERR_FILENO, iov, (v - iov) + 1);
108} 110}
109 111
110char * 112const char *
111hstrerror(err) 113hstrerror(err)
112 int err; 114 int err;
113{ 115{
114 return (u_int)err < h_nerr ? h_errlist[err] : "Unknown resolver error"; 116 if (err < 0)
117 return ("Resolver internal error");
118 else if (err < h_nerr)
119 return (h_errlist[err]);
120 return ("Unknown resolver error");
115} 121}
diff --git a/src/lib/libc/net/htonl.c b/src/lib/libc/net/htonl.c
index ac85cb0fd7..73b7432731 100644
--- a/src/lib/libc/net/htonl.c
+++ b/src/lib/libc/net/htonl.c
@@ -1,29 +1,25 @@
1/* $NetBSD: htonl.c,v 1.5 1995/04/28 23:25:14 jtc Exp $ */
2
3/* 1/*
4 * Written by J.T. Conklin <jtc@netbsd.org>. 2 * Written by J.T. Conklin <jtc@netbsd.org>.
5 * Public domain. 3 * Public domain.
6 */ 4 */
7 5
8#if defined(LIBC_SCCS) && !defined(lint) 6#if defined(LIBC_SCCS) && !defined(lint)
9static char *rcsid = "$NetBSD: htonl.c,v 1.5 1995/04/28 23:25:14 jtc Exp $"; 7static char *rcsid = "$OpenBSD: htonl.c,v 1.4 1996/12/12 03:19:55 tholo Exp $";
10#endif 8#endif /* LIBC_SCCS and not lint */
11 9
12#include <sys/types.h> 10#include <sys/types.h>
13#include <machine/endian.h> 11#include <machine/endian.h>
14 12
15#undef htonl 13#undef htonl
16 14
17unsigned long 15u_int32_t
18htonl(x) 16htonl(x)
19 unsigned long x; 17 u_int32_t x;
20{ 18{
21 u_int32_t y = x;
22
23#if BYTE_ORDER == LITTLE_ENDIAN 19#if BYTE_ORDER == LITTLE_ENDIAN
24 u_char *s = (u_char *)&y; 20 u_char *s = (u_char *)&x;
25 return s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3]; 21 return (u_int32_t)(s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3]);
26#else 22#else
27 return y; 23 return x;
28#endif 24#endif
29} 25}
diff --git a/src/lib/libc/net/htons.c b/src/lib/libc/net/htons.c
index b2500a51d1..ded70712ea 100644
--- a/src/lib/libc/net/htons.c
+++ b/src/lib/libc/net/htons.c
@@ -1,26 +1,23 @@
1/* $NetBSD: htons.c,v 1.5 1995/04/28 23:25:19 jtc Exp $ */
2
3/* 1/*
4 * Written by J.T. Conklin <jtc@netbsd.org>. 2 * Written by J.T. Conklin <jtc@netbsd.org>.
5 * Public domain. 3 * Public domain.
6 */ 4 */
7 5
8#if defined(LIBC_SCCS) && !defined(lint) 6#if defined(LIBC_SCCS) && !defined(lint)
9static char *rcsid = "$NetBSD: htons.c,v 1.5 1995/04/28 23:25:19 jtc Exp $"; 7static char *rcsid = "$OpenBSD: htons.c,v 1.7 2002/02/19 19:39:36 millert Exp $";
10#endif 8#endif /* LIBC_SCCS and not lint */
11 9
12#include <sys/types.h> 10#include <sys/types.h>
13#include <machine/endian.h> 11#include <machine/endian.h>
14 12
15#undef htons 13#undef htons
16 14
17unsigned short 15u_int16_t
18htons(x) 16htons(u_int16_t x)
19 unsigned short x;
20{ 17{
21#if BYTE_ORDER == LITTLE_ENDIAN 18#if BYTE_ORDER == LITTLE_ENDIAN
22 u_char *s = (u_char *) &x; 19 u_char *s = (u_char *) &x;
23 return s[0] << 8 | s[1]; 20 return (u_int16_t)(s[0] << 8 | s[1]);
24#else 21#else
25 return x; 22 return x;
26#endif 23#endif
diff --git a/src/lib/libc/net/if_indextoname.3 b/src/lib/libc/net/if_indextoname.3
new file mode 100644
index 0000000000..85269c3769
--- /dev/null
+++ b/src/lib/libc/net/if_indextoname.3
@@ -0,0 +1,140 @@
1.\" $OpenBSD: if_indextoname.3,v 1.5 2002/03/07 22:41:12 millert Exp $
2.\" Copyright (c) 1983, 1991, 1993
3.\" The Regents of the University of California. All rights reserved.
4.\"
5.\" Redistribution and use in source and binary forms, with or without
6.\" modification, are permitted provided that the following conditions
7.\" are met:
8.\" 1. Redistributions of source code must retain the above copyright
9.\" notice, this list of conditions and the following disclaimer.
10.\" 2. Redistributions in binary form must reproduce the above copyright
11.\" notice, this list of conditions and the following disclaimer in the
12.\" documentation and/or other materials provided with the distribution.
13.\" 3. All advertising materials mentioning features or use of this software
14.\" must display the following acknowledgement:
15.\" This product includes software developed by the University of
16.\" California, Berkeley and its contributors.
17.\" 4. Neither the name of the University nor the names of its contributors
18.\" may be used to endorse or promote products derived from this software
19.\" without specific prior written permission.
20.\"
21.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31.\" SUCH DAMAGE.
32.\"
33.\" From: @(#)rcmd.3 8.1 (Berkeley) 6/4/93
34.\"
35.Dd May 21, 1998
36.Dt IF_NAMETOINDEX 3
37.Os
38.Sh NAME
39.Nm if_nametoindex ,
40.Nm if_indextoname ,
41.Nm if_nameindex ,
42.Nm if_freenameindex
43.Nd convert interface index to name, and vice versa
44.Sh SYNOPSIS
45.Fd #include <net/if.h>
46.Ft "unsigned int"
47.Fn if_nametoindex "const char *ifname"
48.Ft "char *"
49.Fn if_indextoname "unsigned int ifindex" "char *ifname"
50.Ft "struct if_nameindex *"
51.Fn if_nameindex "void"
52.Ft "void"
53.Fn if_freenameindex "struct if_nameindex *ptr"
54.Sh DESCRIPTION
55These functions map interface indexes to interface names (such as
56.Dq lo0 ) ,
57and vice versa.
58.Pp
59The
60.Fn if_nametoindex
61function converts an interface name specified by the
62.Fa ifname
63argument to an interface index (positive integer value).
64If the specified interface does not exist, 0 will be returned.
65.Pp
66.Fn if_indextoname
67converts an interface index specified by the
68.Fa ifindex
69argument to an interface name.
70The
71.Fa ifname
72argument must point to a buffer of at least
73.Dv IF_NAMESIZE
74bytes into which the interface name corresponding to the specified index is
75returned.
76.Pf ( Dv IF_NAMESIZE
77is also defined in
78.Aq Pa net/if.h
79and its value includes a terminating null byte at the end of the
80interface name.)
81This pointer is also the return value of the function.
82If there is no interface corresponding to the specified index,
83.Dv NULL
84is returned.
85.Pp
86.Fn if_nameindex
87returns an array of
88.Fa if_nameindex
89structures.
90.Fa if_nametoindex
91is also defined in
92.Aq Pa net/if.h ,
93and is as follows:
94.Bd -literal -offset
95struct if_nameindex {
96 unsigned int if_index; /* 1, 2, ... */
97 char *if_name; /* null terminated name: "le0", ... */
98};
99.Ed
100.Pp
101The end of the array of structures is indicated by a structure with
102an
103.Fa if_index
104of 0 and an
105.Fa if_name
106of
107.Dv NULL .
108The function returns a null pointer on error.
109The memory used for this array of structures along with the interface
110names pointed to by the
111.Fa if_name
112members is obtained dynamically.
113This memory is freed by the
114.Fn if_freenameindex
115function.
116.Pp
117.Fn if_freenameindex
118takes a pointer that was returned by
119.Fn if_nameindex
120as argument
121.Pq Fa ptr ,
122and it reclaims the region allocated.
123.Sh DIAGNOSTICS
124.Fn if_nametoindex
125returns 0 on error, positive integer on success.
126.Fn if_indextoname
127and
128.Fn if_nameindex
129return
130.Dv NULL
131on errors.
132.Sh SEE ALSO
133.Xr getifaddrs 3 ,
134.Xr networking 4
135.Pp
136R. Gilligan, S. Thomson, J. Bound, and W. Stevens,
137``Basic Socket Interface Extensions for IPv6,'' RFC2553, March 1999.
138.Sh STANDARDS
139These functions are defined in ``Basic Socket Interface Extensions for IPv6''
140.Pq RFC2533 .
diff --git a/src/lib/libc/net/if_indextoname.c b/src/lib/libc/net/if_indextoname.c
new file mode 100644
index 0000000000..f99e52e387
--- /dev/null
+++ b/src/lib/libc/net/if_indextoname.c
@@ -0,0 +1,86 @@
1/* $OpenBSD: if_indextoname.c,v 1.9 2002/03/07 22:40:23 millert Exp $ */
2/* $KAME: if_indextoname.c,v 1.6 2000/11/07 22:33:25 jinmei Exp $ */
3
4/*-
5 * Copyright (c) 1997, 2000
6 * Berkeley Software Design, Inc. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 *
14 * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * BSDI Id: if_indextoname.c,v 2.3 2000/04/17 22:38:05 dab Exp
27 */
28
29#include <sys/types.h>
30#include <sys/socket.h>
31#include <net/if_dl.h>
32#include <net/if.h>
33#include <ifaddrs.h>
34#include <stdlib.h>
35#include <string.h>
36#include <errno.h>
37
38/*
39 * From RFC 2533:
40 *
41 * The second function maps an interface index into its corresponding
42 * name.
43 *
44 * #include <net/if.h>
45 *
46 * char *if_indextoname(unsigned int ifindex, char *ifname);
47 *
48 * The ifname argument must point to a buffer of at least IF_NAMESIZE
49 * bytes into which the interface name corresponding to the specified
50 * index is returned. (IF_NAMESIZE is also defined in <net/if.h> and
51 * its value includes a terminating null byte at the end of the
52 * interface name.) This pointer is also the return value of the
53 * function. If there is no interface corresponding to the specified
54 * index, NULL is returned, and errno is set to ENXIO, if there was a
55 * system error (such as running out of memory), if_indextoname returns
56 * NULL and errno would be set to the proper value (e.g., ENOMEM).
57 */
58
59char *
60if_indextoname(unsigned int ifindex, char *ifname)
61{
62 struct ifaddrs *ifaddrs, *ifa;
63 int error = 0;
64
65 if (getifaddrs(&ifaddrs) < 0)
66 return(NULL); /* getifaddrs properly set errno */
67
68 for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
69 if (ifa->ifa_addr &&
70 ifa->ifa_addr->sa_family == AF_LINK &&
71 ifindex == ((struct sockaddr_dl*)ifa->ifa_addr)->sdl_index)
72 break;
73 }
74
75 if (ifa == NULL) {
76 error = ENXIO;
77 ifname = NULL;
78 }
79 else
80 strlcpy(ifname, ifa->ifa_name, IFNAMSIZ);
81
82 freeifaddrs(ifaddrs);
83
84 errno = error;
85 return(ifname);
86}
diff --git a/src/lib/libc/net/if_nameindex.c b/src/lib/libc/net/if_nameindex.c
new file mode 100644
index 0000000000..3675a2a450
--- /dev/null
+++ b/src/lib/libc/net/if_nameindex.c
@@ -0,0 +1,140 @@
1/* $OpenBSD: if_nameindex.c,v 1.9 2002/03/07 22:40:23 millert Exp $ */
2/* $KAME: if_nameindex.c,v 1.7 2000/11/24 08:17:20 itojun Exp $ */
3
4/*-
5 * Copyright (c) 1997, 2000
6 * Berkeley Software Design, Inc. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 *
14 * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * BSDI Id: if_nameindex.c,v 2.3 2000/04/17 22:38:05 dab Exp
27 */
28
29#include <sys/types.h>
30#include <sys/socket.h>
31#include <net/if_dl.h>
32#include <net/if.h>
33#include <ifaddrs.h>
34#include <stdlib.h>
35#include <string.h>
36
37/*
38 * From RFC 2553:
39 *
40 * 4.3 Return All Interface Names and Indexes
41 *
42 * The if_nameindex structure holds the information about a single
43 * interface and is defined as a result of including the <net/if.h>
44 * header.
45 *
46 * struct if_nameindex {
47 * unsigned int if_index;
48 * char *if_name;
49 * };
50 *
51 * The final function returns an array of if_nameindex structures, one
52 * structure per interface.
53 *
54 * struct if_nameindex *if_nameindex(void);
55 *
56 * The end of the array of structures is indicated by a structure with
57 * an if_index of 0 and an if_name of NULL. The function returns a NULL
58 * pointer upon an error, and would set errno to the appropriate value.
59 *
60 * The memory used for this array of structures along with the interface
61 * names pointed to by the if_name members is obtained dynamically.
62 * This memory is freed by the next function.
63 *
64 * 4.4. Free Memory
65 *
66 * The following function frees the dynamic memory that was allocated by
67 * if_nameindex().
68 *
69 * #include <net/if.h>
70 *
71 * void if_freenameindex(struct if_nameindex *ptr);
72 *
73 * The argument to this function must be a pointer that was returned by
74 * if_nameindex().
75 */
76
77struct if_nameindex *
78if_nameindex(void)
79{
80 struct ifaddrs *ifaddrs, *ifa;
81 unsigned int ni;
82 size_t nbytes;
83 struct if_nameindex *ifni, *ifni2;
84 char *cp;
85
86 if (getifaddrs(&ifaddrs) < 0)
87 return(NULL);
88
89 /*
90 * First, find out how many interfaces there are, and how
91 * much space we need for the string names.
92 */
93 ni = 0;
94 nbytes = 0;
95 for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
96 if (ifa->ifa_addr &&
97 ifa->ifa_addr->sa_family == AF_LINK) {
98 nbytes += strlen(ifa->ifa_name) + 1;
99 ni++;
100 }
101 }
102
103 /*
104 * Next, allocate a chunk of memory, use the first part
105 * for the array of structures, and the last part for
106 * the strings.
107 */
108 cp = malloc((ni + 1) * sizeof(struct if_nameindex) + nbytes);
109 ifni = (struct if_nameindex *)cp;
110 if (ifni == NULL)
111 goto out;
112 cp += (ni + 1) * sizeof(struct if_nameindex);
113
114 /*
115 * Now just loop through the list of interfaces again,
116 * filling in the if_nameindex array and making copies
117 * of all the strings.
118 */
119 ifni2 = ifni;
120 for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
121 if (ifa->ifa_addr &&
122 ifa->ifa_addr->sa_family == AF_LINK) {
123 ifni2->if_index =
124 ((struct sockaddr_dl*)ifa->ifa_addr)->sdl_index;
125 ifni2->if_name = cp;
126 nbytes = strlen(ifa->ifa_name) + 1;
127 memcpy(cp, ifa->ifa_name, nbytes);
128 ifni2++;
129 cp += nbytes;
130 }
131 }
132 /*
133 * Finally, don't forget to terminate the array.
134 */
135 ifni2->if_index = 0;
136 ifni2->if_name = NULL;
137out:
138 freeifaddrs(ifaddrs);
139 return(ifni);
140}
diff --git a/src/lib/libc/net/if_nametoindex.c b/src/lib/libc/net/if_nametoindex.c
new file mode 100644
index 0000000000..8bd792b949
--- /dev/null
+++ b/src/lib/libc/net/if_nametoindex.c
@@ -0,0 +1,81 @@
1/* $OpenBSD: if_nametoindex.c,v 1.8 2002/03/07 22:40:23 millert Exp $ */
2/* $KAME: if_nametoindex.c,v 1.5 2000/11/24 08:04:40 itojun Exp $ */
3
4/*-
5 * Copyright (c) 1997, 2000
6 * Berkeley Software Design, Inc. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 *
14 * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * BSDI Id: if_nametoindex.c,v 2.3 2000/04/17 22:38:05 dab Exp
27 */
28
29#include <sys/types.h>
30#include <sys/socket.h>
31#include <net/if.h>
32#include <net/if_dl.h>
33#include <ifaddrs.h>
34#include <stdlib.h>
35#include <string.h>
36#include <errno.h>
37
38/*
39 * From RFC 2553:
40 *
41 * 4.1 Name-to-Index
42 *
43 *
44 * The first function maps an interface name into its corresponding
45 * index.
46 *
47 * #include <net/if.h>
48 *
49 * unsigned int if_nametoindex(const char *ifname);
50 *
51 * If the specified interface name does not exist, the return value is
52 * 0, and errno is set to ENXIO. If there was a system error (such as
53 * running out of memory), the return value is 0 and errno is set to the
54 * proper value (e.g., ENOMEM).
55 */
56
57unsigned int
58if_nametoindex(const char *ifname)
59{
60 struct ifaddrs *ifaddrs, *ifa;
61 unsigned int ni;
62
63 if (getifaddrs(&ifaddrs) < 0)
64 return(0);
65
66 ni = 0;
67
68 for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
69 if (ifa->ifa_addr &&
70 ifa->ifa_addr->sa_family == AF_LINK &&
71 strcmp(ifa->ifa_name, ifname) == 0) {
72 ni = ((struct sockaddr_dl*)ifa->ifa_addr)->sdl_index;
73 break;
74 }
75 }
76
77 freeifaddrs(ifaddrs);
78 if (!ni)
79 errno = ENXIO;
80 return(ni);
81}
diff --git a/src/lib/libc/net/inet.3 b/src/lib/libc/net/inet.3
index 49bac97e96..b15c478aef 100644
--- a/src/lib/libc/net/inet.3
+++ b/src/lib/libc/net/inet.3
@@ -1,4 +1,5 @@
1.\" $NetBSD: inet.3,v 1.4 1995/02/27 09:45:26 chopps Exp $ 1.\" $OpenBSD: inet.3,v 1.15 2003/05/01 19:17:37 jmc Exp $
2.\" $NetBSD: inet.3,v 1.7 1997/06/18 02:25:24 lukem Exp $
2.\" 3.\"
3.\" Copyright (c) 1983, 1990, 1991, 1993 4.\" Copyright (c) 1983, 1990, 1991, 1993
4.\" The Regents of the University of California. All rights reserved. 5.\" The Regents of the University of California. All rights reserved.
@@ -33,36 +34,43 @@
33.\" 34.\"
34.\" @(#)inet.3 8.1 (Berkeley) 6/4/93 35.\" @(#)inet.3 8.1 (Berkeley) 6/4/93
35.\" 36.\"
36.Dd June 4, 1993 37.Dd June 18, 1997
37.Dt INET 3 38.Dt INET 3
38.Os BSD 4.2 39.Os
39.Sh NAME 40.Sh NAME
40.Nm inet_aton ,
41.Nm inet_addr , 41.Nm inet_addr ,
42.Nm inet_aton ,
43.Nm inet_lnaof ,
44.Nm inet_makeaddr ,
45.Nm inet_netof ,
42.Nm inet_network , 46.Nm inet_network ,
43.Nm inet_ntoa , 47.Nm inet_ntoa ,
44.Nm inet_makeaddr , 48.Nm inet_ntop ,
45.Nm inet_lnaof , 49.Nm inet_pton
46.Nm inet_netof
47.Nd Internet address manipulation routines 50.Nd Internet address manipulation routines
48.Sh SYNOPSIS 51.Sh SYNOPSIS
52.Fd #include <sys/types.h>
49.Fd #include <sys/socket.h> 53.Fd #include <sys/socket.h>
50.Fd #include <netinet/in.h> 54.Fd #include <netinet/in.h>
51.Fd #include <arpa/inet.h> 55.Fd #include <arpa/inet.h>
52.Ft int 56.Ft in_addr_t
53.Fn inet_aton "const char *cp" "struct in_addr *pin"
54.Ft unsigned long
55.Fn inet_addr "const char *cp" 57.Fn inet_addr "const char *cp"
56.Ft unsigned long 58.Ft int
59.Fn inet_aton "const char *cp" "struct in_addr *addr"
60.Ft in_addr_t
61.Fn inet_lnaof "struct in_addr in"
62.Ft struct in_addr
63.Fn inet_makeaddr "unsigned long net" "unsigned long lna"
64.Ft in_addr_t
65.Fn inet_netof "struct in_addr in"
66.Ft in_addr_t
57.Fn inet_network "const char *cp" 67.Fn inet_network "const char *cp"
58.Ft char * 68.Ft char *
59.Fn inet_ntoa "struct in_addr in" 69.Fn inet_ntoa "struct in_addr in"
60.Ft struct in_addr 70.Ft const char *
61.Fn inet_makeaddr "int net" "int lna" 71.Fn inet_ntop "int af" "const void *src" "char *dst" "size_t size"
62.Ft unsigned long 72.Ft int
63.Fn inet_lnaof "struct in_addr in" 73.Fn inet_pton "int af" "const char *src" "void *dst"
64.Ft unsigned long
65.Fn inet_netof "struct in_addr in"
66.Sh DESCRIPTION 74.Sh DESCRIPTION
67The routines 75The routines
68.Fn inet_aton , 76.Fn inet_aton ,
@@ -74,11 +82,26 @@ numbers expressed in the Internet standard
74.Ql \&. 82.Ql \&.
75notation. 83notation.
76The 84The
85.Fn inet_pton
86function converts a presentation format address (that is, printable form
87as held in a character string) to network format (usually a
88.Li struct in_addr
89or some other internal binary representation, in network byte order).
90It returns 1 if the address was valid for the specified address family, or
910 if the address wasn't parseable in the specified address family, or \-1
92if some system error occurred (in which case
93.Va errno
94will have been set).
95This function is presently valid for
96.Dv AF_INET
97and
98.Dv AF_INET6 .
99The
77.Fn inet_aton 100.Fn inet_aton
78routine interprets the specified character string as an Internet address, 101routine interprets the specified character string as an Internet address,
79placing the address into the structure provided. 102placing the address into the structure provided.
80It returns 1 if the string was successfully interpreted, 103It returns 1 if the string was successfully interpreted,
81or 0 if the string is invalid. 104or 0 if the string was invalid.
82The 105The
83.Fn inet_addr 106.Fn inet_addr
84and 107and
@@ -86,17 +109,32 @@ and
86functions return numbers suitable for use 109functions return numbers suitable for use
87as Internet addresses and Internet network 110as Internet addresses and Internet network
88numbers, respectively. 111numbers, respectively.
112.Pp
113The function
114.Fn inet_ntop
115converts an address from network format (usually a
116.Li struct in_addr
117or some other binary form, in network byte order) to presentation format
118(suitable for external display purposes).
119It returns
120.Dv NULL
121if a system
122error occurs (in which case,
123.Va errno
124will have been set), or it returns a pointer to the destination string.
89The routine 125The routine
90.Fn inet_ntoa 126.Fn inet_ntoa
91takes an Internet address and returns an 127takes an Internet address and returns an
92.Tn ASCII 128.Tn ASCII
93string representing the address in 129string representing the address in
94.Ql \&. 130.Ql \&.
95notation. The routine 131notation.
132The routine
96.Fn inet_makeaddr 133.Fn inet_makeaddr
97takes an Internet network number and a local 134takes an Internet network number and a local
98network address and constructs an Internet address 135network address and constructs an Internet address
99from it. The routines 136from it.
137The routines
100.Fn inet_netof 138.Fn inet_netof
101and 139and
102.Fn inet_lnaof 140.Fn inet_lnaof
@@ -108,7 +146,7 @@ All Internet addresses are returned in network
108order (bytes ordered from left to right). 146order (bytes ordered from left to right).
109All network numbers and local address parts are 147All network numbers and local address parts are
110returned as machine format integer values. 148returned as machine format integer values.
111.Sh INTERNET ADDRESSES 149.Sh INTERNET ADDRESSES (IP VERSION 4)
112Values specified using the 150Values specified using the
113.Ql \&. 151.Ql \&.
114notation take one 152notation take one
@@ -122,28 +160,27 @@ a
122.Pp 160.Pp
123When four parts are specified, each is interpreted 161When four parts are specified, each is interpreted
124as a byte of data and assigned, from left to right, 162as a byte of data and assigned, from left to right,
125to the four bytes of an Internet address. Note 163to the four bytes of an Internet address.
126that when an Internet address is viewed as a 32-bit 164Note that when an Internet address is viewed as a 32-bit
127integer quantity on the 165integer quantity on a system that uses little-endian
128.Tn VAX 166byte order (such as the
129the bytes referred to 167.Tn Intel 386, 486
130above appear as 168and
169.Tn Pentium
170processors) the bytes referred to above appear as
131.Dq Li d.c.b.a . 171.Dq Li d.c.b.a .
132That is, 172That is, little-endian bytes are ordered from right to left.
133.Tn VAX
134bytes are
135ordered from right to left.
136.Pp 173.Pp
137When a three part address is specified, the last 174When a three part address is specified, the last
138part is interpreted as a 16-bit quantity and placed 175part is interpreted as a 16-bit quantity and placed
139in the right-most two bytes of the network address. 176in the rightmost two bytes of the network address.
140This makes the three part address format convenient 177This makes the three part address format convenient
141for specifying Class B network addresses as 178for specifying Class B network addresses as
142.Dq Li 128.net.host . 179.Dq Li 128.net.host .
143.Pp 180.Pp
144When a two part address is supplied, the last part 181When a two part address is supplied, the last part
145is interpreted as a 24-bit quantity and placed in 182is interpreted as a 24-bit quantity and placed in
146the right most three bytes of the network address. 183the rightmost three bytes of the network address.
147This makes the two part address format convenient 184This makes the two part address format convenient
148for specifying Class A network addresses as 185for specifying Class A network addresses as
149.Dq Li net.host . 186.Dq Li net.host .
@@ -155,12 +192,89 @@ rearrangement.
155All numbers supplied as 192All numbers supplied as
156.Dq parts 193.Dq parts
157in a 194in a
158.Ql \&. 195.Ql \&.
159notation 196notation
160may be decimal, octal, or hexadecimal, as specified 197may be decimal, octal, or hexadecimal, as specified
161in the C language (i.e., a leading 0x or 0X implies 198in the C language (i.e., a leading 0x or 0X implies
162hexadecimal; otherwise, a leading 0 implies octal; 199hexadecimal; otherwise, a leading 0 implies octal;
163otherwise, the number is interpreted as decimal). 200otherwise, the number is interpreted as decimal).
201.Sh INTERNET ADDRESSES (IP VERSION 6)
202In order to support scoped IPv6 addresses,
203.Xr getaddrinfo 3
204and
205.Xr getnameinfo 3
206are recommended rather than the functions presented here.
207.Pp
208The presentation format of an IPv6 address is given in [RFC1884 2.2]:
209.Pp
210There are three conventional forms for representing IPv6 addresses as
211text strings:
212.Bl -enum
213.It
214The preferred form is x:x:x:x:x:x:x:x, where the 'x's are the
215hexadecimal values of the eight 16-bit pieces of the address.
216Examples:
217.Bd -literal -offset indent
218FEDC:BA98:7654:3210:FEDC:BA98:7654:3210
2191080:0:0:0:8:800:200C:417A
220.Ed
221.Pp
222Note that it is not necessary to write the leading zeros in an
223individual field, but there must be at least one numeral in
224every field (except for the case described in 2.).
225.It
226Due to the method of allocating certain styles of IPv6
227addresses, it will be common for addresses to contain long
228strings of zero bits.
229In order to make writing addresses
230containing zero bits easier, a special syntax is available to
231compress the zeros.
232The use of
233.Dq \&:\&:
234indicates multiple groups
235of 16 bits of zeros.
236The
237.Dq \&:\&:
238can only appear once in an
239address.
240The
241.Dq \&:\&:
242can also be used to compress the leading and/or trailing zeros in an address.
243.Pp
244For example the following addresses:
245.Bd -literal -offset indent
2461080:0:0:0:8:800:200C:417A a unicast address
247FF01:0:0:0:0:0:0:43 a multicast address
2480:0:0:0:0:0:0:1 the loopback address
2490:0:0:0:0:0:0:0 the unspecified addresses
250.Ed
251.Pp
252may be represented as:
253.Bd -literal -offset indent
2541080::8:800:200C:417A a unicast address
255FF01::43 a multicast address
256::1 the loopback address
257:: the unspecified addresses
258.Ed
259.It
260An alternative form that is sometimes more convenient when
261dealing with a mixed environment of IPv4 and IPv6 nodes is
262x:x:x:x:x:x:d.d.d.d, where the 'x's are the hexadecimal values
263of the six high-order 16-bit pieces of the address, and the 'd's
264are the decimal values of the four low-order 8-bit pieces of the
265address (standard IPv4 representation).
266Examples:
267.Bd -literal -offset indent
2680:0:0:0:0:0:13.1.68.3
2690:0:0:0:0:FFFF:129.144.52.38
270.Ed
271.Pp
272or in compressed form:
273.Bd -literal -offset indent
274::13.1.68.3
275::FFFF:129.144.52.38
276.Ed
277.El
164.Sh DIAGNOSTICS 278.Sh DIAGNOSTICS
165The constant 279The constant
166.Dv INADDR_NONE 280.Dv INADDR_NONE
@@ -170,28 +284,66 @@ and
170.Fn inet_network 284.Fn inet_network
171for malformed requests. 285for malformed requests.
172.Sh SEE ALSO 286.Sh SEE ALSO
287.Xr byteorder 3 ,
173.Xr gethostbyname 3 , 288.Xr gethostbyname 3 ,
174.Xr getnetent 3 , 289.Xr getnetent 3 ,
290.Xr inet_net 3 ,
175.Xr hosts 5 , 291.Xr hosts 5 ,
176.Xr networks 5 , 292.Xr networks 5
293.Sh STANDARDS
294The
295.Nm inet_ntop
296and
297.Nm inet_pton
298functions conform to the IETF IPv6 BSD API and address formatting
299specifications.
300Note that
301.Nm inet_pton
302does not accept 1-, 2-, or 3-part dotted addresses; all four parts
303must be specified.
304This is a narrower input set than that accepted by
305.Nm inet_aton .
177.Sh HISTORY 306.Sh HISTORY
178These 307The
179functions appeared in 308.Nm inet_addr ,
309.Nm inet_network ,
310.Nm inet_makeaddr ,
311.Nm inet_lnaof
312and
313.Nm inet_netof
314functions appeared in
180.Bx 4.2 . 315.Bx 4.2 .
316The
317.Nm inet_aton
318and
319.Nm inet_ntoa
320functions appeared in
321.Bx 4.3 .
322The
323.Nm inet_pton
324and
325.Nm inet_ntop
326functions appeared in BIND 4.9.4.
181.Sh BUGS 327.Sh BUGS
182The value 328The value
183.Dv INADDR_NONE 329.Dv INADDR_NONE
184(0xffffffff) is a valid broadcast address, but 330(0xffffffff) is a valid broadcast address, but
185.Fn inet_addr 331.Fn inet_addr
186cannot return that value without indicating failure. 332cannot return that value without indicating failure.
333Also,
334.Fn inet_addr
335should have been designed to return a
336.Li struct in_addr .
187The newer 337The newer
188.Fn inet_aton 338.Fn inet_aton
189function does not share this problem. 339function does not share these problems, and almost all existing code
340should be modified to use
341.Fn inet_aton
342instead.
343.Pp
190The problem of host byte ordering versus network byte ordering is 344The problem of host byte ordering versus network byte ordering is
191confusing. 345confusing.
346.Pp
192The string returned by 347The string returned by
193.Fn inet_ntoa 348.Fn inet_ntoa
194resides in a static memory area. 349resides in a static memory area.
195.Pp
196Inet_addr should return a
197.Fa struct in_addr .
diff --git a/src/lib/libc/net/inet6_option_space.3 b/src/lib/libc/net/inet6_option_space.3
new file mode 100644
index 0000000000..5150b191bd
--- /dev/null
+++ b/src/lib/libc/net/inet6_option_space.3
@@ -0,0 +1,448 @@
1.\" $OpenBSD: inet6_option_space.3,v 1.10 2003/05/01 19:17:37 jmc Exp $
2.\" $KAME: inet6_option_space.3,v 1.7 2000/05/17 14:32:13 itojun Exp $
3.\"
4.\" Copyright (c) 1983, 1987, 1991, 1993
5.\" The Regents of the University of California. All rights reserved.
6.\"
7.\" Redistribution and use in source and binary forms, with or without
8.\" modification, are permitted provided that the following conditions
9.\" are met:
10.\" 1. Redistributions of source code must retain the above copyright
11.\" notice, this list of conditions and the following disclaimer.
12.\" 2. Redistributions in binary form must reproduce the above copyright
13.\" notice, this list of conditions and the following disclaimer in the
14.\" documentation and/or other materials provided with the distribution.
15.\" 3. All advertising materials mentioning features or use of this software
16.\" must display the following acknowledgement:
17.\" This product includes software developed by the University of
18.\" California, Berkeley and its contributors.
19.\" 4. Neither the name of the University nor the names of its contributors
20.\" may be used to endorse or promote products derived from this software
21.\" without specific prior written permission.
22.\"
23.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33.\" SUCH DAMAGE.
34.\"
35.Dd December 10, 1999
36.Dt INET6_OPTION_SPACE 3
37.Os
38.\"
39.Sh NAME
40.Nm inet6_option_space ,
41.Nm inet6_option_init ,
42.Nm inet6_option_append ,
43.Nm inet6_option_alloc ,
44.Nm inet6_option_next ,
45.Nm inet6_option_find
46.Nd IPv6 Hop-by-Hop and Destination Options manipulation
47.\"
48.Sh SYNOPSIS
49.Fd #include <netinet/in.h>
50.Ft "int"
51.Fn inet6_option_space "int nbytes"
52.Ft "int"
53.Fn inet6_option_init "void *bp" "struct cmsghdr **cmsgp" "int type"
54.Ft "int"
55.Fn inet6_option_append "struct cmsghdr *cmsg" "const u_int8_t *typep" "int multx" "int plusy"
56.Ft "u_int8_t *"
57.Fn inet6_option_alloc "struct cmsghdr *cmsg" "int datalen" "int multx" "int plusy";
58.Ft "int"
59.Fn inet6_option_next "const struct cmsghdr *cmsg" "u_int8_t **tptrp"
60.Ft "int"
61.Fn inet6_option_find "const struct cmsghdr *cmsg" "u_int8_t **tptrp" "int type"
62.\"
63.Sh DESCRIPTION
64.\"
65Building and parsing the Hop-by-Hop and Destination options is
66complicated due to alignment constraints, padding and
67ancillary data manipulation.
68RFC2292 defines a set of functions to help the application.
69The function prototypes for
70these functions are all in the
71.Aq Pa netinet/in.h
72header.
73.\"
74.Ss inet6_option_space
75.Fn inet6_option_space
76returns the number of bytes required to hold an option when it is stored as
77ancillary data, including the
78.Li cmsghdr
79structure at the beginning,
80and any padding at the end
81.Po
82to make its size a multiple of 8 bytes
83.Pc .
84The argument is the size of the structure defining the option,
85which must include any pad bytes at the beginning
86.Po
87the value
88.Li y
89in the alignment term
90.Dq Li xn + y
91.Pc ,
92the type byte, the length byte, and the option data.
93.Pp
94Note: If multiple options are stored in a single ancillary data
95object, which is the recommended technique, this function
96overestimates the amount of space required by the size of
97.Li N-1
98.Li cmsghdr
99structures,
100where
101.Li N
102is the number of options to be stored in the object.
103This is of little consequence, since it is assumed that most
104Hop-by-Hop option headers and Destination option headers carry only
105one option
106.Pq appendix B of [RFC-2460] .
107.\"
108.Ss inet6_option_init
109.Fn inet6_option_init
110is called once per ancillary data object that will
111contain either Hop-by-Hop or Destination options.
112It returns
113.Li 0
114on success or
115.Li -1
116on an error.
117.Pp
118.Fa bp
119is a pointer to previously allocated space that will contain the
120ancillary data object.
121It must be large enough to contain all the
122individual options to be added by later calls to
123.Fn inet6_option_append
124and
125.Fn inet6_option_alloc .
126.Pp
127.Fa cmsgp
128is a pointer to a pointer to a
129.Li cmsghdr
130structure.
131.Fa *cmsgp
132is initialized by this function to point to the
133.Li cmsghdr
134structure constructed by this function in the buffer pointed to by
135.Fa bp .
136.Pp
137.Fa type
138is either
139.Dv IPV6_HOPOPTS
140or
141.Dv IPV6_DSTOPTS .
142This
143.Fa type
144is stored in the
145.Li cmsg_type
146member of the
147.Li cmsghdr
148structure pointed to by
149.Fa *cmsgp .
150.\"
151.Ss inet6_option_append
152This function appends a Hop-by-Hop option or a Destination option
153into an ancillary data object that has been initialized by
154.Fn inet6_option_init .
155This function returns
156.Li 0
157if it succeeds or
158.Li -1
159on an error.
160.Pp
161.Fa cmsg
162is a pointer to the
163.Li cmsghdr
164structure that must have been
165initialized by
166.Fn inet6_option_init .
167.Pp
168.Fa typep
169is a pointer to the 8-bit option type.
170It is assumed that this
171field is immediately followed by the 8-bit option data length field,
172which is then followed immediately by the option data.
173The caller
174initializes these three fields
175.Pq the type-length-value, or TLV
176before calling this function.
177.Pp
178The option type must have a value from
179.Li 2
180to
181.Li 255 ,
182inclusive.
183.Po
184.Li 0
185and
186.Li 1
187are reserved for the
188.Li Pad1
189and
190.Li PadN
191options, respectively.
192.Pc
193.Pp
194The option data length must have a value between
195.Li 0
196and
197.Li 255 ,
198inclusive, and is the length of the option data that follows.
199.Pp
200.Fa multx
201is the value
202.Li x
203in the alignment term
204.Dq Li xn + y .
205It must have a value of
206.Li 1 ,
207.Li 2 ,
208.Li 4 ,
209or
210.Li 8 .
211.Pp
212.Fa plusy
213is the value
214.Li y
215in the alignment term
216.Dq Li xn + y .
217It must have a value between
218.Li 0
219and
220.Li 7 ,
221inclusive.
222.\"
223.Ss inet6_option_alloc
224This function appends a Hop-by-Hop option or a Destination option
225into an ancillary data object that has been initialized by
226.Fn inet6_option_init .
227This function returns a pointer to the 8-bit
228option type field that starts the option on success, or
229.Dv NULL
230on an error.
231.Pp
232The difference between this function and
233.Fn inet6_option_append
234is that the latter copies the contents of a previously built option into
235the ancillary data object while the current function returns a
236pointer to the space in the data object where the option's TLV must
237then be built by the caller.
238.Pp
239.Fa cmsg
240is a pointer to the
241.Li cmsghdr
242structure that must have been
243initialized by
244.Fn inet6_option_init .
245.Pp
246.Fa datalen
247is the value of the option data length byte for this option.
248This value is required as an argument to allow the function to
249determine if padding must be appended at the end of the option.
250(The
251.Fn inet6_option_append
252function does not need a data length argument
253since the option data length must already be stored by the caller.)
254.Pp
255.Fa multx
256is the value
257.Li x
258in the alignment term
259.Dq Li xn + y .
260It must have a value of
261.Li 1 ,
262.Li 2 ,
263.Li 4 ,
264or
265.Li 8 .
266.Pp
267.Fa plusy
268is the value
269.Li y
270in the alignment term
271.Dq Li xn + y .
272It must have a value between
273.Li 0
274and
275.Li 7 ,
276inclusive.
277.\"
278.Ss inet6_option_next
279This function processes the next Hop-by-Hop option or Destination
280option in an ancillary data object.
281If another option remains to be
282processed, the return value of the function is
283.Li 0
284and
285.Fa *tptrp
286points to
287the 8-bit option type field
288(which is followed by the 8-bit option
289data length, followed by the option data).
290If no more options remain
291to be processed, the return value is
292.Li -1
293and
294.Fa *tptrp
295is
296.Dv NULL .
297If an error occurs, the return value is
298.Li -1
299and
300.Fa *tptrp
301is not
302.Dv NULL .
303.Pp
304.Fa cmsg
305is a pointer to
306.Li cmsghdr
307structure of which
308.Li cmsg_level
309equals
310.Dv IPPROTO_IPV6
311and
312.Li cmsg_type
313equals either
314.Dv IPV6_HOPOPTS
315or
316.Dv IPV6_DSTOPTS .
317.Pp
318.Fa tptrp
319is a pointer to a pointer to an 8-bit byte and
320.Fa *tptrp
321is used
322by the function to remember its place in the ancillary data object
323each time the function is called.
324The first time this function is
325called for a given ancillary data object,
326.Fa *tptrp
327must be set to
328.Dv NULL .
329.Pp
330Each time this function returns success,
331.Fa *tptrp
332points to the 8-bit
333option type field for the next option to be processed.
334.\"
335.Ss inet6_option_find
336This function is similar to the previously described
337.Fn inet6_option_next
338function, except this function lets the caller
339specify the option type to be searched for, instead of always
340returning the next option in the ancillary data object.
341.Fa cmsg
342is a
343pointer to
344.Li cmsghdr
345structure of which
346.Li cmsg_level
347equals
348.Dv IPPROTO_IPV6
349and
350.Li cmsg_type
351equals either
352.Dv IPV6_HOPOPTS
353or
354.Dv IPV6_DSTOPTS .
355.Pp
356.Fa tptrp
357is a pointer to a pointer to an 8-bit byte and
358.Fa *tptrp
359is used
360by the function to remember its place in the ancillary data object
361each time the function is called.
362The first time this function is
363called for a given ancillary data object,
364.Fa *tptrp
365must be set to
366.Dv NULL .
367.Pp
368This function starts searching for an option of the specified type
369beginning after the value of
370.Fa *tptrp .
371If an option of the specified
372type is located, this function returns
373.Li 0
374and
375.Fa *tptrp
376points to the 8-
377bit option type field for the option of the specified type.
378If an
379option of the specified type is not located, the return value is
380.Li -1
381and
382.Fa *tptrp
383is
384.Dv NULL .
385If an error occurs, the return value is
386.Li -1
387and
388.Fa *tptrp
389is not
390.Dv NULL .
391.\"
392.Sh DIAGNOSTICS
393.Fn inet6_option_init
394and
395.Fn inet6_option_append
396return
397.Li 0
398on success or
399.Li -1
400on an error.
401.Pp
402.Fn inet6_option_alloc
403returns
404.Dv NULL
405on an error.
406.Pp
407On errors,
408.Fn inet6_option_next
409and
410.Fn inet6_option_find
411return
412.Li -1
413setting
414.Fa *tptrp
415to non
416.Dv NULL
417value.
418.\"
419.Sh EXAMPLES
420RFC2292 gives comprehensive examples in chapter 6.
421.\"
422.Sh SEE ALSO
423.Rs
424.%A W. Stevens
425.%A M. Thomas
426.%T "Advanced Sockets API for IPv6"
427.%N RFC2292
428.%D February 1998
429.Re
430.Rs
431.%A S. Deering
432.%A R. Hinden
433.%T "Internet Protocol, Version 6 (IPv6) Specification"
434.%N RFC2460
435.%D December 1998
436.Re
437.\"
438.Sh HISTORY
439The implementation first appeared in KAME advanced networking kit.
440.\"
441.Sh STANDARDS
442The functions
443are documented in
444.Dq Advanced Sockets API for IPv6
445.Pq RFC2292 .
446.\"
447.Sh BUGS
448The text was shamelessly copied from RFC2292.
diff --git a/src/lib/libc/net/inet6_rthdr_space.3 b/src/lib/libc/net/inet6_rthdr_space.3
new file mode 100644
index 0000000000..06a56715b5
--- /dev/null
+++ b/src/lib/libc/net/inet6_rthdr_space.3
@@ -0,0 +1,321 @@
1.\" $OpenBSD: inet6_rthdr_space.3,v 1.10 2003/05/01 19:17:37 jmc Exp $
2.\" $KAME: inet6_rthdr_space.3,v 1.8 2000/05/17 14:30:15 itojun Exp $
3.\"
4.\" Copyright (c) 1983, 1987, 1991, 1993
5.\" The Regents of the University of California. All rights reserved.
6.\"
7.\" Redistribution and use in source and binary forms, with or without
8.\" modification, are permitted provided that the following conditions
9.\" are met:
10.\" 1. Redistributions of source code must retain the above copyright
11.\" notice, this list of conditions and the following disclaimer.
12.\" 2. Redistributions in binary form must reproduce the above copyright
13.\" notice, this list of conditions and the following disclaimer in the
14.\" documentation and/or other materials provided with the distribution.
15.\" 3. All advertising materials mentioning features or use of this software
16.\" must display the following acknowledgement:
17.\" This product includes software developed by the University of
18.\" California, Berkeley and its contributors.
19.\" 4. Neither the name of the University nor the names of its contributors
20.\" may be used to endorse or promote products derived from this software
21.\" without specific prior written permission.
22.\"
23.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33.\" SUCH DAMAGE.
34.\"
35.Dd December 10, 1999
36.Dt INET6_RTHDR_SPACE 3
37.Os
38.\"
39.Sh NAME
40.Nm inet6_rthdr_space ,
41.Nm inet6_rthdr_init ,
42.Nm inet6_rthdr_add ,
43.Nm inet6_rthdr_lasthop ,
44.Nm inet6_rthdr_reverse ,
45.Nm inet6_rthdr_segments ,
46.Nm inet6_rthdr_getaddr ,
47.Nm inet6_rthdr_getflags
48.Nd IPv6 Routing Header Options manipulation
49.\"
50.Sh SYNOPSIS
51.Fd #include <netinet/in.h>
52.Ft size_t
53.Fn inet6_rthdr_space "int type" "int segments"
54.Ft "struct cmsghdr *"
55.Fn inet6_rthdr_init "void *bp" "int type"
56.Ft int
57.Fn inet6_rthdr_add "struct cmsghdr *cmsg" "const struct in6_addr *addr" "unsigned int flags"
58.Ft int
59.Fn inet6_rthdr_lasthop "struct cmsghdr *cmsg" "unsigned int flags"
60.Ft int
61.Fn inet6_rthdr_reverse "const struct cmsghdr *in" "struct cmsghdr *out"
62.Ft int
63.Fn inet6_rthdr_segments "const struct cmsghdr *cmsg"
64.Ft "struct in6_addr *"
65.Fn inet6_rthdr_getaddr "struct cmsghdr *cmsg" "int index"
66.Ft int
67.Fn inet6_rthdr_getflags "const struct cmsghdr *cmsg" "int index"
68.\"
69.Sh DESCRIPTION
70RFC2292 IPv6 advanced API defines eight
71functions that the application calls to build and examine a Routing
72header.
73Four functions build a Routing header:
74.Bl -hang
75.It Fn inet6_rthdr_space
76return #bytes required for ancillary data
77.It Fn inet6_rthdr_init
78initialize ancillary data for Routing header
79.It Fn inet6_rthdr_add
80add IPv6 address & flags to Routing header
81.It Fn inet6_rthdr_lasthop
82specify the flags for the final hop
83.El
84.Pp
85Four functions deal with a returned Routing header:
86.Bl -hang
87.It Fn inet6_rthdr_reverse
88reverse a Routing header
89.It Fn inet6_rthdr_segments
90return #segments in a Routing header
91.It Fn inet6_rthdr_getaddr
92fetch one address from a Routing header
93.It Fn inet6_rthdr_getflags
94fetch one flag from a Routing header
95.El
96.Pp
97The function prototypes for these functions are all in the
98.Aq Pa netinet/in.h
99header.
100.\"
101.Ss inet6_rthdr_space
102This function returns the number of bytes required to hold a Routing
103header of the specified
104.Fa type
105containing the specified number of
106.Fa segments
107.Pq addresses .
108For an IPv6 Type 0 Routing header, the number
109of segments must be between 1 and 23, inclusive.
110The return value
111includes the size of the cmsghdr structure that precedes the Routing
112header, and any required padding.
113.Pp
114If the return value is 0, then either the type of the Routing header
115is not supported by this implementation or the number of segments is
116invalid for this type of Routing header.
117.Pp
118Note: This function returns the size but does not allocate the space
119required for the ancillary data.
120This allows an application to
121allocate a larger buffer, if other ancillary data objects are
122desired, since all the ancillary data objects must be specified to
123.Xr sendmsg 2
124as a single
125.Li msg_control
126buffer.
127.\"
128.Ss inet6_rthdr_init
129This function initializes the buffer pointed to by
130.Fa bp
131to contain a
132.Li cmsghdr
133structure followed by a Routing header of the specified
134.Fa type .
135The
136.Li cmsg_len
137member of the
138.Li cmsghdr
139structure is initialized to the
140size of the structure plus the amount of space required by the
141Routing header.
142The
143.Li cmsg_level
144and
145.Li cmsg_type
146members are also initialized as required.
147.Pp
148The caller must allocate the buffer and its size can be determined by
149calling
150.Fn inet6_rthdr_space .
151.Pp
152Upon success the return value is the pointer to the
153.Li cmsghdr
154structure, and this is then used as the first argument to the next
155two functions.
156Upon an error the return value is
157.Dv NULL .
158.\"
159.Ss inet6_rthdr_add
160This function adds the address pointed to by
161.Fa addr
162to the end of the
163Routing header being constructed and sets the type of this hop to the
164value of
165.Fa flags .
166For an IPv6 Type 0 Routing header,
167.Fa flags
168must be
169either
170.Dv IPV6_RTHDR_LOOSE
171or
172.Dv IPV6_RTHDR_STRICT .
173.Pp
174If successful, the
175.Li cmsg_len
176member of the
177.Li cmsghdr
178structure is
179updated to account for the new address in the Routing header and the
180return value of the function is 0.
181Upon an error the return value of
182the function is -1.
183.\"
184.Ss inet6_rthdr_lasthop
185This function specifies the Strict/Loose flag for the final hop of a
186Routing header.
187For an IPv6 Type 0 Routing header,
188.Fa flags
189must be either
190.Dv IPV6_RTHDR_LOOSE
191or
192.Dv IPV6_RTHDR_STRICT .
193.Pp
194The return value of the function is 0 upon success, or -1 upon an error.
195.Pp
196Notice that a Routing header specifying
197.Li N
198intermediate nodes requires
199.Li N+1
200Strict/Loose flags.
201This requires
202.Li N
203calls to
204.Fn inet6_rthdr_add
205followed by one call to
206.Fn inet6_rthdr_lasthop .
207.\"
208.Ss inet6_rthdr_reverse
209This function takes a Routing header that was received as ancillary
210data
211.Po
212pointed to by the first argument,
213.Fa in
214.Pc
215and writes a new Routing
216header that sends datagrams along the reverse of that route.
217Both
218arguments are allowed to point to the same buffer
219.Pq that is, the reversal can occur in place .
220.Pp
221The return value of the function is 0 on success, or -1 upon an
222error.
223.\"
224.Ss inet6_rthdr_segments
225This function returns the number of segments
226.Pq addresses
227contained in
228the Routing header described by
229.Fa cmsg .
230On success the return value is
231between 1 and 23, inclusive.
232The return value of the function is -1 upon an error.
233.\"
234.Ss inet6_rthdr_getaddr
235This function returns a pointer to the IPv6 address specified by
236.Fa index
237(which must have a value between 1 and the value returned by
238.Fn inet6_rthdr_segments )
239in the Routing header described by
240.Fa cmsg .
241An
242application should first call
243.Fn inet6_rthdr_segments
244to obtain the number of segments in the Routing header.
245.Pp
246Upon an error the return value of the function is
247.Dv NULL .
248.\"
249.Ss inet6_rthdr_getflags
250This function returns the flags value specified by
251.Fa index
252(which must
253have a value between 0 and the value returned by
254.Fn inet6_rthdr_segments )
255in the Routing header described by
256.Fa cmsg .
257For an IPv6 Type 0 Routing header the return value will be either
258.Dv IPV6_RTHDR_LOOSE
259or
260.Dv IPV6_RTHDR_STRICT .
261.Pp
262Upon an error the return value of the function is -1.
263.Pp
264Note: Addresses are indexed starting at 1, and flags starting at 0,
265to maintain consistency with the terminology and figures in RFC2460.
266.\"
267.Sh DIAGNOSTICS
268.Fn inet6_rthdr_space
269returns 0 on errors.
270.Pp
271.Fn inet6_rthdr_add ,
272.Fn inet6_rthdr_lasthop
273and
274.Fn inet6_rthdr_reverse
275return 0 on success, and returns -1 on error.
276.Pp
277.Fn inet6_rthdr_init
278and
279.Fn inet6_rthdr_getaddr
280return
281.Dv NULL
282on error.
283.Pp
284.Fn inet6_rthdr_segments
285and
286.Fn inet6_rthdr_getflags
287return -1 on error.
288.\"
289.Sh EXAMPLES
290RFC2292 gives comprehensive examples in chapter 8.
291.\"
292.Sh SEE ALSO
293.Rs
294.%A W. Stevens
295.%A M. Thomas
296.%T "Advanced Sockets API for IPv6"
297.%N RFC2292
298.%D February 1998
299.Re
300.Rs
301.%A S. Deering
302.%A R. Hinden
303.%T "Internet Protocol, Version 6 (IPv6) Specification"
304.%N RFC2460
305.%D December 1998
306.Re
307.\"
308.Sh HISTORY
309The implementation first appeared in KAME advanced networking kit.
310.\"
311.Sh STANDARDS
312The functions
313are documented in
314.Dq Advanced Sockets API for IPv6
315.Pq RFC2292 .
316.\"
317.Sh BUGS
318The text was shamelessly copied from RFC2292.
319.Pp
320.Fn inet6_rthdr_reverse
321is not implemented yet.
diff --git a/src/lib/libc/net/inet_addr.c b/src/lib/libc/net/inet_addr.c
index b5b9d8302f..6203ccdaac 100644
--- a/src/lib/libc/net/inet_addr.c
+++ b/src/lib/libc/net/inet_addr.c
@@ -1,9 +1,11 @@
1/* $NetBSD: inet_addr.c,v 1.5 1995/02/25 06:20:41 cgd Exp $ */ 1/* $OpenBSD: inet_addr.c,v 1.6 1999/05/03 22:31:14 yanick Exp $ */
2 2
3/* 3/*
4 * ++Copyright++ 1983, 1990, 1993
5 * -
4 * Copyright (c) 1983, 1990, 1993 6 * Copyright (c) 1983, 1990, 1993
5 * The Regents of the University of California. All rights reserved. 7 * The Regents of the University of California. All rights reserved.
6 * 8 *
7 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
9 * are met: 11 * are met:
@@ -14,12 +16,12 @@
14 * documentation and/or other materials provided with the distribution. 16 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software 17 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement: 18 * must display the following acknowledgement:
17 * This product includes software developed by the University of 19 * This product includes software developed by the University of
18 * California, Berkeley and its contributors. 20 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors 21 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software 22 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission. 23 * without specific prior written permission.
22 * 24 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -31,16 +33,38 @@
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE. 35 * SUCH DAMAGE.
36 * -
37 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
38 *
39 * Permission to use, copy, modify, and distribute this software for any
40 * purpose with or without fee is hereby granted, provided that the above
41 * copyright notice and this permission notice appear in all copies, and that
42 * the name of Digital Equipment Corporation not be used in advertising or
43 * publicity pertaining to distribution of the document or software without
44 * specific, written prior permission.
45 *
46 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
47 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
48 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
49 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
50 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
51 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
52 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
53 * SOFTWARE.
54 * -
55 * --Copyright--
34 */ 56 */
35 57
36#if defined(LIBC_SCCS) && !defined(lint) 58#if defined(LIBC_SCCS) && !defined(lint)
37#if 0 59#if 0
38static char sccsid[] = "@(#)inet_addr.c 8.1 (Berkeley) 6/17/93"; 60static char sccsid[] = "@(#)inet_addr.c 8.1 (Berkeley) 6/17/93";
61static char rcsid[] = "$From: inet_addr.c,v 8.5 1996/08/05 08:31:35 vixie Exp $";
39#else 62#else
40static char rcsid[] = "$NetBSD: inet_addr.c,v 1.5 1995/02/25 06:20:41 cgd Exp $"; 63static char rcsid[] = "$OpenBSD: inet_addr.c,v 1.6 1999/05/03 22:31:14 yanick Exp $";
41#endif 64#endif
42#endif /* LIBC_SCCS and not lint */ 65#endif /* LIBC_SCCS and not lint */
43 66
67#include <sys/types.h>
44#include <sys/param.h> 68#include <sys/param.h>
45#include <netinet/in.h> 69#include <netinet/in.h>
46#include <arpa/inet.h> 70#include <arpa/inet.h>
@@ -50,7 +74,7 @@ static char rcsid[] = "$NetBSD: inet_addr.c,v 1.5 1995/02/25 06:20:41 cgd Exp $"
50 * Ascii internet address interpretation routine. 74 * Ascii internet address interpretation routine.
51 * The value returned is in network order. 75 * The value returned is in network order.
52 */ 76 */
53u_long 77in_addr_t
54inet_addr(cp) 78inet_addr(cp)
55 register const char *cp; 79 register const char *cp;
56{ 80{
@@ -73,56 +97,58 @@ inet_aton(cp, addr)
73 register const char *cp; 97 register const char *cp;
74 struct in_addr *addr; 98 struct in_addr *addr;
75{ 99{
76 register u_long val; 100 register in_addr_t val;
77 register int base, n; 101 register int base, n;
78 register char c; 102 register char c;
79 u_int parts[4]; 103 u_int parts[4];
80 register u_int *pp = parts; 104 register u_int *pp = parts;
81 105
106 c = *cp;
82 for (;;) { 107 for (;;) {
83 /* 108 /*
84 * Collect number up to ``.''. 109 * Collect number up to ``.''.
85 * Values are specified as for C: 110 * Values are specified as for C:
86 * 0x=hex, 0=octal, other=decimal. 111 * 0x=hex, 0=octal, isdigit=decimal.
87 */ 112 */
113 if (!isdigit(c))
114 return (0);
88 val = 0; base = 10; 115 val = 0; base = 10;
89 if (*cp == '0') { 116 if (c == '0') {
90 if (*++cp == 'x' || *cp == 'X') 117 c = *++cp;
91 base = 16, cp++; 118 if (c == 'x' || c == 'X')
119 base = 16, c = *++cp;
92 else 120 else
93 base = 8; 121 base = 8;
94 } 122 }
95 while ((c = *cp) != '\0') { 123 for (;;) {
96 if (isascii(c) && isdigit(c)) { 124 if (isascii(c) && isdigit(c)) {
97 val = (val * base) + (c - '0'); 125 val = (val * base) + (c - '0');
98 cp++; 126 c = *++cp;
99 continue; 127 } else if (base == 16 && isascii(c) && isxdigit(c)) {
100 } 128 val = (val << 4) |
101 if (base == 16 && isascii(c) && isxdigit(c)) {
102 val = (val << 4) +
103 (c + 10 - (islower(c) ? 'a' : 'A')); 129 (c + 10 - (islower(c) ? 'a' : 'A'));
104 cp++; 130 c = *++cp;
105 continue; 131 } else
106 } 132 break;
107 break;
108 } 133 }
109 if (*cp == '.') { 134 if (c == '.') {
110 /* 135 /*
111 * Internet format: 136 * Internet format:
112 * a.b.c.d 137 * a.b.c.d
113 * a.b.c (with c treated as 16-bits) 138 * a.b.c (with c treated as 16 bits)
114 * a.b (with b treated as 24 bits) 139 * a.b (with b treated as 24 bits)
115 */ 140 */
116 if (pp >= parts + 3 || val > 0xff) 141 if (pp >= parts + 3)
117 return (0); 142 return (0);
118 *pp++ = val, cp++; 143 *pp++ = val;
144 c = *++cp;
119 } else 145 } else
120 break; 146 break;
121 } 147 }
122 /* 148 /*
123 * Check for trailing characters. 149 * Check for trailing characters.
124 */ 150 */
125 if (*cp && (!isascii(*cp) || !isspace(*cp))) 151 if (c != '\0' && (!isascii(c) || !isspace(c)))
126 return (0); 152 return (0);
127 /* 153 /*
128 * Concoct the address according to 154 * Concoct the address according to
@@ -131,23 +157,26 @@ inet_aton(cp, addr)
131 n = pp - parts + 1; 157 n = pp - parts + 1;
132 switch (n) { 158 switch (n) {
133 159
160 case 0:
161 return (0); /* initial nondigit */
162
134 case 1: /* a -- 32 bits */ 163 case 1: /* a -- 32 bits */
135 break; 164 break;
136 165
137 case 2: /* a.b -- 8.24 bits */ 166 case 2: /* a.b -- 8.24 bits */
138 if (val > 0xffffff) 167 if ((val > 0xffffff) || (parts[0] > 0xff))
139 return (0); 168 return (0);
140 val |= parts[0] << 24; 169 val |= parts[0] << 24;
141 break; 170 break;
142 171
143 case 3: /* a.b.c -- 8.8.16 bits */ 172 case 3: /* a.b.c -- 8.8.16 bits */
144 if (val > 0xffff) 173 if ((val > 0xffff) || (parts[0] > 0xff) || (parts[1] > 0xff))
145 return (0); 174 return (0);
146 val |= (parts[0] << 24) | (parts[1] << 16); 175 val |= (parts[0] << 24) | (parts[1] << 16);
147 break; 176 break;
148 177
149 case 4: /* a.b.c.d -- 8.8.8.8 bits */ 178 case 4: /* a.b.c.d -- 8.8.8.8 bits */
150 if (val > 0xff) 179 if ((val > 0xff) || (parts[0] > 0xff) || (parts[1] > 0xff) || (parts[2] > 0xff))
151 return (0); 180 return (0);
152 val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); 181 val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
153 break; 182 break;
diff --git a/src/lib/libc/net/inet_lnaof.c b/src/lib/libc/net/inet_lnaof.c
index ce1257bf68..6aed18699b 100644
--- a/src/lib/libc/net/inet_lnaof.c
+++ b/src/lib/libc/net/inet_lnaof.c
@@ -1,5 +1,3 @@
1/* $NetBSD: inet_lnaof.c,v 1.4 1995/02/25 06:20:42 cgd Exp $ */
2
3/* 1/*
4 * Copyright (c) 1983, 1993 2 * Copyright (c) 1983, 1993
5 * The Regents of the University of California. All rights reserved. 3 * The Regents of the University of California. All rights reserved.
@@ -34,11 +32,7 @@
34 */ 32 */
35 33
36#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
37#if 0 35static char rcsid[] = "$OpenBSD: inet_lnaof.c,v 1.3 1997/04/05 21:13:11 millert Exp $";
38static char sccsid[] = "@(#)inet_lnaof.c 8.1 (Berkeley) 6/4/93";
39#else
40static char rcsid[] = "$NetBSD: inet_lnaof.c,v 1.4 1995/02/25 06:20:42 cgd Exp $";
41#endif
42#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
43 37
44#include <sys/param.h> 38#include <sys/param.h>
@@ -50,11 +44,11 @@ static char rcsid[] = "$NetBSD: inet_lnaof.c,v 1.4 1995/02/25 06:20:42 cgd Exp $
50 * internet address; handles class a/b/c network 44 * internet address; handles class a/b/c network
51 * number formats. 45 * number formats.
52 */ 46 */
53u_long 47in_addr_t
54inet_lnaof(in) 48inet_lnaof(in)
55 struct in_addr in; 49 struct in_addr in;
56{ 50{
57 register u_long i = ntohl(in.s_addr); 51 register in_addr_t i = ntohl(in.s_addr);
58 52
59 if (IN_CLASSA(i)) 53 if (IN_CLASSA(i))
60 return ((i)&IN_CLASSA_HOST); 54 return ((i)&IN_CLASSA_HOST);
diff --git a/src/lib/libc/net/inet_makeaddr.c b/src/lib/libc/net/inet_makeaddr.c
index 84d366e03a..196a589e4c 100644
--- a/src/lib/libc/net/inet_makeaddr.c
+++ b/src/lib/libc/net/inet_makeaddr.c
@@ -1,5 +1,3 @@
1/* $NetBSD: inet_makeaddr.c,v 1.4 1995/02/25 06:20:42 cgd Exp $ */
2
3/* 1/*
4 * Copyright (c) 1983, 1993 2 * Copyright (c) 1983, 1993
5 * The Regents of the University of California. All rights reserved. 3 * The Regents of the University of California. All rights reserved.
@@ -34,11 +32,7 @@
34 */ 32 */
35 33
36#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
37#if 0 35static char rcsid[] = "$OpenBSD: inet_makeaddr.c,v 1.3 1997/04/05 21:13:12 millert Exp $";
38static char sccsid[] = "@(#)inet_makeaddr.c 8.1 (Berkeley) 6/4/93";
39#else
40static char rcsid[] = "$NetBSD: inet_makeaddr.c,v 1.4 1995/02/25 06:20:42 cgd Exp $";
41#endif
42#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
43 37
44#include <sys/param.h> 38#include <sys/param.h>
@@ -51,9 +45,9 @@ static char rcsid[] = "$NetBSD: inet_makeaddr.c,v 1.4 1995/02/25 06:20:42 cgd Ex
51 */ 45 */
52struct in_addr 46struct in_addr
53inet_makeaddr(net, host) 47inet_makeaddr(net, host)
54 u_long net, host; 48 in_addr_t net, host;
55{ 49{
56 u_long addr; 50 in_addr_t addr;
57 51
58 if (net < 128) 52 if (net < 128)
59 addr = (net << IN_CLASSA_NSHIFT) | (host & IN_CLASSA_HOST); 53 addr = (net << IN_CLASSA_NSHIFT) | (host & IN_CLASSA_HOST);
diff --git a/src/lib/libc/net/inet_net.3 b/src/lib/libc/net/inet_net.3
new file mode 100644
index 0000000000..c14fa52e38
--- /dev/null
+++ b/src/lib/libc/net/inet_net.3
@@ -0,0 +1,181 @@
1.\" $OpenBSD: inet_net.3,v 1.10 2003/05/01 19:17:37 jmc Exp $
2.\" $NetBSD: inet_net.3,v 1.1 1997/06/18 02:25:27 lukem Exp $
3.\"
4.\" Copyright (c) 1997 The NetBSD Foundation, Inc.
5.\" All rights reserved.
6.\"
7.\" This code is derived from software contributed to The NetBSD Foundation
8.\" by Luke Mewburn.
9.\"
10.\" Redistribution and use in source and binary forms, with or without
11.\" modification, are permitted provided that the following conditions
12.\" are met:
13.\" 1. Redistributions of source code must retain the above copyright
14.\" notice, this list of conditions and the following disclaimer.
15.\" 2. Redistributions in binary form must reproduce the above copyright
16.\" notice, this list of conditions and the following disclaimer in the
17.\" documentation and/or other materials provided with the distribution.
18.\" 3. All advertising materials mentioning features or use of this software
19.\" must display the following acknowledgement:
20.\" This product includes software developed by the NetBSD
21.\" Foundation, Inc. and its contributors.
22.\" 4. Neither the name of The NetBSD Foundation nor the names of its
23.\" contributors may be used to endorse or promote products derived
24.\" from this software without specific prior written permission.
25.\"
26.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
30.\" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36.\" POSSIBILITY OF SUCH DAMAGE.
37.\"
38.Dd June 18, 1997
39.Dt INET_NET 3
40.Os
41.Sh NAME
42.Nm inet_net_ntop ,
43.Nm inet_net_pton
44.Nd Internet network number manipulation routines
45.Sh SYNOPSIS
46.Fd #include <sys/socket.h>
47.Fd #include <netinet/in.h>
48.Fd #include <arpa/inet.h>
49.Ft char *
50.Fn inet_net_ntop "int af" "const void *src" "int bits" "char *dst" "size_t size"
51.Ft int
52.Fn inet_net_pton "int af" "const char *src" "void *dst" "size_t size"
53.Sh DESCRIPTION
54The
55.Fn inet_net_ntop
56function converts an Internet network number from network format (usually a
57.Li struct in_addr
58or some other binary form, in network byte order) to CIDR presentation format
59(suitable for external display purposes).
60.Fa bits
61is the number of bits in
62.Fa src
63that are the network number.
64It returns
65.Dv NULL
66if a system error occurs (in which case,
67.Va errno
68will have been set), or it returns a pointer to the destination string.
69.Pp
70The
71.Fn inet_net_pton
72function converts a presentation format Internet network number (that is,
73printable form as held in a character string) to network format (usually a
74.Li struct in_addr
75or some other internal binary representation, in network byte order).
76It returns the number of bits (either computed based on the class, or
77specified with /CIDR), or \-1 if a failure occurred
78(in which case
79.Va errno
80will have been set.
81It will be set to
82.Er ENOENT
83if the Internet network number was not valid).
84.Pp
85Caution:
86The
87.Fa dst
88field should be zeroed before calling
89.Fn inet_net_pton
90as the function will only fill the number of bytes necessary to
91encode the network number in network byte order.
92.Pp
93The only value for
94.Fa af
95currently supported is
96.Dv AF_INET .
97.Fa size
98is the size of the result buffer
99.Fa dst .
100.Sh NETWORK NUMBERS (IP VERSION 4)
101The external representation of Internet network numbers may be specified in
102one of the following forms:
103.Bd -literal -offset indent
104a
105a.b
106a.b.c
107a.b.c.d
108.Ed
109.Pp
110Any of the above four forms may have
111.Dq Li /bits
112appended where
113.Dq Li bits
114is in the range
115.Li 0-32
116and is used to explicitly specify the number of bits in the network address.
117When
118.Dq Li /bits
119is not specified the number of bits in the network address is calculated
120as the larger of the number of bits in the class to which the address
121belongs and the number of bits provided rounded up modulo 8.
122Examples:
123.Bl -tag -width 10.1.2.3/24
124.It Li 10
125an 8 bit network number (class A), value
126.Li 10.0.0.0 .
127.It Li 192
128a 24 bit network number (class C), value
129.Li 192.0.0.0 .
130.It Li 10.10
131a 16 bit network number, value
132.Li 10.10.0.0 .
133.It Li 10.1.2
134a 24 bit network number, value
135.Li 10.1.2.0 .
136.It Li 10.1.2.3
137a 32 bit network number, value
138.Li 10.1.2.3 .
139.It Li 10.1.2.3/24
140a 24 bit network number (explicit), value
141.Li 10.1.2.3 .
142.El
143.Pp
144Note that when the number of bits is specified using
145.Dq Li /bits
146notation, the value of the address still includes all bits suplied
147in the external representation, even those bits which are the host
148part of an internet address.
149Also, unlike
150.Xr inet_pton 3
151where the external representation is assumed to be an internet address, the
152external representation for
153.Fn inet_net_pton
154is assumed to be a network address.
155Thus
156.Dq Li 10.1
157is assumed to be
158.Dq Li 10.1.0.0
159not
160.Dq Li 10.0.0.1
161.Pp
162All numbers supplied as
163.Dq parts
164in a
165.Ql \&.
166notation
167may be decimal, octal, or hexadecimal, as specified
168in the C language (i.e., a leading 0x or 0X implies
169hexadecimal; otherwise, a leading 0 implies octal;
170otherwise, the number is interpreted as decimal).
171.Sh SEE ALSO
172.Xr byteorder 3 ,
173.Xr inet 3 ,
174.Xr inet_pton 3 ,
175.Xr networks 5
176.Sh HISTORY
177The
178.Nm inet_net_ntop
179and
180.Nm inet_net_pton
181functions first appeared in BIND 4.9.4.
diff --git a/src/lib/libc/net/inet_net_ntop.c b/src/lib/libc/net/inet_net_ntop.c
new file mode 100644
index 0000000000..18eea6bb6d
--- /dev/null
+++ b/src/lib/libc/net/inet_net_ntop.c
@@ -0,0 +1,153 @@
1/* $OpenBSD: inet_net_ntop.c,v 1.3 2002/08/19 03:01:54 itojun Exp $ */
2
3/*
4 * Copyright (c) 1996 by Internet Software Consortium.
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
11 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
12 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
13 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
16 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
17 * SOFTWARE.
18 */
19
20#if defined(LIBC_SCCS) && !defined(lint)
21#if 0
22static const char rcsid[] = "$From: inet_net_ntop.c,v 8.2 1996/08/08 06:54:44 vixie Exp $";
23#else
24static const char rcsid[] = "$OpenBSD: inet_net_ntop.c,v 1.3 2002/08/19 03:01:54 itojun Exp $";
25#endif
26#endif
27
28#include <sys/types.h>
29#include <sys/socket.h>
30#include <netinet/in.h>
31#include <arpa/inet.h>
32
33#include <errno.h>
34#include <stdio.h>
35#include <string.h>
36#include <stdlib.h>
37
38static char *inet_net_ntop_ipv4(const u_char *, int, char *, size_t);
39
40/*
41 * char *
42 * inet_net_ntop(af, src, bits, dst, size)
43 * convert network number from network to presentation format.
44 * generates CIDR style result always.
45 * return:
46 * pointer to dst, or NULL if an error occurred (check errno).
47 * author:
48 * Paul Vixie (ISC), July 1996
49 */
50char *
51inet_net_ntop(af, src, bits, dst, size)
52 int af;
53 const void *src;
54 int bits;
55 char *dst;
56 size_t size;
57{
58 switch (af) {
59 case AF_INET:
60 return (inet_net_ntop_ipv4(src, bits, dst, size));
61 default:
62 errno = EAFNOSUPPORT;
63 return (NULL);
64 }
65}
66
67/*
68 * static char *
69 * inet_net_ntop_ipv4(src, bits, dst, size)
70 * convert IPv4 network number from network to presentation format.
71 * generates CIDR style result always.
72 * return:
73 * pointer to dst, or NULL if an error occurred (check errno).
74 * note:
75 * network byte order assumed. this means 192.5.5.240/28 has
76 * 0x11110000 in its fourth octet.
77 * author:
78 * Paul Vixie (ISC), July 1996
79 */
80static char *
81inet_net_ntop_ipv4(src, bits, dst, size)
82 const u_char *src;
83 int bits;
84 char *dst;
85 size_t size;
86{
87 char *odst = dst;
88 char *t;
89 u_int m;
90 int b;
91 char *ep;
92 int advance;
93
94 ep = dst + size;
95 if (ep <= dst)
96 goto emsgsize;
97
98 if (bits < 0 || bits > 32) {
99 errno = EINVAL;
100 return (NULL);
101 }
102 if (bits == 0) {
103 if (ep - dst < sizeof "0")
104 goto emsgsize;
105 *dst++ = '0';
106 *dst = '\0';
107 }
108
109 /* Format whole octets. */
110 for (b = bits / 8; b > 0; b--) {
111 if (ep - dst < sizeof "255.")
112 goto emsgsize;
113 advance = snprintf(dst, ep - dst, "%u", *src++);
114 if (advance <= 0 || advance >= ep - dst)
115 goto emsgsize;
116 dst += advance;
117 if (b > 1) {
118 if (dst + 1 >= ep)
119 goto emsgsize;
120 *dst++ = '.';
121 *dst = '\0';
122 }
123 }
124
125 /* Format partial octet. */
126 b = bits % 8;
127 if (b > 0) {
128 if (ep - dst < sizeof ".255")
129 goto emsgsize;
130 if (dst != odst)
131 if (dst + 1 >= ep)
132 goto emsgsize;
133 *dst++ = '.';
134 m = ((1 << b) - 1) << (8 - b);
135 advance = snprintf(dst, ep - dst, "%u", *src & m);
136 if (advance <= 0 || advance >= ep - dst)
137 goto emsgsize;
138 dst += advance;
139 }
140
141 /* Format CIDR /width. */
142 if (ep - dst < sizeof "/32")
143 goto emsgsize;
144 advance = snprintf(dst, ep - dst, "/%u", bits);
145 if (advance <= 0 || advance >= ep - dst)
146 goto emsgsize;
147 dst += advance;
148 return (odst);
149
150 emsgsize:
151 errno = EMSGSIZE;
152 return (NULL);
153}
diff --git a/src/lib/libc/net/inet_net_pton.c b/src/lib/libc/net/inet_net_pton.c
new file mode 100644
index 0000000000..3c72efac6b
--- /dev/null
+++ b/src/lib/libc/net/inet_net_pton.c
@@ -0,0 +1,206 @@
1/* $OpenBSD: inet_net_pton.c,v 1.3 2003/04/25 19:40:25 henning Exp $ */
2
3/*
4 * Copyright (c) 1996 by Internet Software Consortium.
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
11 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
12 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
13 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
16 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
17 * SOFTWARE.
18 */
19
20#if defined(LIBC_SCCS) && !defined(lint)
21#if 0
22static const char rcsid[] = "$From: inet_net_pton.c,v 8.3 1996/11/11 06:36:52 vixie Exp $";
23#else
24static const char rcsid[] = "$OpenBSD: inet_net_pton.c,v 1.3 2003/04/25 19:40:25 henning Exp $";
25#endif
26#endif
27
28#include <sys/types.h>
29#include <sys/socket.h>
30#include <netinet/in.h>
31#include <arpa/inet.h>
32
33#include <assert.h>
34#include <ctype.h>
35#include <errno.h>
36#include <stdio.h>
37#include <string.h>
38#include <stdlib.h>
39
40static int inet_net_pton_ipv4(const char *, u_char *, size_t);
41
42/*
43 * static int
44 * inet_net_pton(af, src, dst, size)
45 * convert network number from presentation to network format.
46 * accepts hex octets, hex strings, decimal octets, and /CIDR.
47 * "size" is in bytes and describes "dst".
48 * return:
49 * number of bits, either imputed classfully or specified with /CIDR,
50 * or -1 if some failure occurred (check errno). ENOENT means it was
51 * not a valid network specification.
52 * author:
53 * Paul Vixie (ISC), June 1996
54 */
55int
56inet_net_pton(af, src, dst, size)
57 int af;
58 const char *src;
59 void *dst;
60 size_t size;
61{
62 switch (af) {
63 case AF_INET:
64 return (inet_net_pton_ipv4(src, dst, size));
65 default:
66 errno = EAFNOSUPPORT;
67 return (-1);
68 }
69}
70
71/*
72 * static int
73 * inet_net_pton_ipv4(src, dst, size)
74 * convert IPv4 network number from presentation to network format.
75 * accepts hex octets, hex strings, decimal octets, and /CIDR.
76 * "size" is in bytes and describes "dst".
77 * return:
78 * number of bits, either imputed classfully or specified with /CIDR,
79 * or -1 if some failure occurred (check errno). ENOENT means it was
80 * not an IPv4 network specification.
81 * note:
82 * network byte order assumed. this means 192.5.5.240/28 has
83 * 0x11110000 in its fourth octet.
84 * author:
85 * Paul Vixie (ISC), June 1996
86 */
87static int
88inet_net_pton_ipv4(src, dst, size)
89 const char *src;
90 u_char *dst;
91 size_t size;
92{
93 static const char
94 xdigits[] = "0123456789abcdef",
95 digits[] = "0123456789";
96 int n, ch, tmp, dirty, bits;
97 const u_char *odst = dst;
98
99 ch = *src++;
100 if (ch == '0' && (src[0] == 'x' || src[0] == 'X')
101 && isascii(src[1]) && isxdigit(src[1])) {
102 /* Hexadecimal: Eat nybble string. */
103 if (size <= 0)
104 goto emsgsize;
105 *dst = 0, dirty = 0;
106 src++; /* skip x or X. */
107 while ((ch = *src++) != '\0' &&
108 isascii(ch) && isxdigit(ch)) {
109 if (isupper(ch))
110 ch = tolower(ch);
111 n = strchr(xdigits, ch) - xdigits;
112 assert(n >= 0 && n <= 15);
113 *dst |= n;
114 if (!dirty++)
115 *dst <<= 4;
116 else if (size-- > 0)
117 *++dst = 0, dirty = 0;
118 else
119 goto emsgsize;
120 }
121 if (dirty)
122 size--;
123 } else if (isascii(ch) && isdigit(ch)) {
124 /* Decimal: eat dotted digit string. */
125 for (;;) {
126 tmp = 0;
127 do {
128 n = strchr(digits, ch) - digits;
129 assert(n >= 0 && n <= 9);
130 tmp *= 10;
131 tmp += n;
132 if (tmp > 255)
133 goto enoent;
134 } while ((ch = *src++) != '\0' &&
135 isascii(ch) && isdigit(ch));
136 if (size-- <= 0)
137 goto emsgsize;
138 *dst++ = (u_char) tmp;
139 if (ch == '\0' || ch == '/')
140 break;
141 if (ch != '.')
142 goto enoent;
143 ch = *src++;
144 if (!isascii(ch) || !isdigit(ch))
145 goto enoent;
146 }
147 } else
148 goto enoent;
149
150 bits = -1;
151 if (ch == '/' && isascii(src[0]) && isdigit(src[0]) && dst > odst) {
152 /* CIDR width specifier. Nothing can follow it. */
153 ch = *src++; /* Skip over the /. */
154 bits = 0;
155 do {
156 n = strchr(digits, ch) - digits;
157 assert(n >= 0 && n <= 9);
158 bits *= 10;
159 bits += n;
160 } while ((ch = *src++) != '\0' &&
161 isascii(ch) && isdigit(ch));
162 if (ch != '\0')
163 goto enoent;
164 if (bits > 32)
165 goto emsgsize;
166 }
167
168 /* Firey death and destruction unless we prefetched EOS. */
169 if (ch != '\0')
170 goto enoent;
171
172 /* If nothing was written to the destination, we found no address. */
173 if (dst == odst)
174 goto enoent;
175 /* If no CIDR spec was given, infer width from net class. */
176 if (bits == -1) {
177 if (*odst >= 240) /* Class E */
178 bits = 32;
179 else if (*odst >= 224) /* Class D */
180 bits = 4;
181 else if (*odst >= 192) /* Class C */
182 bits = 24;
183 else if (*odst >= 128) /* Class B */
184 bits = 16;
185 else /* Class A */
186 bits = 8;
187 /* If imputed mask is narrower than specified octets, widen. */
188 if (bits < ((dst - odst) * 8))
189 bits = (dst - odst) * 8;
190 }
191 /* Extend network to cover the actual mask. */
192 while (bits > ((dst - odst) * 8)) {
193 if (size-- <= 0)
194 goto emsgsize;
195 *dst++ = '\0';
196 }
197 return (bits);
198
199 enoent:
200 errno = ENOENT;
201 return (-1);
202
203 emsgsize:
204 errno = EMSGSIZE;
205 return (-1);
206}
diff --git a/src/lib/libc/net/inet_neta.c b/src/lib/libc/net/inet_neta.c
new file mode 100644
index 0000000000..6960bcd0b5
--- /dev/null
+++ b/src/lib/libc/net/inet_neta.c
@@ -0,0 +1,91 @@
1/* $OpenBSD: inet_neta.c,v 1.4 2002/08/19 03:01:54 itojun Exp $ */
2
3/*
4 * Copyright (c) 1996 by Internet Software Consortium.
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
11 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
12 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
13 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
16 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
17 * SOFTWARE.
18 */
19
20#if defined(LIBC_SCCS) && !defined(lint)
21#if 0
22static const char rcsid[] = "$Id: inet_neta.c,v 1.4 2002/08/19 03:01:54 itojun Exp $";
23#else
24static const char rcsid[] = "$OpenBSD: inet_neta.c,v 1.4 2002/08/19 03:01:54 itojun Exp $";
25#endif
26#endif
27
28#include <sys/types.h>
29#include <sys/socket.h>
30#include <netinet/in.h>
31#include <arpa/inet.h>
32
33#include <errno.h>
34#include <stdio.h>
35#include <string.h>
36
37/*
38 * char *
39 * inet_neta(src, dst, size)
40 * format an in_addr_t network number into presentation format.
41 * return:
42 * pointer to dst, or NULL if an error occurred (check errno).
43 * note:
44 * format of ``src'' is as for inet_network().
45 * author:
46 * Paul Vixie (ISC), July 1996
47 */
48char *
49inet_neta(src, dst, size)
50 in_addr_t src;
51 char *dst;
52 size_t size;
53{
54 char *odst = dst;
55 char *ep;
56 int advance;
57
58 if (src == 0x00000000) {
59 if (size < sizeof "0.0.0.0")
60 goto emsgsize;
61 strlcpy(dst, "0.0.0.0", size);
62 return dst;
63 }
64 ep = dst + size;
65 if (ep <= dst)
66 goto emsgsize;
67 while (src & 0xffffffff) {
68 u_char b = (src & 0xff000000) >> 24;
69
70 src <<= 8;
71 if (b || src) {
72 if (ep - dst < sizeof "255.")
73 goto emsgsize;
74 advance = snprintf(dst, ep - dst, "%u", b);
75 if (advance <= 0 || advance >= ep - dst)
76 goto emsgsize;
77 dst += advance;
78 if (src != 0L) {
79 if (dst + 1 >= ep)
80 goto emsgsize;
81 *dst++ = '.';
82 *dst = '\0';
83 }
84 }
85 }
86 return (odst);
87
88 emsgsize:
89 errno = EMSGSIZE;
90 return (NULL);
91}
diff --git a/src/lib/libc/net/inet_netof.c b/src/lib/libc/net/inet_netof.c
index 02f52ca318..f3b9c01697 100644
--- a/src/lib/libc/net/inet_netof.c
+++ b/src/lib/libc/net/inet_netof.c
@@ -1,5 +1,3 @@
1/* $NetBSD: inet_netof.c,v 1.4 1995/02/25 06:20:43 cgd Exp $ */
2
3/* 1/*
4 * Copyright (c) 1983, 1993 2 * Copyright (c) 1983, 1993
5 * The Regents of the University of California. All rights reserved. 3 * The Regents of the University of California. All rights reserved.
@@ -34,11 +32,7 @@
34 */ 32 */
35 33
36#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
37#if 0 35static char rcsid[] = "$OpenBSD: inet_netof.c,v 1.3 1997/04/05 21:13:13 millert Exp $";
38static char sccsid[] = "@(#)inet_netof.c 8.1 (Berkeley) 6/4/93";
39#else
40static char rcsid[] = "$NetBSD: inet_netof.c,v 1.4 1995/02/25 06:20:43 cgd Exp $";
41#endif
42#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
43 37
44#include <sys/param.h> 38#include <sys/param.h>
@@ -49,11 +43,11 @@ static char rcsid[] = "$NetBSD: inet_netof.c,v 1.4 1995/02/25 06:20:43 cgd Exp $
49 * Return the network number from an internet 43 * Return the network number from an internet
50 * address; handles class a/b/c network #'s. 44 * address; handles class a/b/c network #'s.
51 */ 45 */
52u_long 46in_addr_t
53inet_netof(in) 47inet_netof(in)
54 struct in_addr in; 48 struct in_addr in;
55{ 49{
56 register u_long i = ntohl(in.s_addr); 50 register in_addr_t i = ntohl(in.s_addr);
57 51
58 if (IN_CLASSA(i)) 52 if (IN_CLASSA(i))
59 return (((i)&IN_CLASSA_NET) >> IN_CLASSA_NSHIFT); 53 return (((i)&IN_CLASSA_NET) >> IN_CLASSA_NSHIFT);
diff --git a/src/lib/libc/net/inet_network.c b/src/lib/libc/net/inet_network.c
index 35105fa75a..8a9a555d62 100644
--- a/src/lib/libc/net/inet_network.c
+++ b/src/lib/libc/net/inet_network.c
@@ -1,5 +1,3 @@
1/* $NetBSD: inet_network.c,v 1.4 1995/02/25 06:20:45 cgd Exp $ */
2
3/* 1/*
4 * Copyright (c) 1983, 1993 2 * Copyright (c) 1983, 1993
5 * The Regents of the University of California. All rights reserved. 3 * The Regents of the University of California. All rights reserved.
@@ -34,11 +32,7 @@
34 */ 32 */
35 33
36#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
37#if 0 35static char rcsid[] = "$OpenBSD: inet_network.c,v 1.7 1997/07/09 01:08:37 millert Exp $";
38static char sccsid[] = "@(#)inet_network.c 8.1 (Berkeley) 6/4/93";
39#else
40static char rcsid[] = "$NetBSD: inet_network.c,v 1.4 1995/02/25 06:20:45 cgd Exp $";
41#endif
42#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
43 37
44#include <sys/types.h> 38#include <sys/types.h>
@@ -51,13 +45,13 @@ static char rcsid[] = "$NetBSD: inet_network.c,v 1.4 1995/02/25 06:20:45 cgd Exp
51 * The library routines call this routine to interpret 45 * The library routines call this routine to interpret
52 * network numbers. 46 * network numbers.
53 */ 47 */
54u_long 48in_addr_t
55inet_network(cp) 49inet_network(cp)
56 register const char *cp; 50 register const char *cp;
57{ 51{
58 register u_long val, base, n; 52 register in_addr_t val, base, n;
59 register char c; 53 register char c;
60 u_long parts[4], *pp = parts; 54 in_addr_t parts[4], *pp = parts;
61 register int i; 55 register int i;
62 56
63again: 57again:
@@ -66,7 +60,7 @@ again:
66 base = 8, cp++; 60 base = 8, cp++;
67 if (*cp == 'x' || *cp == 'X') 61 if (*cp == 'x' || *cp == 'X')
68 base = 16, cp++; 62 base = 16, cp++;
69 while (c = *cp) { 63 while ((c = *cp)) {
70 if (isdigit(c)) { 64 if (isdigit(c)) {
71 val = (val * base) + (c - '0'); 65 val = (val * base) + (c - '0');
72 cp++; 66 cp++;
@@ -80,7 +74,7 @@ again:
80 break; 74 break;
81 } 75 }
82 if (*cp == '.') { 76 if (*cp == '.') {
83 if (pp >= parts + 4) 77 if (pp >= parts + 3)
84 return (INADDR_NONE); 78 return (INADDR_NONE);
85 *pp++ = val, cp++; 79 *pp++ = val, cp++;
86 goto again; 80 goto again;
@@ -89,11 +83,10 @@ again:
89 return (INADDR_NONE); 83 return (INADDR_NONE);
90 *pp++ = val; 84 *pp++ = val;
91 n = pp - parts; 85 n = pp - parts;
92 if (n > 4) 86 for (val = 0, i = 0; i < 4; i++) {
93 return (INADDR_NONE);
94 for (val = 0, i = 0; i < n; i++) {
95 val <<= 8; 87 val <<= 8;
96 val |= parts[i] & 0xff; 88 if (i < n)
89 val |= parts[i] & 0xff;
97 } 90 }
98 return (val); 91 return (val);
99} 92}
diff --git a/src/lib/libc/net/inet_ntoa.c b/src/lib/libc/net/inet_ntoa.c
index 2da0ab00ff..377184f366 100644
--- a/src/lib/libc/net/inet_ntoa.c
+++ b/src/lib/libc/net/inet_ntoa.c
@@ -1,5 +1,3 @@
1/* $NetBSD: inet_ntoa.c,v 1.4 1995/02/25 06:20:46 cgd Exp $ */
2
3/* 1/*
4 * Copyright (c) 1983, 1993 2 * Copyright (c) 1983, 1993
5 * The Regents of the University of California. All rights reserved. 3 * The Regents of the University of California. All rights reserved.
@@ -34,11 +32,7 @@
34 */ 32 */
35 33
36#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
37#if 0 35static char rcsid[] = "$OpenBSD: inet_ntoa.c,v 1.3 2002/06/27 10:14:01 itojun Exp $";
38static char sccsid[] = "@(#)inet_ntoa.c 8.1 (Berkeley) 6/4/93";
39#else
40static char rcsid[] = "$NetBSD: inet_ntoa.c,v 1.4 1995/02/25 06:20:46 cgd Exp $";
41#endif
42#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
43 37
44/* 38/*
@@ -60,6 +54,6 @@ inet_ntoa(in)
60 p = (char *)&in; 54 p = (char *)&in;
61#define UC(b) (((int)b)&0xff) 55#define UC(b) (((int)b)&0xff)
62 (void)snprintf(b, sizeof(b), 56 (void)snprintf(b, sizeof(b),
63 "%d.%d.%d.%d", UC(p[0]), UC(p[1]), UC(p[2]), UC(p[3])); 57 "%u.%u.%u.%u", UC(p[0]), UC(p[1]), UC(p[2]), UC(p[3]));
64 return (b); 58 return (b);
65} 59}
diff --git a/src/lib/libc/net/inet_ntop.c b/src/lib/libc/net/inet_ntop.c
new file mode 100644
index 0000000000..adce61c1d4
--- /dev/null
+++ b/src/lib/libc/net/inet_ntop.c
@@ -0,0 +1,213 @@
1/* $OpenBSD: inet_ntop.c,v 1.5 2002/08/23 16:27:31 itojun Exp $ */
2
3/* Copyright (c) 1996 by Internet Software Consortium.
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
10 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
11 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
12 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
15 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
16 * SOFTWARE.
17 */
18
19#if defined(LIBC_SCCS) && !defined(lint)
20#if 0
21static char rcsid[] = "$From: inet_ntop.c,v 8.7 1996/08/05 08:41:18 vixie Exp $";
22#else
23static char rcsid[] = "$OpenBSD: inet_ntop.c,v 1.5 2002/08/23 16:27:31 itojun Exp $";
24#endif
25#endif /* LIBC_SCCS and not lint */
26
27#include <sys/param.h>
28#include <sys/types.h>
29#include <sys/socket.h>
30#include <netinet/in.h>
31#include <arpa/inet.h>
32#include <arpa/nameser.h>
33#include <string.h>
34#include <errno.h>
35#include <stdio.h>
36
37/*
38 * WARNING: Don't even consider trying to compile this on a system where
39 * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
40 */
41
42static const char *inet_ntop4(const u_char *src, char *dst, size_t size);
43static const char *inet_ntop6(const u_char *src, char *dst, size_t size);
44
45/* char *
46 * inet_ntop(af, src, dst, size)
47 * convert a network format address to presentation format.
48 * return:
49 * pointer to presentation format address (`dst'), or NULL (see errno).
50 * author:
51 * Paul Vixie, 1996.
52 */
53const char *
54inet_ntop(af, src, dst, size)
55 int af;
56 const void *src;
57 char *dst;
58 size_t size;
59{
60 switch (af) {
61 case AF_INET:
62 return (inet_ntop4(src, dst, size));
63 case AF_INET6:
64 return (inet_ntop6(src, dst, size));
65 default:
66 errno = EAFNOSUPPORT;
67 return (NULL);
68 }
69 /* NOTREACHED */
70}
71
72/* const char *
73 * inet_ntop4(src, dst, size)
74 * format an IPv4 address, more or less like inet_ntoa()
75 * return:
76 * `dst' (as a const)
77 * notes:
78 * (1) uses no statics
79 * (2) takes a u_char* not an in_addr as input
80 * author:
81 * Paul Vixie, 1996.
82 */
83static const char *
84inet_ntop4(src, dst, size)
85 const u_char *src;
86 char *dst;
87 size_t size;
88{
89 static const char fmt[] = "%u.%u.%u.%u";
90 char tmp[sizeof "255.255.255.255"];
91 int l;
92
93 l = snprintf(tmp, size, fmt, src[0], src[1], src[2], src[3]);
94 if (l <= 0 || l >= size) {
95 errno = ENOSPC;
96 return (NULL);
97 }
98 strlcpy(dst, tmp, size);
99 return (dst);
100}
101
102/* const char *
103 * inet_ntop6(src, dst, size)
104 * convert IPv6 binary address into presentation (printable) format
105 * author:
106 * Paul Vixie, 1996.
107 */
108static const char *
109inet_ntop6(src, dst, size)
110 const u_char *src;
111 char *dst;
112 size_t size;
113{
114 /*
115 * Note that int32_t and int16_t need only be "at least" large enough
116 * to contain a value of the specified size. On some systems, like
117 * Crays, there is no such thing as an integer variable with 16 bits.
118 * Keep this in mind if you think this function should have been coded
119 * to use pointer overlays. All the world's not a VAX.
120 */
121 char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"];
122 char *tp, *ep;
123 struct { int base, len; } best, cur;
124 u_int words[IN6ADDRSZ / INT16SZ];
125 int i;
126 int advance;
127
128 /*
129 * Preprocess:
130 * Copy the input (bytewise) array into a wordwise array.
131 * Find the longest run of 0x00's in src[] for :: shorthanding.
132 */
133 memset(words, '\0', sizeof words);
134 for (i = 0; i < IN6ADDRSZ; i++)
135 words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
136 best.base = -1;
137 cur.base = -1;
138 for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
139 if (words[i] == 0) {
140 if (cur.base == -1)
141 cur.base = i, cur.len = 1;
142 else
143 cur.len++;
144 } else {
145 if (cur.base != -1) {
146 if (best.base == -1 || cur.len > best.len)
147 best = cur;
148 cur.base = -1;
149 }
150 }
151 }
152 if (cur.base != -1) {
153 if (best.base == -1 || cur.len > best.len)
154 best = cur;
155 }
156 if (best.base != -1 && best.len < 2)
157 best.base = -1;
158
159 /*
160 * Format the result.
161 */
162 tp = tmp;
163 ep = tmp + sizeof(tmp);
164 for (i = 0; i < (IN6ADDRSZ / INT16SZ) && tp < ep; i++) {
165 /* Are we inside the best run of 0x00's? */
166 if (best.base != -1 && i >= best.base &&
167 i < (best.base + best.len)) {
168 if (i == best.base) {
169 if (tp + 1 >= ep)
170 return (NULL);
171 *tp++ = ':';
172 }
173 continue;
174 }
175 /* Are we following an initial run of 0x00s or any real hex? */
176 if (i != 0) {
177 if (tp + 1 >= ep)
178 return (NULL);
179 *tp++ = ':';
180 }
181 /* Is this address an encapsulated IPv4? */
182 if (i == 6 && best.base == 0 &&
183 (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
184 if (!inet_ntop4(src+12, tp, (size_t)(ep - tp)))
185 return (NULL);
186 tp += strlen(tp);
187 break;
188 }
189 advance = snprintf(tp, ep - tp, "%x", words[i]);
190 if (advance <= 0 || advance >= ep - tp)
191 return (NULL);
192 tp += advance;
193 }
194 /* Was it a trailing run of 0x00's? */
195 if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ)) {
196 if (tp + 1 >= ep)
197 return (NULL);
198 *tp++ = ':';
199 }
200 if (tp + 1 >= ep)
201 return (NULL);
202 *tp++ = '\0';
203
204 /*
205 * Check for overflow, copy, and we're done.
206 */
207 if ((size_t)(tp - tmp) > size) {
208 errno = ENOSPC;
209 return (NULL);
210 }
211 strlcpy(dst, tmp, size);
212 return (dst);
213}
diff --git a/src/lib/libc/net/inet_pton.c b/src/lib/libc/net/inet_pton.c
new file mode 100644
index 0000000000..b04ef05c31
--- /dev/null
+++ b/src/lib/libc/net/inet_pton.c
@@ -0,0 +1,222 @@
1/* $OpenBSD: inet_pton.c,v 1.4 2002/02/16 21:27:23 millert Exp $ */
2
3/* Copyright (c) 1996 by Internet Software Consortium.
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
10 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
11 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
12 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
15 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
16 * SOFTWARE.
17 */
18
19#if defined(LIBC_SCCS) && !defined(lint)
20#if 0
21static char rcsid[] = "$From: inet_pton.c,v 8.7 1996/08/05 08:31:35 vixie Exp $";
22#else
23static char rcsid[] = "$OpenBSD: inet_pton.c,v 1.4 2002/02/16 21:27:23 millert Exp $";
24#endif
25#endif /* LIBC_SCCS and not lint */
26
27#include <sys/param.h>
28#include <sys/types.h>
29#include <sys/socket.h>
30#include <netinet/in.h>
31#include <arpa/inet.h>
32#include <arpa/nameser.h>
33#include <string.h>
34#include <errno.h>
35
36/*
37 * WARNING: Don't even consider trying to compile this on a system where
38 * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
39 */
40
41static int inet_pton4(const char *src, u_char *dst);
42static int inet_pton6(const char *src, u_char *dst);
43
44/* int
45 * inet_pton(af, src, dst)
46 * convert from presentation format (which usually means ASCII printable)
47 * to network format (which is usually some kind of binary format).
48 * return:
49 * 1 if the address was valid for the specified address family
50 * 0 if the address wasn't valid (`dst' is untouched in this case)
51 * -1 if some other error occurred (`dst' is untouched in this case, too)
52 * author:
53 * Paul Vixie, 1996.
54 */
55int
56inet_pton(af, src, dst)
57 int af;
58 const char *src;
59 void *dst;
60{
61 switch (af) {
62 case AF_INET:
63 return (inet_pton4(src, dst));
64 case AF_INET6:
65 return (inet_pton6(src, dst));
66 default:
67 errno = EAFNOSUPPORT;
68 return (-1);
69 }
70 /* NOTREACHED */
71}
72
73/* int
74 * inet_pton4(src, dst)
75 * like inet_aton() but without all the hexadecimal and shorthand.
76 * return:
77 * 1 if `src' is a valid dotted quad, else 0.
78 * notice:
79 * does not touch `dst' unless it's returning 1.
80 * author:
81 * Paul Vixie, 1996.
82 */
83static int
84inet_pton4(src, dst)
85 const char *src;
86 u_char *dst;
87{
88 static const char digits[] = "0123456789";
89 int saw_digit, octets, ch;
90 u_char tmp[INADDRSZ], *tp;
91
92 saw_digit = 0;
93 octets = 0;
94 *(tp = tmp) = 0;
95 while ((ch = *src++) != '\0') {
96 const char *pch;
97
98 if ((pch = strchr(digits, ch)) != NULL) {
99 u_int new = *tp * 10 + (pch - digits);
100
101 if (new > 255)
102 return (0);
103 if (! saw_digit) {
104 if (++octets > 4)
105 return (0);
106 saw_digit = 1;
107 }
108 *tp = new;
109 } else if (ch == '.' && saw_digit) {
110 if (octets == 4)
111 return (0);
112 *++tp = 0;
113 saw_digit = 0;
114 } else
115 return (0);
116 }
117 if (octets < 4)
118 return (0);
119
120 memcpy(dst, tmp, INADDRSZ);
121 return (1);
122}
123
124/* int
125 * inet_pton6(src, dst)
126 * convert presentation level address to network order binary form.
127 * return:
128 * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
129 * notice:
130 * (1) does not touch `dst' unless it's returning 1.
131 * (2) :: in a full address is silently ignored.
132 * credit:
133 * inspired by Mark Andrews.
134 * author:
135 * Paul Vixie, 1996.
136 */
137static int
138inet_pton6(src, dst)
139 const char *src;
140 u_char *dst;
141{
142 static const char xdigits_l[] = "0123456789abcdef",
143 xdigits_u[] = "0123456789ABCDEF";
144 u_char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
145 const char *xdigits, *curtok;
146 int ch, saw_xdigit;
147 u_int val;
148
149 memset((tp = tmp), '\0', IN6ADDRSZ);
150 endp = tp + IN6ADDRSZ;
151 colonp = NULL;
152 /* Leading :: requires some special handling. */
153 if (*src == ':')
154 if (*++src != ':')
155 return (0);
156 curtok = src;
157 saw_xdigit = 0;
158 val = 0;
159 while ((ch = *src++) != '\0') {
160 const char *pch;
161
162 if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
163 pch = strchr((xdigits = xdigits_u), ch);
164 if (pch != NULL) {
165 val <<= 4;
166 val |= (pch - xdigits);
167 if (val > 0xffff)
168 return (0);
169 saw_xdigit = 1;
170 continue;
171 }
172 if (ch == ':') {
173 curtok = src;
174 if (!saw_xdigit) {
175 if (colonp)
176 return (0);
177 colonp = tp;
178 continue;
179 } else if (*src == '\0') {
180 return (0);
181 }
182 if (tp + INT16SZ > endp)
183 return (0);
184 *tp++ = (u_char) (val >> 8) & 0xff;
185 *tp++ = (u_char) val & 0xff;
186 saw_xdigit = 0;
187 val = 0;
188 continue;
189 }
190 if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
191 inet_pton4(curtok, tp) > 0) {
192 tp += INADDRSZ;
193 saw_xdigit = 0;
194 break; /* '\0' was seen by inet_pton4(). */
195 }
196 return (0);
197 }
198 if (saw_xdigit) {
199 if (tp + INT16SZ > endp)
200 return (0);
201 *tp++ = (u_char) (val >> 8) & 0xff;
202 *tp++ = (u_char) val & 0xff;
203 }
204 if (colonp != NULL) {
205 /*
206 * Since some memmove()'s erroneously fail to handle
207 * overlapping regions, we'll do the shift by hand.
208 */
209 const int n = tp - colonp;
210 int i;
211
212 for (i = 1; i <= n; i++) {
213 endp[- i] = colonp[n - i];
214 colonp[n - i] = 0;
215 }
216 tp = endp;
217 }
218 if (tp != endp)
219 return (0);
220 memcpy(dst, tmp, IN6ADDRSZ);
221 return (1);
222}
diff --git a/src/lib/libc/net/ip6opt.c b/src/lib/libc/net/ip6opt.c
new file mode 100644
index 0000000000..cbd49f0c22
--- /dev/null
+++ b/src/lib/libc/net/ip6opt.c
@@ -0,0 +1,388 @@
1/* $OpenBSD: ip6opt.c,v 1.1 1999/12/11 08:09:11 itojun Exp $ */
2
3/*
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#include <sys/param.h>
33#include <sys/types.h>
34#include <sys/socket.h>
35
36#include <netinet/in.h>
37#include <netinet/ip6.h>
38
39#include <string.h>
40#include <stdio.h>
41
42static int ip6optlen(u_int8_t *opt, u_int8_t *lim);
43static void inet6_insert_padopt(u_char *p, int len);
44
45/*
46 * This function returns the number of bytes required to hold an option
47 * when it is stored as ancillary data, including the cmsghdr structure
48 * at the beginning, and any padding at the end (to make its size a
49 * multiple of 8 bytes). The argument is the size of the structure
50 * defining the option, which must include any pad bytes at the
51 * beginning (the value y in the alignment term "xn + y"), the type
52 * byte, the length byte, and the option data.
53 */
54int
55inet6_option_space(nbytes)
56 int nbytes;
57{
58 nbytes += 2; /* we need space for nxt-hdr and length fields */
59 return(CMSG_SPACE((nbytes + 7) & ~7));
60}
61
62/*
63 * This function is called once per ancillary data object that will
64 * contain either Hop-by-Hop or Destination options. It returns 0 on
65 * success or -1 on an error.
66 */
67int
68inet6_option_init(bp, cmsgp, type)
69 void *bp;
70 struct cmsghdr **cmsgp;
71 int type;
72{
73 register struct cmsghdr *ch = (struct cmsghdr *)bp;
74
75 /* argument validation */
76 if (type != IPV6_HOPOPTS && type != IPV6_DSTOPTS)
77 return(-1);
78
79 ch->cmsg_level = IPPROTO_IPV6;
80 ch->cmsg_type = type;
81 ch->cmsg_len = CMSG_LEN(0);
82
83 *cmsgp = ch;
84 return(0);
85}
86
87/*
88 * This function appends a Hop-by-Hop option or a Destination option
89 * into an ancillary data object that has been initialized by
90 * inet6_option_init(). This function returns 0 if it succeeds or -1 on
91 * an error.
92 * multx is the value x in the alignment term "xn + y" described
93 * earlier. It must have a value of 1, 2, 4, or 8.
94 * plusy is the value y in the alignment term "xn + y" described
95 * earlier. It must have a value between 0 and 7, inclusive.
96 */
97int
98inet6_option_append(cmsg, typep, multx, plusy)
99 struct cmsghdr *cmsg;
100 const u_int8_t *typep;
101 int multx;
102 int plusy;
103{
104 int padlen, optlen, off;
105 register u_char *bp = (u_char *)cmsg + cmsg->cmsg_len;
106 struct ip6_ext *eh = (struct ip6_ext *)CMSG_DATA(cmsg);
107
108 /* argument validation */
109 if (multx != 1 && multx != 2 && multx != 4 && multx != 8)
110 return(-1);
111 if (plusy < 0 || plusy > 7)
112 return(-1);
113 if (typep[0] > 255)
114 return(-1);
115
116 /*
117 * If this is the first option, allocate space for the
118 * first 2 bytes(for next header and length fields) of
119 * the option header.
120 */
121 if (bp == (u_char *)eh) {
122 bp += 2;
123 cmsg->cmsg_len += 2;
124 }
125
126 /* calculate pad length before the option. */
127 off = bp - (u_char *)eh;
128 padlen = (((off % multx) + (multx - 1)) & ~(multx - 1)) -
129 (off % multx);
130 padlen += plusy;
131 padlen %= multx; /* keep the pad as short as possible */
132 /* insert padding */
133 inet6_insert_padopt(bp, padlen);
134 cmsg->cmsg_len += padlen;
135 bp += padlen;
136
137 /* copy the option */
138 if (typep[0] == IP6OPT_PAD1)
139 optlen = 1;
140 else
141 optlen = typep[1] + 2;
142 memcpy(bp, typep, optlen);
143 bp += optlen;
144 cmsg->cmsg_len += optlen;
145
146 /* calculate pad length after the option and insert the padding */
147 off = bp - (u_char *)eh;
148 padlen = ((off + 7) & ~7) - off;
149 inet6_insert_padopt(bp, padlen);
150 bp += padlen;
151 cmsg->cmsg_len += padlen;
152
153 /* update the length field of the ip6 option header */
154 eh->ip6e_len = ((bp - (u_char *)eh) >> 3) - 1;
155
156 return(0);
157}
158
159/*
160 * This function appends a Hop-by-Hop option or a Destination option
161 * into an ancillary data object that has been initialized by
162 * inet6_option_init(). This function returns a pointer to the 8-bit
163 * option type field that starts the option on success, or NULL on an
164 * error.
165 * The difference between this function and inet6_option_append() is
166 * that the latter copies the contents of a previously built option into
167 * the ancillary data object while the current function returns a
168 * pointer to the space in the data object where the option's TLV must
169 * then be built by the caller.
170 *
171 */
172u_int8_t *
173inet6_option_alloc(cmsg, datalen, multx, plusy)
174 struct cmsghdr *cmsg;
175 int datalen;
176 int multx;
177 int plusy;
178{
179 int padlen, off;
180 register u_int8_t *bp = (u_char *)cmsg + cmsg->cmsg_len;
181 u_int8_t *retval;
182 struct ip6_ext *eh = (struct ip6_ext *)CMSG_DATA(cmsg);
183
184 /* argument validation */
185 if (multx != 1 && multx != 2 && multx != 4 && multx != 8)
186 return(NULL);
187 if (plusy < 0 || plusy > 7)
188 return(NULL);
189
190 /*
191 * If this is the first option, allocate space for the
192 * first 2 bytes(for next header and length fields) of
193 * the option header.
194 */
195 if (bp == (u_char *)eh) {
196 bp += 2;
197 cmsg->cmsg_len += 2;
198 }
199
200 /* calculate pad length before the option. */
201 off = bp - (u_char *)eh;
202 padlen = (((off % multx) + (multx - 1)) & ~(multx - 1)) -
203 (off % multx);
204 padlen += plusy;
205 padlen %= multx; /* keep the pad as short as possible */
206 /* insert padding */
207 inet6_insert_padopt(bp, padlen);
208 cmsg->cmsg_len += padlen;
209 bp += padlen;
210
211 /* keep space to store specified length of data */
212 retval = bp;
213 bp += datalen;
214 cmsg->cmsg_len += datalen;
215
216 /* calculate pad length after the option and insert the padding */
217 off = bp - (u_char *)eh;
218 padlen = ((off + 7) & ~7) - off;
219 inet6_insert_padopt(bp, padlen);
220 bp += padlen;
221 cmsg->cmsg_len += padlen;
222
223 /* update the length field of the ip6 option header */
224 eh->ip6e_len = ((bp - (u_char *)eh) >> 3) - 1;
225
226 return(retval);
227}
228
229/*
230 * This function processes the next Hop-by-Hop option or Destination
231 * option in an ancillary data object. If another option remains to be
232 * processed, the return value of the function is 0 and *tptrp points to
233 * the 8-bit option type field (which is followed by the 8-bit option
234 * data length, followed by the option data). If no more options remain
235 * to be processed, the return value is -1 and *tptrp is NULL. If an
236 * error occurs, the return value is -1 and *tptrp is not NULL.
237 * (RFC 2292, 6.3.5)
238 */
239int
240inet6_option_next(cmsg, tptrp)
241 const struct cmsghdr *cmsg;
242 u_int8_t **tptrp;
243{
244 struct ip6_ext *ip6e;
245 int hdrlen, optlen;
246 u_int8_t *lim;
247
248 if (cmsg->cmsg_level != IPPROTO_IPV6 ||
249 (cmsg->cmsg_type != IPV6_HOPOPTS &&
250 cmsg->cmsg_type != IPV6_DSTOPTS))
251 return(-1);
252
253 /* message length validation */
254 if (cmsg->cmsg_len < CMSG_SPACE(sizeof(struct ip6_ext)))
255 return(-1);
256 ip6e = (struct ip6_ext *)CMSG_DATA(cmsg);
257 hdrlen = (ip6e->ip6e_len + 1) << 3;
258 if (cmsg->cmsg_len < CMSG_SPACE(hdrlen))
259 return(-1);
260
261 /*
262 * If the caller does not specify the starting point,
263 * simply return the 1st option.
264 * Otherwise, search the option list for the next option.
265 */
266 lim = (u_int8_t *)ip6e + hdrlen;
267 if (*tptrp == NULL)
268 *tptrp = (u_int8_t *)(ip6e + 1);
269 else {
270 if ((optlen = ip6optlen(*tptrp, lim)) == 0)
271 return(-1);
272
273 *tptrp = *tptrp + optlen;
274 }
275 if (*tptrp >= lim) { /* there is no option */
276 *tptrp = NULL;
277 return(-1);
278 }
279 /*
280 * Finally, checks if the next option is safely stored in the
281 * cmsg data.
282 */
283 if (ip6optlen(*tptrp, lim) == 0)
284 return(-1);
285 else
286 return(0);
287}
288
289/*
290 * This function is similar to the inet6_option_next() function,
291 * except this function lets the caller specify the option type to be
292 * searched for, instead of always returning the next option in the
293 * ancillary data object.
294 * Note: RFC 2292 says the type of tptrp is u_int8_t *, but we think
295 * it's a typo. The variable should be type of u_int8_t **.
296 */
297int
298inet6_option_find(cmsg, tptrp, type)
299 const struct cmsghdr *cmsg;
300 u_int8_t **tptrp;
301 int type;
302{
303 struct ip6_ext *ip6e;
304 int hdrlen, optlen;
305 u_int8_t *optp, *lim;
306
307 if (cmsg->cmsg_level != IPPROTO_IPV6 ||
308 (cmsg->cmsg_type != IPV6_HOPOPTS &&
309 cmsg->cmsg_type != IPV6_DSTOPTS))
310 return(-1);
311
312 /* message length validation */
313 if (cmsg->cmsg_len < CMSG_SPACE(sizeof(struct ip6_ext)))
314 return(-1);
315 ip6e = (struct ip6_ext *)CMSG_DATA(cmsg);
316 hdrlen = (ip6e->ip6e_len + 1) << 3;
317 if (cmsg->cmsg_len < CMSG_SPACE(hdrlen))
318 return(-1);
319
320 /*
321 * If the caller does not specify the starting point,
322 * search from the beginning of the option list.
323 * Otherwise, search from *the next option* of the specified point.
324 */
325 lim = (u_int8_t *)ip6e + hdrlen;
326 if (*tptrp == NULL)
327 *tptrp = (u_int8_t *)(ip6e + 1);
328 else {
329 if ((optlen = ip6optlen(*tptrp, lim)) == 0)
330 return(-1);
331
332 *tptrp = *tptrp + optlen;
333 }
334 for (optp = *tptrp; optp < lim; optp += optlen) {
335 if (*optp == type) {
336 *tptrp = optp;
337 return(0);
338 }
339 if ((optlen = ip6optlen(optp, lim)) == 0)
340 return(-1);
341 }
342
343 /* search failed */
344 *tptrp = NULL;
345 return(-1);
346}
347
348/*
349 * Calculate the length of a given IPv6 option. Also checks
350 * if the option is safely stored in user's buffer according to the
351 * calculated length and the limitation of the buffer.
352 */
353static int
354ip6optlen(opt, lim)
355 u_int8_t *opt, *lim;
356{
357 int optlen;
358
359 if (*opt == IP6OPT_PAD1)
360 optlen = 1;
361 else {
362 /* is there enough space to store type and len? */
363 if (opt + 2 > lim)
364 return(0);
365 optlen = *(opt + 1) + 2;
366 }
367 if (opt + optlen <= lim)
368 return(optlen);
369
370 return(0);
371}
372
373static void
374inet6_insert_padopt(u_char *p, int len)
375{
376 switch(len) {
377 case 0:
378 return;
379 case 1:
380 p[0] = IP6OPT_PAD1;
381 return;
382 default:
383 p[0] = IP6OPT_PADN;
384 p[1] = len - 2;
385 memset(&p[2], 0, len - 2);
386 return;
387 }
388}
diff --git a/src/lib/libc/net/ipx.3 b/src/lib/libc/net/ipx.3
new file mode 100644
index 0000000000..670f174d8b
--- /dev/null
+++ b/src/lib/libc/net/ipx.3
@@ -0,0 +1,127 @@
1.\" $OpenBSD: ipx.3,v 1.9 2003/05/01 19:17:37 jmc Exp $
2.\"
3.\" Copyright (c) 1986, 1991, 1993
4.\" The Regents of the University of California. All rights reserved.
5.\"
6.\" Redistribution and use in source and binary forms, with or without
7.\" modification, are permitted provided that the following conditions
8.\" are met:
9.\" 1. Redistributions of source code must retain the above copyright
10.\" notice, this list of conditions and the following disclaimer.
11.\" 2. Redistributions in binary form must reproduce the above copyright
12.\" notice, this list of conditions and the following disclaimer in the
13.\" documentation and/or other materials provided with the distribution.
14.\" 3. All advertising materials mentioning features or use of this software
15.\" must display the following acknowledgement:
16.\" This product includes software developed by the University of
17.\" California, Berkeley and its contributors.
18.\" 4. Neither the name of the University nor the names of its contributors
19.\" may be used to endorse or promote products derived from this software
20.\" without specific prior written permission.
21.\"
22.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32.\" SUCH DAMAGE.
33.\"
34.Dd June 4, 1993
35.Dt IPX 3
36.Os
37.Sh NAME
38.Nm ipx_addr ,
39.Nm ipx_ntoa
40.Nd IPX address conversion routines
41.Sh SYNOPSIS
42.Fd #include <sys/types.h>
43.Fd #include <netipx/ipx.h>
44.Ft struct ipx_addr
45.Fn ipx_addr "const char *cp"
46.Ft char *
47.Fn ipx_ntoa "struct ipx_addr ipx"
48.Sh DESCRIPTION
49The routine
50.Fn ipx_addr
51interprets character strings representing
52.Tn IPX
53addresses, returning binary information suitable
54for use in system calls.
55The routine
56.Fn ipx_ntoa
57takes
58.Tn IPX
59addresses and returns
60.Tn ASCII
61strings representing the address in a
62notation in common use:
63.Bd -filled -offset indent
64<network number>.<host number>.<port number>
65.Ed
66.Pp
67Trailing zero fields are suppressed, and each number is printed in hexadecimal,
68in a format suitable for input to
69.Fn ipx_addr .
70Any fields lacking super-decimal digits will have a
71trailing
72.Sq H
73appended.
74.Pp
75An effort has been made to ensure that
76.Fn ipx_addr
77be compatible with most formats in common use.
78It will first separate an address into 1 to 3 fields using a single delimiter
79chosen from
80period
81.Pq Ql \&. ,
82colon
83.Pq Ql \&: ,
84or pound-sign
85.Pq Ql # .
86Each field is then examined for byte separators (colon or period).
87If there are byte separators, each subfield separated is taken to be
88a small hexadecimal number, and the entirety is taken as a network-byte-ordered
89quantity to be zero extended in the high-network-order bytes.
90Next, the field is inspected for hyphens, in which case
91the field is assumed to be a number in decimal notation
92with hyphens separating the millenia.
93Next, the field is assumed to be a number:
94It is interpreted
95as hexadecimal if there is a leading
96.Ql 0x
97(as in C),
98a trailing
99.Sq H
100(as in Mesa), or there are any super-decimal digits present.
101It is interpreted as octal if there is a leading
102.Ql 0
103and there are no super-octal digits.
104Otherwise, it is converted as a decimal number.
105.Sh RETURN VALUES
106None.
107(See
108.Sx BUGS . )
109.Sh SEE ALSO
110.Xr ns 4 ,
111.Xr hosts 5 ,
112.Xr networks 5
113.Sh HISTORY
114The precursor
115.Fn ns_addr
116and
117.Fn ns_ntoa
118functions appeared in
119.Bx 4.3 .
120.Sh BUGS
121The string returned by
122.Fn ipx_ntoa
123resides in a static memory area.
124The function
125.Fn ipx_addr
126should diagnose improperly formed input, and there should be an unambiguous
127way to recognize this.
diff --git a/src/lib/libc/net/ipx_addr.c b/src/lib/libc/net/ipx_addr.c
new file mode 100644
index 0000000000..0d225e281b
--- /dev/null
+++ b/src/lib/libc/net/ipx_addr.c
@@ -0,0 +1,228 @@
1/*
2 * Copyright (c) 1986, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * J.Q. Johnson.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * from @(#)ipx_addr.c
37 */
38
39#if defined(LIBC_SCCS) && !defined(lint)
40static char rcsid[] = "$OpenBSD: ipx_addr.c,v 1.5 2001/06/27 00:58:55 lebel Exp $";
41#endif /* LIBC_SCCS and not lint */
42
43#include <sys/param.h>
44#include <netipx/ipx.h>
45#include <stdio.h>
46#include <string.h>
47
48static struct ipx_addr addr, zero_addr;
49
50static void Field(), cvtbase();
51
52struct ipx_addr
53ipx_addr(name)
54 const char *name;
55{
56 char separator;
57 char *hostname, *socketname, *cp;
58 char buf[50];
59
60 strlcpy(buf, name, sizeof(buf));
61
62 /*
63 * First, figure out what he intends as a field separtor.
64 * Despite the way this routine is written, the prefered
65 * form 2-272.AA001234H.01777, i.e. XDE standard.
66 * Great efforts are made to insure backward compatibility.
67 */
68 if ((hostname = strchr(buf, '#')))
69 separator = '#';
70 else {
71 hostname = strchr(buf, '.');
72 if ((cp = strchr(buf, ':')) &&
73 ((hostname && cp < hostname) || (hostname == 0))) {
74 hostname = cp;
75 separator = ':';
76 } else
77 separator = '.';
78 }
79 if (hostname)
80 *hostname++ = 0;
81
82 addr = zero_addr;
83 Field(buf, addr.ipx_net.c_net, 4);
84 if (hostname == 0)
85 return (addr); /* No separator means net only */
86
87 socketname = strchr(hostname, separator);
88 if (socketname) {
89 *socketname++ = 0;
90 Field(socketname, (u_char *)&addr.ipx_port, 2);
91 }
92
93 Field(hostname, addr.ipx_host.c_host, 6);
94
95 return (addr);
96}
97
98static void
99Field(buf, out, len)
100 char *buf;
101 u_char *out;
102 int len;
103{
104 register char *bp = buf;
105 int i, ibase, base16 = 0, base10 = 0, clen = 0;
106 int hb[6], *hp;
107 char *fmt;
108
109 /*
110 * first try 2-273#2-852-151-014#socket
111 */
112 if ((*buf != '-') &&
113 (1 < (i = sscanf(buf, "%d-%d-%d-%d-%d",
114 &hb[0], &hb[1], &hb[2], &hb[3], &hb[4])))) {
115 cvtbase(1000L, 256, hb, i, out, len);
116 return;
117 }
118 /*
119 * try form 8E1#0.0.AA.0.5E.E6#socket
120 */
121 if (1 < (i = sscanf(buf,"%x.%x.%x.%x.%x.%x",
122 &hb[0], &hb[1], &hb[2], &hb[3], &hb[4], &hb[5]))) {
123 cvtbase(256L, 256, hb, i, out, len);
124 return;
125 }
126 /*
127 * try form 8E1#0:0:AA:0:5E:E6#socket
128 */
129 if (1 < (i = sscanf(buf,"%x:%x:%x:%x:%x:%x",
130 &hb[0], &hb[1], &hb[2], &hb[3], &hb[4], &hb[5]))) {
131 cvtbase(256L, 256, hb, i, out, len);
132 return;
133 }
134 /*
135 * This is REALLY stretching it but there was a
136 * comma notation separting shorts -- definitely non standard
137 */
138 if (1 < (i = sscanf(buf,"%x,%x,%x",
139 &hb[0], &hb[1], &hb[2]))) {
140 hb[0] = htons(hb[0]); hb[1] = htons(hb[1]);
141 hb[2] = htons(hb[2]);
142 cvtbase(65536L, 256, hb, i, out, len);
143 return;
144 }
145
146 /* Need to decide if base 10, 16 or 8 */
147 while (*bp) switch (*bp++) {
148
149 case '0': case '1': case '2': case '3': case '4': case '5':
150 case '6': case '7': case '-':
151 break;
152
153 case '8': case '9':
154 base10 = 1;
155 break;
156
157 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
158 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
159 base16 = 1;
160 break;
161
162 case 'x': case 'X':
163 *--bp = '0';
164 base16 = 1;
165 break;
166
167 case 'h': case 'H':
168 base16 = 1;
169 /* fall into */
170
171 default:
172 *--bp = 0; /* Ends Loop */
173 }
174 if (base16) {
175 fmt = "%3x";
176 ibase = 4096;
177 } else if (base10 == 0 && *buf == '0') {
178 fmt = "%3o";
179 ibase = 512;
180 } else {
181 fmt = "%3d";
182 ibase = 1000;
183 }
184
185 for (bp = buf; *bp++; ) clen++;
186 if (clen == 0) clen++;
187 if (clen > 18) clen = 18;
188 i = ((clen - 1) / 3) + 1;
189 bp = clen + buf - 3;
190 hp = hb + i - 1;
191
192 while (hp > hb) {
193 (void)sscanf(bp, fmt, hp);
194 bp[0] = 0;
195 hp--;
196 bp -= 3;
197 }
198 (void)sscanf(buf, fmt, hp);
199 cvtbase((long)ibase, 256, hb, i, out, len);
200}
201
202static void
203cvtbase(oldbase,newbase,input,inlen,result,reslen)
204 long oldbase;
205 int newbase;
206 int input[];
207 int inlen;
208 unsigned char result[];
209 int reslen;
210{
211 int d, e;
212 long sum;
213
214 e = 1;
215 while (e > 0 && reslen > 0) {
216 d = 0; e = 0; sum = 0;
217 /* long division: input=input/newbase */
218 while (d < inlen) {
219 sum = sum*oldbase + (long) input[d];
220 e += (sum > 0);
221 input[d++] = sum / newbase;
222 sum %= newbase;
223 }
224 result[--reslen] = sum; /* accumulate remainder */
225 }
226 for (d=0; d < reslen; d++)
227 result[d] = 0;
228}
diff --git a/src/lib/libc/net/ipx_ntoa.c b/src/lib/libc/net/ipx_ntoa.c
new file mode 100644
index 0000000000..598c94d599
--- /dev/null
+++ b/src/lib/libc/net/ipx_ntoa.c
@@ -0,0 +1,58 @@
1/*
2 * Copyright (c) 1986, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#if defined(LIBC_SCCS) && !defined(lint)
35static char rcsid[] = "$OpenBSD: ipx_ntoa.c,v 1.3 2002/05/24 21:22:37 deraadt Exp $";
36#endif /* LIBC_SCCS and not lint */
37
38#include <sys/param.h>
39#include <netipx/ipx.h>
40#include <stdio.h>
41
42char *
43ipx_ntoa(addr)
44 struct ipx_addr addr;
45{
46 static char obuf[] = "xxxx.xx:xx:xx:xx:xx:xx.uuuuu";
47
48 snprintf(obuf, sizeof obuf, "%8xH.%02x:%02x:%02x:%02x:%02x:%02x.%u",
49 ntohl(addr.ipx_net.l_net),
50 addr.ipx_host.c_host[0],
51 addr.ipx_host.c_host[1],
52 addr.ipx_host.c_host[2],
53 addr.ipx_host.c_host[3],
54 addr.ipx_host.c_host[4],
55 addr.ipx_host.c_host[5],
56 ntohs(addr.ipx_port));
57 return (obuf);
58}
diff --git a/src/lib/libc/net/iso_addr.3 b/src/lib/libc/net/iso_addr.3
index 95c136e5fc..8655a63973 100644
--- a/src/lib/libc/net/iso_addr.3
+++ b/src/lib/libc/net/iso_addr.3
@@ -1,4 +1,4 @@
1.\" $NetBSD: iso_addr.3,v 1.2 1995/02/25 06:20:46 cgd Exp $ 1.\" $OpenBSD: iso_addr.3,v 1.4 1999/07/05 06:08:05 aaron Exp $
2.\" 2.\"
3.\" Copyright (c) 1993 3.\" Copyright (c) 1993
4.\" The Regents of the University of California. All rights reserved. 4.\" The Regents of the University of California. All rights reserved.
@@ -31,15 +31,13 @@
31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32.\" SUCH DAMAGE. 32.\" SUCH DAMAGE.
33.\" 33.\"
34.\" @(#)iso_addr.3 8.1 (Berkeley) 6/4/93
35.\"
36.Dd June 4, 1993 34.Dd June 4, 1993
37.Dt ISO_ADDR 3 35.Dt ISO_ADDR 3
38.Os 36.Os
39.Sh NAME 37.Sh NAME
40.Nm iso_addr , 38.Nm iso_addr ,
41.Nm iso_ntoa 39.Nm iso_ntoa
42.Nd "elementary network address conversion routines for Open System Interconnection 40.Nd "network address conversion routines for Open System Interconnection"
43.Sh SYNOPSIS 41.Sh SYNOPSIS
44.Fd #include <sys/types.h> 42.Fd #include <sys/types.h>
45.Fd #include <netiso/iso.h> 43.Fd #include <netiso/iso.h>
@@ -62,7 +60,7 @@ addresses and returns
62.Tn ASCII 60.Tn ASCII
63strings representing NSAPs (network service 61strings representing NSAPs (network service
64access points) in a 62access points) in a
65notation inverse to that accepted by 63notation inverse to that accepted by
66.Fn iso_addr . 64.Fn iso_addr .
67.Pp 65.Pp
68Unfortunately, no universal standard exists for representing 66Unfortunately, no universal standard exists for representing
@@ -90,7 +88,8 @@ to have its higher order bits filled with zeros.
90.Fn iso_ntoa 88.Fn iso_ntoa
91always returns a null terminated string. 89always returns a null terminated string.
92.Fn iso_addr 90.Fn iso_addr
93always returns a pointer to a struct iso_addr. 91always returns a pointer to a
92.Li struct iso_addr .
94(See 93(See
95.Sx BUGS . ) 94.Sx BUGS . )
96.Sh SEE ALSO 95.Sh SEE ALSO
@@ -100,7 +99,7 @@ The
100.Fn iso_addr 99.Fn iso_addr
101and 100and
102.Fn iso_ntoa 101.Fn iso_ntoa
103functions appeared in 102functions appeared in
104.Bx 4.3 Reno . 103.Bx 4.3 Reno .
105.Sh BUGS 104.Sh BUGS
106The returned values 105The returned values
diff --git a/src/lib/libc/net/iso_addr.c b/src/lib/libc/net/iso_addr.c
index c26ec1a64a..01561e395b 100644
--- a/src/lib/libc/net/iso_addr.c
+++ b/src/lib/libc/net/iso_addr.c
@@ -1,5 +1,3 @@
1/* $NetBSD: iso_addr.c,v 1.4 1995/02/25 06:20:47 cgd Exp $ */
2
3/* 1/*
4 * Copyright (c) 1989, 1993 2 * Copyright (c) 1989, 1993
5 * The Regents of the University of California. All rights reserved. 3 * The Regents of the University of California. All rights reserved.
@@ -34,11 +32,7 @@
34 */ 32 */
35 33
36#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
37#if 0 35static char rcsid[] = "$OpenBSD: iso_addr.c,v 1.2 1996/08/19 08:29:23 tholo Exp $";
38static char sccsid[] = "@(#)iso_addr.c 8.1 (Berkeley) 6/4/93";
39#else
40static char rcsid[] = "$NetBSD: iso_addr.c,v 1.4 1995/02/25 06:20:47 cgd Exp $";
41#endif
42#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
43 37
44#include <sys/types.h> 38#include <sys/types.h>
diff --git a/src/lib/libc/net/linkaddr.3 b/src/lib/libc/net/link_addr.3
index 1a2af9b30d..29c2449f77 100644
--- a/src/lib/libc/net/linkaddr.3
+++ b/src/lib/libc/net/link_addr.3
@@ -1,4 +1,4 @@
1.\" $NetBSD: linkaddr.3,v 1.2 1995/02/25 06:20:48 cgd Exp $ 1.\" $OpenBSD: link_addr.3,v 1.7 2000/04/18 03:01:32 aaron Exp $
2.\" 2.\"
3.\" Copyright (c) 1993 3.\" Copyright (c) 1993
4.\" The Regents of the University of California. All rights reserved. 4.\" The Regents of the University of California. All rights reserved.
@@ -34,11 +34,9 @@
34.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35.\" SUCH DAMAGE. 35.\" SUCH DAMAGE.
36.\" 36.\"
37.\" @(#)linkaddr.3 8.1 (Berkeley) 7/28/93
38.\"
39.Dd July 28, 1993 37.Dd July 28, 1993
40.Dt LINK_ADDR 3 38.Dt LINK_ADDR 3
41.Os BSD 4.4 39.Os
42.Sh NAME 40.Sh NAME
43.Nm link_addr , 41.Nm link_addr ,
44.Nm link_ntoa 42.Nm link_ntoa
@@ -52,12 +50,11 @@
52.Ft char * 50.Ft char *
53.Fn link_ntoa "const struct sockaddr_dl *sdl" 51.Fn link_ntoa "const struct sockaddr_dl *sdl"
54.Sh DESCRIPTION 52.Sh DESCRIPTION
55The routine 53The
56.Fn link_addr 54.Fn link_addr
57interprets character strings representing 55function interprets character strings representing
58link-level addresses, returning binary information suitable 56link-level addresses, returning binary information suitable
59for use in system calls. 57for use in system calls.
60The routine
61.Fn link_ntoa 58.Fn link_ntoa
62takes 59takes
63a link-level 60a link-level
@@ -75,9 +72,9 @@ the string
75.Fa addr 72.Fa addr
76may contain 73may contain
77an optional network interface identifier of the form 74an optional network interface identifier of the form
78.Dq "name unit-number" , 75.Dq name unit-number ,
79suitable for the first argument to 76suitable for the first argument to
80.Xr ifconfig 4 , 77.Xr ifconfig 8 ,
81followed in all cases by a colon and 78followed in all cases by a colon and
82an interface address in the form of 79an interface address in the form of
83groups of hexadecimal digits 80groups of hexadecimal digits
@@ -93,24 +90,25 @@ low order bytes through high order bytes.
93.\" .Pp 90.\" .Pp
94Thus 91Thus
95.Li le0:8.0.9.13.d.30 92.Li le0:8.0.9.13.d.30
96represents an ethernet address 93represents an Ethernet address
97to be transmitted on the first Lance ethernet interface. 94to be transmitted on the first Lance Ethernet interface.
98.Sh RETURN VALUES 95.Sh RETURN VALUES
99.Fn link_ntoa 96.Fn link_ntoa
100always returns a null terminated string. 97always returns a null-terminated string.
101.Fn link_addr 98.Fn link_addr
102has no return value. 99has no return value.
103(See 100(See
104.Sx BUGS . ) 101.Sx BUGS . )
105.Sh SEE ALSO 102.Sh SEE ALSO
106.Xr iso 4 , 103.Xr iso 4 ,
104.Xr ifconfig 8
107.Sh HISTORY 105.Sh HISTORY
108The 106The
109.Fn link_addr 107.Fn link_addr
110and 108and
111.Fn link_ntoa 109.Fn link_ntoa
112functions appeared in 110functions appeared in
113.Bx 4.3 Reno . 111.Bx 4.3 Reno .
114.Sh BUGS 112.Sh BUGS
115The returned values for link_ntoa 113The returned values for link_ntoa
116reside in a static memory area. 114reside in a static memory area.
@@ -121,7 +119,7 @@ should diagnose improperly formed input, and there should be an unambiguous
121way to recognize this. 119way to recognize this.
122.Pp 120.Pp
123If the 121If the
124.Va sdl_len 122.Fa sdl_len
125field of the link socket address 123field of the link socket address
126.Fa sdl 124.Fa sdl
127is 0, 125is 0,
diff --git a/src/lib/libc/net/linkaddr.c b/src/lib/libc/net/linkaddr.c
index 19a0de3abd..fb522f3233 100644
--- a/src/lib/libc/net/linkaddr.c
+++ b/src/lib/libc/net/linkaddr.c
@@ -1,5 +1,3 @@
1/* $NetBSD: linkaddr.c,v 1.5 1995/02/25 06:20:49 cgd Exp $ */
2
3/*- 1/*-
4 * Copyright (c) 1990, 1993 2 * Copyright (c) 1990, 1993
5 * The Regents of the University of California. All rights reserved. 3 * The Regents of the University of California. All rights reserved.
@@ -34,11 +32,7 @@
34 */ 32 */
35 33
36#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
37#if 0 35static char rcsid[] = "$OpenBSD: linkaddr.c,v 1.2 1996/08/19 08:29:27 tholo Exp $";
38static char sccsid[] = "@(#)linkaddr.c 8.1 (Berkeley) 6/4/93";
39#else
40static char rcsid[] = "$NetBSD: linkaddr.c,v 1.5 1995/02/25 06:20:49 cgd Exp $";
41#endif
42#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
43 37
44#include <sys/types.h> 38#include <sys/types.h>
diff --git a/src/lib/libc/net/net_addrcmp.3 b/src/lib/libc/net/net_addrcmp.3
new file mode 100644
index 0000000000..f1ce4c8cd1
--- /dev/null
+++ b/src/lib/libc/net/net_addrcmp.3
@@ -0,0 +1,91 @@
1.\" $OpenBSD: net_addrcmp.3,v 1.3 2001/08/07 06:53:27 deraadt Exp $
2.\"
3.\" Copyright (c) 1999 Theo de Raadt
4.\"
5.\" Redistribution and use in source and binary forms, with or without
6.\" modification, are permitted provided that the following conditions
7.\" are met:
8.\" 1. Redistributions of source code must retain the above copyright
9.\" notice, this list of conditions and the following disclaimer.
10.\" 2. Redistributions in binary form must reproduce the above copyright
11.\" notice, this list of conditions and the following disclaimer in the
12.\" documentation and/or other materials provided with the distribution.
13.\"
14.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24.\"
25.Dd July 3, 1999
26.Dt NET_ADDRCMP 3
27.Os
28.Sh NAME
29.Nm net_addrcmp
30.Nd compare socket address structures
31.Sh SYNOPSIS
32.Fd #include <netdb.h>
33.Ft int
34.Fn net_addrcmp "struct sockaddr *sa1" "struct sockaddr *sa2"
35.Sh DESCRIPTION
36The
37.Fn net_addrcmp
38function compares two socket address structures,
39.Fa sa1
40and
41.Fa sa2 .
42.Sh RETURN VALUES
43If
44.Fa sa1
45and
46.Fa sa2
47are for the same address,
48.Fn net_addrcmp
49returns 0.
50.Pp
51The
52.Fa sa_len
53fields are compared first.
54If they do not match,
55.Fn net_addrcmp
56returns \-1 or 1 if
57.Li sa1->sa_len
58is less than or greater than
59.Li sa2->sa_len ,
60respectively.
61.Pp
62Next, the
63.Fa sa_family
64members are compared.
65If they do not match,
66.Fn net_addrcmp
67returns \-1 or 1 if
68.Li sa1->sa_family
69is less than or greater than
70.Li sa2->sa_family ,
71respectively.
72.Pp
73Lastly, if each socket address structure's
74.Fa sa_len
75and
76.Fa sa_family
77fields match,
78the protocol-specific data (the
79.Fa sa_data
80field) is compared.
81If there's a match, both
82.Fa sa1
83and
84.Fa sa2
85must refer to the same address, and 0 is returned; otherwise, a value >0
86or <0 is returned.
87.Sh HISTORY
88A
89.Fn net_addrcmp
90function was added in
91.Ox 2.5 .
diff --git a/src/lib/libc/net/net_addrcmp.c b/src/lib/libc/net/net_addrcmp.c
new file mode 100644
index 0000000000..c77a2fda48
--- /dev/null
+++ b/src/lib/libc/net/net_addrcmp.c
@@ -0,0 +1,68 @@
1/*
2 * Copyright (c) 1999 Theo de Raadt
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include <sys/types.h>
27#include <sys/socket.h>
28#include <sys/un.h>
29#include <netinet/in.h>
30#include <netns/ns.h>
31#include <string.h>
32
33int
34net_addrcmp(sa1, sa2)
35 struct sockaddr *sa1;
36 struct sockaddr *sa2;
37{
38
39 if (sa1->sa_len != sa2->sa_len)
40 return (sa1->sa_len < sa2->sa_len) ? -1 : 1;
41 if (sa1->sa_family != sa2->sa_family)
42 return (sa1->sa_family < sa2->sa_family) ? -1 : 1;
43
44 switch(sa1->sa_family) {
45 case AF_INET:
46 return (memcmp(&((struct sockaddr_in *)sa1)->sin_addr,
47 &((struct sockaddr_in *)sa2)->sin_addr,
48 sizeof(struct in_addr)));
49 case AF_INET6:
50 if (((struct sockaddr_in6 *)sa1)->sin6_scope_id !=
51 ((struct sockaddr_in6 *)sa2)->sin6_scope_id)
52 return (((struct sockaddr_in6 *)sa1)->sin6_scope_id <
53 ((struct sockaddr_in6 *)sa2)->sin6_scope_id)
54 ? -1 : 1;
55 return memcmp(&((struct sockaddr_in6 *)sa1)->sin6_addr,
56 &((struct sockaddr_in6 *)sa2)->sin6_addr,
57 sizeof(struct in6_addr));
58 case AF_NS:
59 return (memcmp(&((struct sockaddr_ns *)sa1)->sns_addr,
60 &((struct sockaddr_ns *)sa2)->sns_addr,
61 sizeof(struct ns_addr)));
62 case AF_LOCAL:
63 return (strcmp(((struct sockaddr_un *)sa1)->sun_path,
64 ((struct sockaddr_un *)sa1)->sun_path));
65 default:
66 return -1;
67 }
68}
diff --git a/src/lib/libc/net/ns.3 b/src/lib/libc/net/ns.3
index f89b4fe042..883b079db2 100644
--- a/src/lib/libc/net/ns.3
+++ b/src/lib/libc/net/ns.3
@@ -1,4 +1,4 @@
1.\" $NetBSD: ns.3,v 1.3 1995/02/25 06:20:50 cgd Exp $ 1.\" $OpenBSD: ns.3,v 1.8 2003/05/01 19:17:37 jmc Exp $
2.\" 2.\"
3.\" Copyright (c) 1986, 1991, 1993 3.\" Copyright (c) 1986, 1991, 1993
4.\" The Regents of the University of California. All rights reserved. 4.\" The Regents of the University of California. All rights reserved.
@@ -31,11 +31,9 @@
31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32.\" SUCH DAMAGE. 32.\" SUCH DAMAGE.
33.\" 33.\"
34.\" @(#)ns.3 8.1 (Berkeley) 6/4/93
35.\"
36.Dd June 4, 1993 34.Dd June 4, 1993
37.Dt NS 3 35.Dt NS 3
38.Os BSD 4.3 36.Os
39.Sh NAME 37.Sh NAME
40.Nm ns_addr , 38.Nm ns_addr ,
41.Nm ns_ntoa 39.Nm ns_ntoa
@@ -45,7 +43,7 @@ address conversion routines
45.Sh SYNOPSIS 43.Sh SYNOPSIS
46.Fd #include <sys/types.h> 44.Fd #include <sys/types.h>
47.Fd #include <netns/ns.h> 45.Fd #include <netns/ns.h>
48.Ft struct ns_addr 46.Ft struct ns_addr
49.Fn ns_addr "char *cp" 47.Fn ns_addr "char *cp"
50.Ft char * 48.Ft char *
51.Fn ns_ntoa "struct ns_addr ns" 49.Fn ns_ntoa "struct ns_addr ns"
@@ -69,27 +67,27 @@ notation in common use in the Xerox Development Environment:
69.Ed 67.Ed
70.Pp 68.Pp
71Trailing zero fields are suppressed, and each number is printed in hexadecimal, 69Trailing zero fields are suppressed, and each number is printed in hexadecimal,
72in a format suitable for input to 70in a format suitable for input to
73.Fn ns_addr . 71.Fn ns_addr .
74Any fields lacking super-decimal digits will have a 72Any fields lacking super-decimal digits will have a
75trailing 73trailing
76.Ql H 74.Sq H
77appended. 75appended.
78.Pp 76.Pp
79Unfortunately, no universal standard exists for representing 77Unfortunately, no universal standard exists for representing
80.Tn XNS 78.Tn XNS
81addresses. 79addresses.
82An effort has been made to insure that 80An effort has been made to ensure that
83.Fn ns_addr 81.Fn ns_addr
84be compatible with most formats in common use. 82be compatible with most formats in common use.
85It will first separate an address into 1 to 3 fields using a single delimiter 83It will first separate an address into 1 to 3 fields using a single delimiter
86chosen from 84chosen from
87period 85period
88.Ql \&. , 86.Pq Ql \&. ,
89colon 87colon
90.Ql \&: 88.Pq Ql \&: ,
91or pound-sign 89or pound-sign
92.Ql \&# . 90.Ql # .
93Each field is then examined for byte separators (colon or period). 91Each field is then examined for byte separators (colon or period).
94If there are byte separators, each subfield separated is taken to be 92If there are byte separators, each subfield separated is taken to be
95a small hexadecimal number, and the entirety is taken as a network-byte-ordered 93a small hexadecimal number, and the entirety is taken as a network-byte-ordered
@@ -103,24 +101,25 @@ as hexadecimal if there is a leading
103.Ql 0x 101.Ql 0x
104(as in C), 102(as in C),
105a trailing 103a trailing
106.Ql H 104.Sq H
107(as in Mesa), or there are any super-decimal digits present. 105(as in Mesa), or there are any super-decimal digits present.
108It is interpreted as octal is there is a leading 106It is interpreted as octal if there is a leading
109.Ql 0 107.Ql 0
110and there are no super-octal digits. 108and there are no super-octal digits.
111Otherwise, it is converted as a decimal number. 109Otherwise, it is converted as a decimal number.
112.Sh RETURN VALUES 110.Sh RETURN VALUES
113None. (See 111None.
112(See
114.Sx BUGS . ) 113.Sx BUGS . )
115.Sh SEE ALSO 114.Sh SEE ALSO
116.Xr hosts 5 , 115.Xr hosts 5 ,
117.Xr networks 5 , 116.Xr networks 5
118.Sh HISTORY 117.Sh HISTORY
119The 118The
120.Fn ns_addr 119.Fn ns_addr
121and 120and
122.Fn ns_toa 121.Fn ns_toa
123functions appeared in 122functions appeared in
124.Bx 4.3 . 123.Bx 4.3 .
125.Sh BUGS 124.Sh BUGS
126The string returned by 125The string returned by
diff --git a/src/lib/libc/net/ns_addr.c b/src/lib/libc/net/ns_addr.c
index f75ddb23b7..0d1b45858f 100644
--- a/src/lib/libc/net/ns_addr.c
+++ b/src/lib/libc/net/ns_addr.c
@@ -1,5 +1,3 @@
1/* $NetBSD: ns_addr.c,v 1.5 1995/02/25 06:20:51 cgd Exp $ */
2
3/* 1/*
4 * Copyright (c) 1986, 1993 2 * Copyright (c) 1986, 1993
5 * The Regents of the University of California. All rights reserved. 3 * The Regents of the University of California. All rights reserved.
@@ -37,11 +35,7 @@
37 */ 35 */
38 36
39#if defined(LIBC_SCCS) && !defined(lint) 37#if defined(LIBC_SCCS) && !defined(lint)
40#if 0 38static char rcsid[] = "$OpenBSD: ns_addr.c,v 1.7 2002/02/16 21:27:23 millert Exp $";
41static char sccsid[] = "@(#)ns_addr.c 8.1 (Berkeley) 6/7/93";
42#else
43static char rcsid[] = "$NetBSD: ns_addr.c,v 1.5 1995/02/25 06:20:51 cgd Exp $";
44#endif
45#endif /* LIBC_SCCS and not lint */ 39#endif /* LIBC_SCCS and not lint */
46 40
47#include <sys/param.h> 41#include <sys/param.h>
@@ -51,7 +45,8 @@ static char rcsid[] = "$NetBSD: ns_addr.c,v 1.5 1995/02/25 06:20:51 cgd Exp $";
51 45
52static struct ns_addr addr, zero_addr; 46static struct ns_addr addr, zero_addr;
53 47
54static void Field(), cvtbase(); 48static void Field(char *, u_int8_t *, int);
49static void cvtbase(long, int, int[], int, u_int8_t[], int);
55 50
56struct ns_addr 51struct ns_addr
57ns_addr(name) 52ns_addr(name)
@@ -61,16 +56,15 @@ ns_addr(name)
61 char *hostname, *socketname, *cp; 56 char *hostname, *socketname, *cp;
62 char buf[50]; 57 char buf[50];
63 58
64 (void)strncpy(buf, name, sizeof(buf) - 1); 59 strlcpy(buf, name, sizeof(buf));
65 buf[sizeof(buf) - 1] = '\0';
66 60
67 /* 61 /*
68 * First, figure out what he intends as a field separtor. 62 * First, figure out what he intends as a field separtor.
69 * Despite the way this routine is written, the prefered 63 * Despite the way this routine is written, the prefered
70 * form 2-272.AA001234H.01777, i.e. XDE standard. 64 * form 2-272.AA001234H.01777, i.e. XDE standard.
71 * Great efforts are made to insure backward compatability. 65 * Great efforts are made to insure backward compatibility.
72 */ 66 */
73 if (hostname = strchr(buf, '#')) 67 if ((hostname = strchr(buf, '#')))
74 separator = '#'; 68 separator = '#';
75 else { 69 else {
76 hostname = strchr(buf, '.'); 70 hostname = strchr(buf, '.');
@@ -95,7 +89,7 @@ ns_addr(name)
95 Field(socketname, (u_char *)&addr.x_port, 2); 89 Field(socketname, (u_char *)&addr.x_port, 2);
96 } 90 }
97 91
98 Field(hostname, addr.x_host.c_host, 6); 92 Field(hostname, (u_char *)addr.x_host.c_host, 6);
99 93
100 return (addr); 94 return (addr);
101} 95}
diff --git a/src/lib/libc/net/ns_ntoa.c b/src/lib/libc/net/ns_ntoa.c
index ad3265399b..35d4f28aca 100644
--- a/src/lib/libc/net/ns_ntoa.c
+++ b/src/lib/libc/net/ns_ntoa.c
@@ -1,5 +1,3 @@
1/* $NetBSD: ns_ntoa.c,v 1.4 1995/02/25 06:20:51 cgd Exp $ */
2
3/* 1/*
4 * Copyright (c) 1986, 1993 2 * Copyright (c) 1986, 1993
5 * The Regents of the University of California. All rights reserved. 3 * The Regents of the University of California. All rights reserved.
@@ -34,73 +32,79 @@
34 */ 32 */
35 33
36#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
37#if 0 35static char rcsid[] = "$OpenBSD: ns_ntoa.c,v 1.11 2003/04/05 00:44:42 tdeval Exp $";
38static char sccsid[] = "@(#)ns_ntoa.c 8.1 (Berkeley) 6/4/93";
39#else
40static char rcsid[] = "$NetBSD: ns_ntoa.c,v 1.4 1995/02/25 06:20:51 cgd Exp $";
41#endif
42#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
43 37
44#include <sys/param.h> 38#include <sys/param.h>
45#include <netns/ns.h> 39#include <netns/ns.h>
46#include <stdio.h> 40#include <stdio.h>
47 41
42static char *spectHex(char *);
43
48char * 44char *
49ns_ntoa(addr) 45ns_ntoa(struct ns_addr addr)
50 struct ns_addr addr;
51{ 46{
52 static char obuf[40]; 47 static char obuf[40];
53 union { union ns_net net_e; u_long long_e; } net; 48 union { union ns_net net_e; u_int32_t long_e; } net;
54 u_short port = htons(addr.x_port); 49 in_port_t port = htons(addr.x_port);
55 register char *cp; 50 char *cp, *cp2;
56 char *cp2; 51 u_char *up = addr.x_host.c_host;
57 register u_char *up = addr.x_host.c_host;
58 u_char *uplim = up + 6; 52 u_char *uplim = up + 6;
59 static char *spectHex(); 53 size_t rem;
60 54
61 net.net_e = addr.x_net; 55 net.net_e = addr.x_net;
62 sprintf(obuf, "%lx", ntohl(net.long_e)); 56 snprintf(obuf, sizeof obuf, "%x", ntohl(net.long_e));
63 cp = spectHex(obuf); 57 cp = spectHex(obuf);
58 rem = sizeof(obuf) - (cp - obuf);
64 cp2 = cp + 1; 59 cp2 = cp + 1;
65 while (*up==0 && up < uplim) up++; 60 while (*up==0 && up < uplim)
61 up++;
66 if (up == uplim) { 62 if (up == uplim) {
67 if (port) { 63 if (port) {
68 sprintf(cp, ".0"); 64 snprintf(cp, rem, ".0");
69 cp += 2; 65 cp += 2;
66 rem -= 2;
70 } 67 }
71 } else { 68 } else {
72 sprintf(cp, ".%x", *up++); 69 snprintf(cp, rem, ".%x", *up++);
73 while (up < uplim) { 70 while (up < uplim) {
74 while (*cp) cp++; 71 while (*cp) {
75 sprintf(cp, "%02x", *up++); 72 cp++;
73 rem--;
74 }
75 snprintf(cp, rem, "%02x", *up++);
76 } 76 }
77 cp = spectHex(cp2); 77 cp = spectHex(cp2);
78 rem = sizeof(obuf) - (cp - obuf);
78 } 79 }
79 if (port) { 80 if (port) {
80 sprintf(cp, ".%x", port); 81 snprintf(cp, rem, ".%x", port);
81 spectHex(cp + 1); 82 spectHex(cp + 1);
82 } 83 }
83 return (obuf); 84 return (obuf);
84} 85}
85 86
86static char * 87static char *
87spectHex(p0) 88spectHex(char *p0)
88 char *p0;
89{ 89{
90 int ok = 0; 90 int ok = 0, nonzero = 0;
91 int nonzero = 0; 91 char *p = p0;
92 register char *p = p0;
93 for (; *p; p++) switch (*p) {
94 92
95 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': 93 for (; *p; p++) {
96 *p += ('A' - 'a'); 94 switch (*p) {
97 /* fall into . . . */ 95 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
98 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': 96 *p += ('A' - 'a');
99 ok = 1; 97 /* fall into . . . */
100 case '1': case '2': case '3': case '4': case '5': 98 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
101 case '6': case '7': case '8': case '9': 99 ok = 1;
102 nonzero = 1; 100 case '1': case '2': case '3': case '4': case '5':
101 case '6': case '7': case '8': case '9':
102 nonzero = 1;
103 }
104 }
105 if (nonzero && !ok) {
106 *p++ = 'H';
107 *p = 0;
103 } 108 }
104 if (nonzero && !ok) { *p++ = 'H'; *p = 0; }
105 return (p); 109 return (p);
106} 110}
diff --git a/src/lib/libc/net/nsap_addr.c b/src/lib/libc/net/nsap_addr.c
new file mode 100644
index 0000000000..22a5f8d66e
--- /dev/null
+++ b/src/lib/libc/net/nsap_addr.c
@@ -0,0 +1,109 @@
1/* $OpenBSD: nsap_addr.c,v 1.4 1997/07/09 01:08:45 millert Exp $ */
2
3/*
4 * Copyright (c) 1996 by Internet Software Consortium.
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
11 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
12 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
13 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
16 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
17 * SOFTWARE.
18 */
19
20#if defined(LIBC_SCCS) && !defined(lint)
21#if 0
22static char rcsid[] = "$From: nsap_addr.c,v 8.3 1996/08/05 08:31:35 vixie Exp $";
23#else
24static char rcsid[] = "$OpenBSD: nsap_addr.c,v 1.4 1997/07/09 01:08:45 millert Exp $";
25#endif
26#endif /* LIBC_SCCS and not lint */
27
28#include <sys/types.h>
29#include <sys/param.h>
30#include <sys/socket.h>
31#include <netinet/in.h>
32#include <arpa/nameser.h>
33#include <ctype.h>
34#include <resolv.h>
35
36static char
37xtob(c)
38 register int c;
39{
40 return (c - (((c >= '0') && (c <= '9')) ? '0' : '7'));
41}
42
43u_int
44inet_nsap_addr(ascii, binary, maxlen)
45 const char *ascii;
46 u_char *binary;
47 int maxlen;
48{
49 register u_char c, nib;
50 u_int len = 0;
51
52 while ((c = *ascii++) != '\0' && len < maxlen) {
53 if (c == '.' || c == '+' || c == '/')
54 continue;
55 if (!isascii(c))
56 return (0);
57 if (islower(c))
58 c = toupper(c);
59 if (isxdigit(c)) {
60 nib = xtob(c);
61 if ((c = *ascii++)) {
62 c = toupper(c);
63 if (isxdigit(c)) {
64 *binary++ = (nib << 4) | xtob(c);
65 len++;
66 } else
67 return (0);
68 }
69 else
70 return (0);
71 }
72 else
73 return (0);
74 }
75 return (len);
76}
77
78char *
79inet_nsap_ntoa(binlen, binary, ascii)
80 int binlen;
81 register const u_char *binary;
82 register char *ascii;
83{
84 register int nib;
85 int i;
86 static char tmpbuf[255*3];
87 char *start;
88
89 if (ascii)
90 start = ascii;
91 else {
92 ascii = tmpbuf;
93 start = tmpbuf;
94 }
95
96 if (binlen > 255)
97 binlen = 255;
98
99 for (i = 0; i < binlen; i++) {
100 nib = *binary >> 4;
101 *ascii++ = nib + (nib < 10 ? '0' : '7');
102 nib = *binary++ & 0x0f;
103 *ascii++ = nib + (nib < 10 ? '0' : '7');
104 if (((i % 2) == 0 && (i + 1) < binlen))
105 *ascii++ = '.';
106 }
107 *ascii = '\0';
108 return (start);
109}
diff --git a/src/lib/libc/net/ntohl.c b/src/lib/libc/net/ntohl.c
index 05b7f4c9a3..7d3e227e60 100644
--- a/src/lib/libc/net/ntohl.c
+++ b/src/lib/libc/net/ntohl.c
@@ -1,29 +1,25 @@
1/* $NetBSD: ntohl.c,v 1.5 1995/04/28 23:25:21 jtc Exp $ */
2
3/* 1/*
4 * Written by J.T. Conklin <jtc@netbsd.org>. 2 * Written by J.T. Conklin <jtc@netbsd.org>.
5 * Public domain. 3 * Public domain.
6 */ 4 */
7 5
8#if defined(LIBC_SCCS) && !defined(lint) 6#if defined(LIBC_SCCS) && !defined(lint)
9static char *rcsid = "$NetBSD: ntohl.c,v 1.5 1995/04/28 23:25:21 jtc Exp $"; 7static char *rcsid = "$OpenBSD: ntohl.c,v 1.4 1996/12/12 03:19:56 tholo Exp $";
10#endif 8#endif /* LIBC_SCCS and not lint */
11 9
12#include <sys/types.h> 10#include <sys/types.h>
13#include <machine/endian.h> 11#include <machine/endian.h>
14 12
15#undef ntohl 13#undef ntohl
16 14
17unsigned long 15u_int32_t
18ntohl(x) 16ntohl(x)
19 unsigned long x; 17 u_int32_t x;
20{ 18{
21 u_int32_t y = x;
22
23#if BYTE_ORDER == LITTLE_ENDIAN 19#if BYTE_ORDER == LITTLE_ENDIAN
24 u_char *s = (u_char *)&y; 20 u_char *s = (u_char *)&x;
25 return s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3]; 21 return (u_int32_t)(s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3]);
26#else 22#else
27 return y; 23 return x;
28#endif 24#endif
29} 25}
diff --git a/src/lib/libc/net/ntohs.c b/src/lib/libc/net/ntohs.c
index 93ab83ee4d..4c3ab33f31 100644
--- a/src/lib/libc/net/ntohs.c
+++ b/src/lib/libc/net/ntohs.c
@@ -1,26 +1,23 @@
1/* $NetBSD: ntohs.c,v 1.5 1995/04/28 23:25:23 jtc Exp $ */
2
3/* 1/*
4 * Written by J.T. Conklin <jtc@netbsd.org>. 2 * Written by J.T. Conklin <jtc@netbsd.org>.
5 * Public domain. 3 * Public domain.
6 */ 4 */
7 5
8#if defined(LIBC_SCCS) && !defined(lint) 6#if defined(LIBC_SCCS) && !defined(lint)
9static char *rcsid = "$NetBSD: ntohs.c,v 1.5 1995/04/28 23:25:23 jtc Exp $"; 7static char *rcsid = "$OpenBSD: ntohs.c,v 1.7 2002/02/19 19:39:36 millert Exp $";
10#endif 8#endif /* LIBC_SCCS and not lint */
11 9
12#include <sys/types.h> 10#include <sys/types.h>
13#include <machine/endian.h> 11#include <machine/endian.h>
14 12
15#undef ntohs 13#undef ntohs
16 14
17unsigned short 15u_int16_t
18ntohs(x) 16ntohs(u_int16_t x)
19 unsigned short x;
20{ 17{
21#if BYTE_ORDER == LITTLE_ENDIAN 18#if BYTE_ORDER == LITTLE_ENDIAN
22 u_char *s = (u_char *) &x; 19 u_char *s = (u_char *) &x;
23 return s[0] << 8 | s[1]; 20 return (u_int16_t)(s[0] << 8 | s[1]);
24#else 21#else
25 return x; 22 return x;
26#endif 23#endif
diff --git a/src/lib/libc/net/rcmd.3 b/src/lib/libc/net/rcmd.3
index 4db847c392..62f370efad 100644
--- a/src/lib/libc/net/rcmd.3
+++ b/src/lib/libc/net/rcmd.3
@@ -1,4 +1,4 @@
1.\" $NetBSD: rcmd.3,v 1.8 1995/02/25 06:20:52 cgd Exp $ 1.\" $OpenBSD: rcmd.3,v 1.25 2002/09/25 17:30:02 deraadt Exp $
2.\" 2.\"
3.\" Copyright (c) 1983, 1991, 1993 3.\" Copyright (c) 1983, 1991, 1993
4.\" The Regents of the University of California. All rights reserved. 4.\" The Regents of the University of California. All rights reserved.
@@ -31,38 +31,67 @@
31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32.\" SUCH DAMAGE. 32.\" SUCH DAMAGE.
33.\" 33.\"
34.\" @(#)rcmd.3 8.1 (Berkeley) 6/4/93
35.\"
36.Dd June 4, 1993 34.Dd June 4, 1993
37.Dt RCMD 3 35.Dt RCMD 3
38.Os BSD 4.2 36.Os
39.Sh NAME 37.Sh NAME
40.Nm rcmd , 38.Nm rcmd ,
39.Nm rcmd_af ,
41.Nm rresvport , 40.Nm rresvport ,
41.Nm rresvport_af ,
42.Nm iruserok , 42.Nm iruserok ,
43.Nm ruserok 43.Nm ruserok ,
44.Nm iruserok_sa
44.Nd routines for returning a stream to a remote command 45.Nd routines for returning a stream to a remote command
45.Sh SYNOPSIS 46.Sh SYNOPSIS
46.Fd #include <unistd.h> 47.Fd #include <unistd.h>
47.Ft int 48.Ft int
48.Fn rcmd "char **ahost" "int inport" "const char *locuser" "const char *remuser" "const char *cmd" "int *fd2p" 49.Fn rcmd "char **ahost" "int inport" "const char *locuser" "const char *remuser" "const char *cmd" "int *fd2p"
49.Ft int 50.Ft int
51.Fn rcmd_af "char **ahost" "int inport" "const char *locuser" "const char *remuser" "const char *cmd" "int *fd2p" "int af"
52.Ft int
50.Fn rresvport "int *port" 53.Fn rresvport "int *port"
51.Ft int 54.Ft int
52.Fn iruserok "u_long raddr" "int superuser" "const char *ruser" "const char *luser" 55.Fn rresvport_af "int *port" "int af"
56.Ft int
57.Fn iruserok "u_int32_t raddr" "int superuser" "const char *ruser" "const char *luser"
53.Ft int 58.Ft int
54.Fn ruserok "const char *rhost" "int superuser" "const char *ruser" "const char *luser" 59.Fn ruserok "const char *rhost" "int superuser" "const char *ruser" "const char *luser"
60.Ft int
61.Fn iruserok_sa "const void *sa" "int salen" "int superuser" "const char *ruser" "const char *luser"
55.Sh DESCRIPTION 62.Sh DESCRIPTION
56The 63The
57.Fn rcmd 64.Fn rcmd
58function 65function is used by the superuser to execute a command on a remote
59is used by the super-user to execute a command on 66machine using an authentication scheme based on reserved
60a remote machine using an authentication scheme based 67port numbers.
61on reserved port numbers. 68If the calling process is not setuid, the
69.Ev RSH
70environment variable is set, and
71.Fa inport
72is
73.Dq shell/tcp ,
74.Xr rcmdsh 3
75is called instead with the value of
76.Ev RSH .
77Alternately, if the user is not the superuser,
78.Fn rcmd
79will invoke
80.Xr rcmdsh 3
81to run the command via
82.Xr rsh 1 .
83While
84.Fn rcmd
85can handle IPv4 cases only,
86the
87.Fn rcmd_af
88function can handle other cases as well.
89.Pp
62The 90The
63.Fn rresvport 91.Fn rresvport
64function 92and
65returns a descriptor to a socket 93.Fn rresvport_af
94functions return a descriptor to a socket
66with an address in the privileged port space. 95with an address in the privileged port space.
67The 96The
68.Fn iruserok 97.Fn iruserok
@@ -75,11 +104,13 @@ All four functions are present in the same file and are used
75by the 104by the
76.Xr rshd 8 105.Xr rshd 8
77server (among others). 106server (among others).
107.Fn iruserok_sa
108is an address family independent variant of
109.Fn iruserok .
78.Pp 110.Pp
79The 111The
80.Fn rcmd 112.Fn rcmd
81function 113function looks up the host
82looks up the host
83.Fa *ahost 114.Fa *ahost
84using 115using
85.Xr gethostbyname 3 , 116.Xr gethostbyname 3 ,
@@ -90,15 +121,15 @@ is set to the standard name of the host
90and a connection is established to a server 121and a connection is established to a server
91residing at the well-known Internet port 122residing at the well-known Internet port
92.Fa inport . 123.Fa inport .
124If the user is not the superuser, the only valid port is
125.Dq shell/tcp
126(usually port 514).
93.Pp 127.Pp
94If the connection succeeds, 128If the connection succeeds,
95a socket in the Internet domain of type 129a socket in the Internet domain of type
96.Dv SOCK_STREAM 130.Dv SOCK_STREAM
97is returned to the caller, and given to the remote 131is returned to the caller, and given to the remote
98command as 132command as stdin and stdout.
99.Em stdin
100and
101.Em stdout .
102If 133If
103.Fa fd2p 134.Fa fd2p
104is non-zero, then an auxiliary channel to a control 135is non-zero, then an auxiliary channel to a control
@@ -113,27 +144,46 @@ signal numbers, to be
113forwarded to the process group of the command. 144forwarded to the process group of the command.
114If 145If
115.Fa fd2p 146.Fa fd2p
116is 0, then the 147is
117.Em stderr 148.Va NULL ,
118(unit 2 of the remote 149then the standard error (unit 2 of the remote command) will be made
119command) will be made the same as the 150the same as the standard output and no provision is made for sending
120.Em stdout 151arbitrary signals to the remote process, although you may be able to
121and no 152get its attention by using out-of-band data.
122provision is made for sending arbitrary signals to the remote process, 153Note that if the user is not the superuser,
123although you may be able to get its attention by using out-of-band data. 154.Fa fd2p
155must be
156.Va NULL .
157.Pp
158.Fn rcmd_af
159takes address family in the last argument.
160If the last argument is
161.Dv PF_UNSPEC ,
162interpretation of
163.Fa *ahost
164will obey the underlying address resolution like DNS.
124.Pp 165.Pp
125The protocol is described in detail in 166The protocol is described in detail in
126.Xr rshd 8 . 167.Xr rshd 8 .
127.Pp 168.Pp
128The 169The
129.Fn rresvport 170.Fn rresvport
130function is used to obtain a socket with a privileged 171and
131address bound to it. This socket is suitable for use 172.Fn rresvport_af
132by 173functions are used to obtain a socket with a privileged
174address bound to it.
175This socket is suitable for use by
133.Fn rcmd 176.Fn rcmd
134and several other functions. Privileged Internet ports are those 177and several other functions.
135in the range 0 to 1023. Only the super-user 178Privileged Internet ports are those in the range 0 to
136is allowed to bind an address of this sort to a socket. 179.Va IPPORT_RESERVED - 1 ,
180which happens to be 1023.
181Only the superuser is allowed to bind an address of this sort to a socket.
182.Fn rresvport
183and
184.Fn rresvport_af
185need to be seeded with a port number; if that port
186is not available these functions will find another.
137.Pp 187.Pp
138The 188The
139.Fn iruserok 189.Fn iruserok
@@ -141,10 +191,10 @@ and
141.Fn ruserok 191.Fn ruserok
142functions take a remote host's IP address or name, respectively, 192functions take a remote host's IP address or name, respectively,
143two user names and a flag indicating whether the local user's 193two user names and a flag indicating whether the local user's
144name is that of the super-user. 194name is that of the superuser.
145Then, if the user is 195Then, if the user is
146.Em NOT 196.Em not
147the super-user, it checks the 197the superuser, it checks the
148.Pa /etc/hosts.equiv 198.Pa /etc/hosts.equiv
149file. 199file.
150If that lookup is not done, or is unsuccessful, the 200If that lookup is not done, or is unsuccessful, the
@@ -153,19 +203,19 @@ in the local user's home directory is checked to see if the request for
153service is allowed. 203service is allowed.
154.Pp 204.Pp
155If this file does not exist, is not a regular file, is owned by anyone 205If this file does not exist, is not a regular file, is owned by anyone
156other than the user or the super-user, or is writeable by anyone other 206other than the user or the superuser, or is writeable by anyone other
157than the owner, the check automatically fails. 207than the owner, the check automatically fails.
158Zero is returned if the machine name is listed in the 208Zero is returned if the machine name is listed in the
159.Dq Pa hosts.equiv 209.Pa hosts.equiv
160file, or the host and remote user name are found in the 210file, or the host and remote user name are found in the
161.Dq Pa .rhosts 211.Pa .rhosts
162file; otherwise 212file; otherwise
163.Fn iruserok 213.Fn iruserok
164and 214and
165.Fn ruserok 215.Fn ruserok
166return \-1. 216return \-1.
167If the local domain (as obtained from 217If the local domain (as obtained from
168.Xr gethostname 2 ) 218.Xr gethostname 3 )
169is the same as the remote domain, only the machine name need be specified. 219is the same as the remote domain, only the machine name need be specified.
170.Pp 220.Pp
171If the IP address of the remote host is known, 221If the IP address of the remote host is known,
@@ -173,32 +223,48 @@ If the IP address of the remote host is known,
173should be used in preference to 223should be used in preference to
174.Fn ruserok , 224.Fn ruserok ,
175as it does not require trusting the DNS server for the remote host's domain. 225as it does not require trusting the DNS server for the remote host's domain.
226.Pp
227While
228.Fn iruserok
229can handle IPv4 addresses only,
230.Fn iruserok_sa
231and
232.Fn ruserok
233can handle other address families as well, like IPv6.
234The first argument of
235.Fn iruserok_sa
236is typed as
237.Li "void *"
238to avoid dependency between
239.Aq Pa unistd.h
240and
241.Aq Pa sys/socket.h .
176.Sh DIAGNOSTICS 242.Sh DIAGNOSTICS
177The 243The
178.Fn rcmd 244.Fn rcmd
179function 245function returns a valid socket descriptor on success.
180returns a valid socket descriptor on success.
181It returns \-1 on error and prints a diagnostic message on the standard error. 246It returns \-1 on error and prints a diagnostic message on the standard error.
182.Pp 247.Pp
183The 248The
184.Fn rresvport 249.Fn rresvport
185function 250and
186returns a valid, bound socket descriptor on success. 251.Fn rresvport_af
252functions return a valid, bound socket descriptor on success.
187It returns \-1 on error with the global value 253It returns \-1 on error with the global value
188.Va errno 254.Va errno
189set according to the reason for failure. 255set according to the reason for failure.
190The error code 256The error code
191.Dv EAGAIN 257.Er EAGAIN
192is overloaded to mean ``All network ports in use.'' 258is overloaded to mean
259.Dq all network ports in use .
193.Sh SEE ALSO 260.Sh SEE ALSO
194.Xr rlogin 1 ,
195.Xr rsh 1 , 261.Xr rsh 1 ,
196.Xr intro 2 , 262.Xr intro 2 ,
197.Xr rexec 3 , 263.Xr bindresvport 3 ,
198.Xr rexecd 8 , 264.Xr bindresvport_sa 3 ,
199.Xr rlogind 8 , 265.Xr rcmdsh 3 ,
200.Xr rshd 8 266.Xr rshd 8
201.Sh HISTORY 267.Sh HISTORY
202These 268These
203functions appeared in 269functions appeared in
204.Bx 4.2 . 270.Bx 4.2 .
diff --git a/src/lib/libc/net/rcmd.c b/src/lib/libc/net/rcmd.c
index e0310031b0..1f2e02c989 100644
--- a/src/lib/libc/net/rcmd.c
+++ b/src/lib/libc/net/rcmd.c
@@ -1,6 +1,5 @@
1/* $NetBSD: rcmd.c,v 1.12 1995/06/03 22:33:34 mycroft Exp $ */
2
3/* 1/*
2 * Copyright (c) 1995, 1996, 1998 Theo de Raadt. All rights reserved.
4 * Copyright (c) 1983, 1993, 1994 3 * Copyright (c) 1983, 1993, 1994
5 * The Regents of the University of California. All rights reserved. 4 * The Regents of the University of California. All rights reserved.
6 * 5 *
@@ -16,6 +15,7 @@
16 * must display the following acknowledgement: 15 * must display the following acknowledgement:
17 * This product includes software developed by the University of 16 * This product includes software developed by the University of
18 * California, Berkeley and its contributors. 17 * California, Berkeley and its contributors.
18 * This product includes software developed by Theo de Raadt.
19 * 4. Neither the name of the University nor the names of its contributors 19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software 20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission. 21 * without specific prior written permission.
@@ -34,11 +34,7 @@
34 */ 34 */
35 35
36#if defined(LIBC_SCCS) && !defined(lint) 36#if defined(LIBC_SCCS) && !defined(lint)
37#if 0 37static char *rcsid = "$OpenBSD: rcmd.c,v 1.45 2002/12/15 13:27:06 henning Exp $";
38static char sccsid[] = "@(#)rcmd.c 8.3 (Berkeley) 3/26/94";
39#else
40static char *rcsid = "$NetBSD: rcmd.c,v 1.12 1995/06/03 22:33:34 mycroft Exp $";
41#endif
42#endif /* LIBC_SCCS and not lint */ 38#endif /* LIBC_SCCS and not lint */
43 39
44#include <sys/param.h> 40#include <sys/param.h>
@@ -57,35 +53,90 @@ static char *rcsid = "$NetBSD: rcmd.c,v 1.12 1995/06/03 22:33:34 mycroft Exp $";
57#include <stdio.h> 53#include <stdio.h>
58#include <ctype.h> 54#include <ctype.h>
59#include <string.h> 55#include <string.h>
56#include <syslog.h>
57#include <stdlib.h>
58#include <netgroup.h>
60 59
61int __ivaliduser __P((FILE *, u_long, const char *, const char *)); 60int __ivaliduser(FILE *, in_addr_t, const char *, const char *);
62static int __icheckhost __P((u_long, const char *)); 61int __ivaliduser_sa(FILE *, struct sockaddr *, socklen_t,
62 const char *, const char *);
63static int __icheckhost(struct sockaddr *, socklen_t, const char *);
64static char *__gethostloop(struct sockaddr *, socklen_t);
63 65
64int 66int
65rcmd(ahost, rport, locuser, remuser, cmd, fd2p) 67rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
66 char **ahost; 68 char **ahost;
67 u_short rport; 69 in_port_t rport;
70 const char *locuser, *remuser, *cmd;
71 int *fd2p;
72{
73 return rcmd_af(ahost, rport, locuser, remuser, cmd, fd2p, AF_INET);
74}
75
76int
77rcmd_af(ahost, rport, locuser, remuser, cmd, fd2p, af)
78 char **ahost;
79 in_port_t rport;
68 const char *locuser, *remuser, *cmd; 80 const char *locuser, *remuser, *cmd;
69 int *fd2p; 81 int *fd2p;
82 int af;
70{ 83{
71 struct hostent *hp; 84 static char hbuf[MAXHOSTNAMELEN];
72 struct sockaddr_in sin, from; 85 char pbuf[NI_MAXSERV];
73 fd_set reads; 86 struct addrinfo hints, *res, *r;
74 long oldmask; 87 int error;
88 struct sockaddr_storage from;
89 fd_set *readsp = NULL;
90 sigset_t oldmask, mask;
75 pid_t pid; 91 pid_t pid;
76 int s, lport, timo; 92 int s, lport, timo;
77 char c; 93 char c, *p;
94 int refused;
95
96 /* call rcmdsh() with specified remote shell if appropriate. */
97 if (!issetugid() && (p = getenv("RSH")) && *p) {
98 struct servent *sp = getservbyname("shell", "tcp");
99
100 if (sp && sp->s_port == rport)
101 return (rcmdsh(ahost, rport, locuser, remuser,
102 cmd, p));
103 }
104
105 /* use rsh(1) if non-root and remote port is shell. */
106 if (geteuid()) {
107 struct servent *sp = getservbyname("shell", "tcp");
108
109 if (sp && sp->s_port == rport)
110 return (rcmdsh(ahost, rport, locuser, remuser,
111 cmd, NULL));
112 }
78 113
79 pid = getpid(); 114 pid = getpid();
80 hp = gethostbyname(*ahost); 115 snprintf(pbuf, sizeof(pbuf), "%u", ntohs(rport));
81 if (hp == NULL) { 116 memset(&hints, 0, sizeof(hints));
82 herror(*ahost); 117 hints.ai_family = af;
118 hints.ai_socktype = SOCK_STREAM;
119 hints.ai_flags = AI_CANONNAME;
120 error = getaddrinfo(*ahost, pbuf, &hints, &res);
121 if (error) {
122#if 0
123 warnx("%s: %s", *ahost, gai_strerror(error));
124#endif
83 return (-1); 125 return (-1);
84 } 126 }
85 *ahost = hp->h_name; 127 if (res->ai_canonname) {
86 oldmask = sigblock(sigmask(SIGURG)); 128 strlcpy(hbuf, res->ai_canonname, sizeof(hbuf));
129 *ahost = hbuf;
130 } else
131 ; /*XXX*/
132
133 r = res;
134 refused = 0;
135 sigemptyset(&mask);
136 sigaddset(&mask, SIGURG);
137 oldmask = sigprocmask(SIG_BLOCK, &mask, &oldmask);
87 for (timo = 1, lport = IPPORT_RESERVED - 1;;) { 138 for (timo = 1, lport = IPPORT_RESERVED - 1;;) {
88 s = rresvport(&lport); 139 s = rresvport_af(&lport, r->ai_family);
89 if (s < 0) { 140 if (s < 0) {
90 if (errno == EAGAIN) 141 if (errno == EAGAIN)
91 (void)fprintf(stderr, 142 (void)fprintf(stderr,
@@ -93,54 +144,86 @@ rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
93 else 144 else
94 (void)fprintf(stderr, "rcmd: socket: %s\n", 145 (void)fprintf(stderr, "rcmd: socket: %s\n",
95 strerror(errno)); 146 strerror(errno));
96 sigsetmask(oldmask); 147 if (r->ai_next) {
97 return (-1); 148 r = r->ai_next;
149 continue;
150 } else {
151 sigprocmask(SIG_SETMASK, &oldmask, NULL);
152 freeaddrinfo(res);
153 return (-1);
154 }
98 } 155 }
99 fcntl(s, F_SETOWN, pid); 156 fcntl(s, F_SETOWN, pid);
100 sin.sin_len = sizeof(struct sockaddr_in); 157 if (connect(s, r->ai_addr, r->ai_addrlen) >= 0)
101 sin.sin_family = hp->h_addrtype;
102 sin.sin_port = rport;
103 bcopy(hp->h_addr_list[0], &sin.sin_addr, hp->h_length);
104 if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0)
105 break; 158 break;
106 (void)close(s); 159 (void)close(s);
107 if (errno == EADDRINUSE) { 160 if (errno == EADDRINUSE) {
108 lport--; 161 lport--;
109 continue; 162 continue;
110 } 163 }
111 if (errno == ECONNREFUSED && timo <= 16) { 164 if (errno == ECONNREFUSED)
112 (void)sleep(timo); 165 refused++;
113 timo *= 2; 166 if (r->ai_next) {
114 continue;
115 }
116 if (hp->h_addr_list[1] != NULL) {
117 int oerrno = errno; 167 int oerrno = errno;
168 char hbuf[NI_MAXHOST];
169#ifdef NI_WITHSCOPEID
170 const int niflags = NI_NUMERICHOST | NI_WITHSCOPEID;
171#else
172 const int niflags = NI_NUMERICHOST;
173#endif
118 174
119 (void)fprintf(stderr, "connect to address %s: ", 175 hbuf[0] = '\0';
120 inet_ntoa(sin.sin_addr)); 176 if (getnameinfo(r->ai_addr, r->ai_addrlen,
177 hbuf, sizeof(hbuf), NULL, 0, niflags) != 0)
178 strlcpy(hbuf, "(invalid)", sizeof hbuf);
179 (void)fprintf(stderr, "connect to address %s: ", hbuf);
121 errno = oerrno; 180 errno = oerrno;
122 perror(0); 181 perror(0);
123 hp->h_addr_list++; 182 r = r->ai_next;
124 bcopy(hp->h_addr_list[0], &sin.sin_addr, hp->h_length); 183 hbuf[0] = '\0';
125 (void)fprintf(stderr, "Trying %s...\n", 184 if (getnameinfo(r->ai_addr, r->ai_addrlen,
126 inet_ntoa(sin.sin_addr)); 185 hbuf, sizeof(hbuf), NULL, 0, niflags) != 0)
186 strlcpy(hbuf, "(invalid)", sizeof hbuf);
187 (void)fprintf(stderr, "Trying %s...\n", hbuf);
188 continue;
189 }
190 if (refused && timo <= 16) {
191 (void)sleep(timo);
192 timo *= 2;
193 r = res;
194 refused = 0;
127 continue; 195 continue;
128 } 196 }
129 (void)fprintf(stderr, "%s: %s\n", hp->h_name, strerror(errno)); 197 (void)fprintf(stderr, "%s: %s\n", res->ai_canonname,
130 sigsetmask(oldmask); 198 strerror(errno));
199 sigprocmask(SIG_SETMASK, &oldmask, NULL);
200 freeaddrinfo(res);
131 return (-1); 201 return (-1);
132 } 202 }
203 /* given "af" can be PF_UNSPEC, we need the real af for "s" */
204 af = r->ai_family;
205 freeaddrinfo(res);
206#if 0
207 /*
208 * try to rresvport() to the same port. This will make rresvport()
209 * fail it's first bind, resulting in it choosing a random port.
210 */
133 lport--; 211 lport--;
212#endif
134 if (fd2p == 0) { 213 if (fd2p == 0) {
135 write(s, "", 1); 214 write(s, "", 1);
136 lport = 0; 215 lport = 0;
137 } else { 216 } else {
138 char num[8]; 217 char num[8];
139 int s2 = rresvport(&lport), s3; 218 int s2 = rresvport_af(&lport, af), s3;
140 int len = sizeof(from); 219 socklen_t len = sizeof(from);
220 int fdssize = howmany(MAX(s, s2)+1, NFDBITS) * sizeof(fd_mask);
141 221
142 if (s2 < 0) 222 if (s2 < 0)
143 goto bad; 223 goto bad;
224 readsp = (fd_set *)malloc(fdssize);
225 if (readsp == NULL)
226 goto bad;
144 listen(s2, 1); 227 listen(s2, 1);
145 (void)snprintf(num, sizeof(num), "%d", lport); 228 (void)snprintf(num, sizeof(num), "%d", lport);
146 if (write(s, num, strlen(num)+1) != strlen(num)+1) { 229 if (write(s, num, strlen(num)+1) != strlen(num)+1) {
@@ -150,12 +233,13 @@ rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
150 (void)close(s2); 233 (void)close(s2);
151 goto bad; 234 goto bad;
152 } 235 }
153 FD_ZERO(&reads); 236again:
154 FD_SET(s, &reads); 237 bzero(readsp, fdssize);
155 FD_SET(s2, &reads); 238 FD_SET(s, readsp);
239 FD_SET(s2, readsp);
156 errno = 0; 240 errno = 0;
157 if (select(MAX(s, s2) + 1, &reads, 0, 0, 0) < 1 || 241 if (select(MAX(s, s2) + 1, readsp, 0, 0, 0) < 1 ||
158 !FD_ISSET(s2, &reads)) { 242 !FD_ISSET(s2, readsp)) {
159 if (errno != 0) 243 if (errno != 0)
160 (void)fprintf(stderr, 244 (void)fprintf(stderr,
161 "rcmd: select (setting up stderr): %s\n", 245 "rcmd: select (setting up stderr): %s\n",
@@ -167,6 +251,23 @@ rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
167 goto bad; 251 goto bad;
168 } 252 }
169 s3 = accept(s2, (struct sockaddr *)&from, &len); 253 s3 = accept(s2, (struct sockaddr *)&from, &len);
254 /*
255 * XXX careful for ftp bounce attacks. If discovered, shut them
256 * down and check for the real auxiliary channel to connect.
257 */
258 switch (from.ss_family) {
259 case AF_INET:
260 case AF_INET6:
261 if (getnameinfo((struct sockaddr *)&from, len,
262 NULL, 0, num, sizeof(num), NI_NUMERICSERV) == 0 &&
263 atoi(num) != 20) {
264 break;
265 }
266 close(s3);
267 goto again;
268 default:
269 break;
270 }
170 (void)close(s2); 271 (void)close(s2);
171 if (s3 < 0) { 272 if (s3 < 0) {
172 (void)fprintf(stderr, 273 (void)fprintf(stderr,
@@ -175,13 +276,20 @@ rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
175 goto bad; 276 goto bad;
176 } 277 }
177 *fd2p = s3; 278 *fd2p = s3;
178 from.sin_port = ntohs(from.sin_port); 279 switch (from.ss_family) {
179 if (from.sin_family != AF_INET || 280 case AF_INET:
180 from.sin_port >= IPPORT_RESERVED || 281 case AF_INET6:
181 from.sin_port < IPPORT_RESERVED / 2) { 282 if (getnameinfo((struct sockaddr *)&from, len,
182 (void)fprintf(stderr, 283 NULL, 0, num, sizeof(num), NI_NUMERICSERV) != 0 ||
183 "socket: protocol failure in circuit setup.\n"); 284 (atoi(num) >= IPPORT_RESERVED ||
184 goto bad2; 285 atoi(num) < IPPORT_RESERVED / 2)) {
286 (void)fprintf(stderr,
287 "socket: protocol failure in circuit setup.\n");
288 goto bad2;
289 }
290 break;
291 default:
292 break;
185 } 293 }
186 } 294 }
187 (void)write(s, locuser, strlen(locuser)+1); 295 (void)write(s, locuser, strlen(locuser)+1);
@@ -200,47 +308,20 @@ rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
200 } 308 }
201 goto bad2; 309 goto bad2;
202 } 310 }
203 sigsetmask(oldmask); 311 sigprocmask(SIG_SETMASK, &oldmask, NULL);
312 free(readsp);
204 return (s); 313 return (s);
205bad2: 314bad2:
206 if (lport) 315 if (lport)
207 (void)close(*fd2p); 316 (void)close(*fd2p);
208bad: 317bad:
318 if (readsp)
319 free(readsp);
209 (void)close(s); 320 (void)close(s);
210 sigsetmask(oldmask); 321 sigprocmask(SIG_SETMASK, &oldmask, NULL);
211 return (-1); 322 return (-1);
212} 323}
213 324
214int
215rresvport(alport)
216 int *alport;
217{
218 struct sockaddr_in sin;
219 int s;
220
221 sin.sin_len = sizeof(struct sockaddr_in);
222 sin.sin_family = AF_INET;
223 sin.sin_addr.s_addr = INADDR_ANY;
224 s = socket(AF_INET, SOCK_STREAM, 0);
225 if (s < 0)
226 return (-1);
227 for (;;) {
228 sin.sin_port = htons((u_short)*alport);
229 if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0)
230 return (s);
231 if (errno != EADDRINUSE) {
232 (void)close(s);
233 return (-1);
234 }
235 (*alport)--;
236 if (*alport == IPPORT_RESERVED/2) {
237 (void)close(s);
238 errno = EAGAIN; /* close */
239 return (-1);
240 }
241 }
242}
243
244int __check_rhosts_file = 1; 325int __check_rhosts_file = 1;
245char *__rcmd_errstr; 326char *__rcmd_errstr;
246 327
@@ -249,21 +330,24 @@ ruserok(rhost, superuser, ruser, luser)
249 const char *rhost, *ruser, *luser; 330 const char *rhost, *ruser, *luser;
250 int superuser; 331 int superuser;
251{ 332{
252 struct hostent *hp; 333 struct addrinfo hints, *res, *r;
253 char **ap; 334 int error;
254 int i; 335
255#define MAXADDRS 35 336 memset(&hints, 0, sizeof(hints));
256 u_long addrs[MAXADDRS + 1]; 337 hints.ai_family = PF_UNSPEC;
257 338 hints.ai_socktype = SOCK_DGRAM; /*dummy*/
258 if ((hp = gethostbyname(rhost)) == NULL) 339 error = getaddrinfo(rhost, "0", &hints, &res);
340 if (error)
259 return (-1); 341 return (-1);
260 for (i = 0, ap = hp->h_addr_list; *ap && i < MAXADDRS; ++ap, ++i)
261 bcopy(*ap, &addrs[i], sizeof(addrs[i]));
262 addrs[i] = 0;
263 342
264 for (i = 0; i < MAXADDRS && addrs[i]; i++) 343 for (r = res; r; r = r->ai_next) {
265 if (iruserok(addrs[i], superuser, ruser, luser) == 0) 344 if (iruserok_sa(r->ai_addr, r->ai_addrlen, superuser, ruser,
345 luser) == 0) {
346 freeaddrinfo(res);
266 return (0); 347 return (0);
348 }
349 }
350 freeaddrinfo(res);
267 return (-1); 351 return (-1);
268} 352}
269 353
@@ -278,10 +362,28 @@ ruserok(rhost, superuser, ruser, luser)
278 */ 362 */
279int 363int
280iruserok(raddr, superuser, ruser, luser) 364iruserok(raddr, superuser, ruser, luser)
281 u_long raddr; 365 u_int32_t raddr;
282 int superuser; 366 int superuser;
283 const char *ruser, *luser; 367 const char *ruser, *luser;
284{ 368{
369 struct sockaddr_in sin;
370
371 memset(&sin, 0, sizeof(sin));
372 sin.sin_family = AF_INET;
373 sin.sin_len = sizeof(struct sockaddr_in);
374 memcpy(&sin.sin_addr, &raddr, sizeof(sin.sin_addr));
375 return iruserok_sa(&sin, sizeof(struct sockaddr_in), superuser, ruser,
376 luser);
377}
378
379int
380iruserok_sa(raddr, rlen, superuser, ruser, luser)
381 const void *raddr;
382 int rlen;
383 int superuser;
384 const char *ruser, *luser;
385{
386 struct sockaddr *sa;
285 register char *cp; 387 register char *cp;
286 struct stat sbuf; 388 struct stat sbuf;
287 struct passwd *pwd; 389 struct passwd *pwd;
@@ -290,11 +392,12 @@ iruserok(raddr, superuser, ruser, luser)
290 int first; 392 int first;
291 char pbuf[MAXPATHLEN]; 393 char pbuf[MAXPATHLEN];
292 394
395 sa = (struct sockaddr *)raddr;
293 first = 1; 396 first = 1;
294 hostf = superuser ? NULL : fopen(_PATH_HEQUIV, "r"); 397 hostf = superuser ? NULL : fopen(_PATH_HEQUIV, "r");
295again: 398again:
296 if (hostf) { 399 if (hostf) {
297 if (__ivaliduser(hostf, raddr, luser, ruser) == 0) { 400 if (__ivaliduser_sa(hostf, sa, rlen, luser, ruser) == 0) {
298 (void)fclose(hostf); 401 (void)fclose(hostf);
299 return (0); 402 return (0);
300 } 403 }
@@ -304,8 +407,7 @@ again:
304 first = 0; 407 first = 0;
305 if ((pwd = getpwnam(luser)) == NULL) 408 if ((pwd = getpwnam(luser)) == NULL)
306 return (-1); 409 return (-1);
307 (void)strcpy(pbuf, pwd->pw_dir); 410 snprintf(pbuf, sizeof pbuf, "%s/.rhosts", pwd->pw_dir);
308 (void)strcat(pbuf, "/.rhosts");
309 411
310 /* 412 /*
311 * Change effective uid while opening .rhosts. If root and 413 * Change effective uid while opening .rhosts. If root and
@@ -333,7 +435,7 @@ again:
333 else if (sbuf.st_uid && sbuf.st_uid != pwd->pw_uid) 435 else if (sbuf.st_uid && sbuf.st_uid != pwd->pw_uid)
334 cp = "bad .rhosts owner"; 436 cp = "bad .rhosts owner";
335 else if (sbuf.st_mode & (S_IWGRP|S_IWOTH)) 437 else if (sbuf.st_mode & (S_IWGRP|S_IWOTH))
336 cp = ".rhosts writeable by other than owner"; 438 cp = ".rhosts writable by other than owner";
337 /* If there were any problems, quit. */ 439 /* If there were any problems, quit. */
338 if (cp) { 440 if (cp) {
339 __rcmd_errstr = cp; 441 __rcmd_errstr = cp;
@@ -352,41 +454,63 @@ again:
352 * Returns 0 if ok, -1 if not ok. 454 * Returns 0 if ok, -1 if not ok.
353 */ 455 */
354int 456int
355__ivaliduser(hostf, raddr, luser, ruser) 457__ivaliduser(hostf, raddrl, luser, ruser)
458 FILE *hostf;
459 in_addr_t raddrl;
460 const char *luser, *ruser;
461{
462 struct sockaddr_in sin;
463
464 memset(&sin, 0, sizeof(sin));
465 sin.sin_family = AF_INET;
466 sin.sin_len = sizeof(struct sockaddr_in);
467 memcpy(&sin.sin_addr, &raddrl, sizeof(sin.sin_addr));
468 return __ivaliduser_sa(hostf, (struct sockaddr *)&sin, sin.sin_len,
469 luser, ruser);
470}
471
472int
473__ivaliduser_sa(hostf, raddr, salen, luser, ruser)
356 FILE *hostf; 474 FILE *hostf;
357 u_long raddr; 475 struct sockaddr *raddr;
476 socklen_t salen;
358 const char *luser, *ruser; 477 const char *luser, *ruser;
359{ 478{
360 register char *user, *p; 479 register char *user, *p;
361 int ch; 480 char *buf;
362 char buf[MAXHOSTNAMELEN + 128]; /* host + login */
363 const char *auser, *ahost; 481 const char *auser, *ahost;
364 int hostok, userok; 482 int hostok, userok;
365 char rhost[MAXHOSTNAMELEN]; 483 char *rhost = (char *)-1;
366 struct hostent *hp;
367 char domain[MAXHOSTNAMELEN]; 484 char domain[MAXHOSTNAMELEN];
485 size_t buflen;
368 486
369 getdomainname(domain, sizeof(domain)); 487 getdomainname(domain, sizeof(domain));
370 488
371 while (fgets(buf, sizeof(buf), hostf)) { 489 while ((buf = fgetln(hostf, &buflen))) {
372 p = buf; 490 p = buf;
373 /* Skip lines that are too long. */ 491 if (*p == '#')
374 if (strchr(p, '\n') == NULL) {
375 while ((ch = getc(hostf)) != '\n' && ch != EOF);
376 continue; 492 continue;
377 } 493 while (*p != '\n' && *p != ' ' && *p != '\t' && p < buf + buflen) {
378 while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') { 494 if (!isprint(*p))
495 goto bail;
379 *p = isupper(*p) ? tolower(*p) : *p; 496 *p = isupper(*p) ? tolower(*p) : *p;
380 p++; 497 p++;
381 } 498 }
499 if (p >= buf + buflen)
500 continue;
382 if (*p == ' ' || *p == '\t') { 501 if (*p == ' ' || *p == '\t') {
383 *p++ = '\0'; 502 *p++ = '\0';
384 while (*p == ' ' || *p == '\t') 503 while ((*p == ' ' || *p == '\t') && p < buf + buflen)
385 p++; 504 p++;
505 if (p >= buf + buflen)
506 continue;
386 user = p; 507 user = p;
387 while (*p != '\n' && *p != ' ' && 508 while (*p != '\n' && *p != ' ' &&
388 *p != '\t' && *p != '\0') 509 *p != '\t' && p < buf + buflen) {
510 if (!isprint(*p))
511 goto bail;
389 p++; 512 p++;
513 }
390 } else 514 } else
391 user = p; 515 user = p;
392 *p = '\0'; 516 *p = '\0';
@@ -397,27 +521,29 @@ __ivaliduser(hostf, raddr, luser, ruser)
397 auser = *user ? user : luser; 521 auser = *user ? user : luser;
398 ahost = buf; 522 ahost = buf;
399 523
400 if ((hp = gethostbyaddr((char *) &raddr, 524 if (strlen(ahost) >= MAXHOSTNAMELEN)
401 sizeof(raddr), AF_INET)) == NULL) { 525 continue;
402 abort();
403 return -1;
404 }
405 (void) strncpy(rhost, hp->h_name, sizeof(rhost));
406 rhost[sizeof(rhost) - 1] = '\0';
407 526
527 /*
528 * innetgr() must lookup a hostname (we do not attempt
529 * to change the semantics so that netgroups may have
530 * #.#.#.# addresses in the list.)
531 */
408 if (ahost[0] == '+') 532 if (ahost[0] == '+')
409 switch (ahost[1]) { 533 switch (ahost[1]) {
410 case '\0': 534 case '\0':
411 hostok = 1; 535 hostok = 1;
412 break; 536 break;
413
414 case '@': 537 case '@':
415 hostok = innetgr(&ahost[2], rhost, NULL, 538 if (rhost == (char *)-1)
416 domain); 539 rhost = __gethostloop(raddr, salen);
540 hostok = 0;
541 if (rhost)
542 hostok = innetgr(&ahost[2], rhost,
543 NULL, domain);
417 break; 544 break;
418
419 default: 545 default:
420 hostok = __icheckhost(raddr, &ahost[1]); 546 hostok = __icheckhost(raddr, salen, &ahost[1]);
421 break; 547 break;
422 } 548 }
423 else if (ahost[0] == '-') 549 else if (ahost[0] == '-')
@@ -425,18 +551,20 @@ __ivaliduser(hostf, raddr, luser, ruser)
425 case '\0': 551 case '\0':
426 hostok = -1; 552 hostok = -1;
427 break; 553 break;
428
429 case '@': 554 case '@':
430 hostok = -innetgr(&ahost[2], rhost, NULL, 555 if (rhost == (char *)-1)
431 domain); 556 rhost = __gethostloop(raddr, salen);
557 hostok = 0;
558 if (rhost)
559 hostok = -innetgr(&ahost[2], rhost,
560 NULL, domain);
432 break; 561 break;
433
434 default: 562 default:
435 hostok = -__icheckhost(raddr, &ahost[1]); 563 hostok = -__icheckhost(raddr, salen, &ahost[1]);
436 break; 564 break;
437 } 565 }
438 else 566 else
439 hostok = __icheckhost(raddr, ahost); 567 hostok = __icheckhost(raddr, salen, ahost);
440 568
441 569
442 if (auser[0] == '+') 570 if (auser[0] == '+')
@@ -444,14 +572,12 @@ __ivaliduser(hostf, raddr, luser, ruser)
444 case '\0': 572 case '\0':
445 userok = 1; 573 userok = 1;
446 break; 574 break;
447
448 case '@': 575 case '@':
449 userok = innetgr(&auser[2], NULL, ruser, 576 userok = innetgr(&auser[2], NULL, ruser,
450 domain); 577 domain);
451 break; 578 break;
452
453 default: 579 default:
454 userok = strcmp(ruser, &auser[1]) == 0; 580 userok = strcmp(ruser, &auser[1]) ? 0 : 1;
455 break; 581 break;
456 } 582 }
457 else if (auser[0] == '-') 583 else if (auser[0] == '-')
@@ -459,59 +585,149 @@ __ivaliduser(hostf, raddr, luser, ruser)
459 case '\0': 585 case '\0':
460 userok = -1; 586 userok = -1;
461 break; 587 break;
462
463 case '@': 588 case '@':
464 userok = -innetgr(&auser[2], NULL, ruser, 589 userok = -innetgr(&auser[2], NULL, ruser,
465 domain); 590 domain);
466 break; 591 break;
467
468 default: 592 default:
469 userok = -(strcmp(ruser, &auser[1]) == 0); 593 userok = strcmp(ruser, &auser[1]) ? 0 : -1;
470 break; 594 break;
471 } 595 }
472 else 596 else
473 userok = strcmp(ruser, auser) == 0; 597 userok = strcmp(ruser, auser) ? 0 : 1;
474 598
475 /* Check if one component did not match */ 599 /* Check if one component did not match */
476 if (hostok == 0 || userok == 0) 600 if (hostok == 0 || userok == 0)
477 continue; 601 continue;
478 602
479 /* Check if we got a forbidden pair */ 603 /* Check if we got a forbidden pair */
480 if (userok == -1 || hostok == -1) 604 if (userok <= -1 || hostok <= -1)
481 return -1; 605 return (-1);
482 606
483 /* Check if we got a valid pair */ 607 /* Check if we got a valid pair */
484 if (hostok == 1 && userok == 1) 608 if (hostok >= 1 && userok >= 1)
485 return 0; 609 return (0);
486 } 610 }
487 return -1; 611bail:
612 return (-1);
488} 613}
489 614
490/* 615/*
491 * Returns "true" if match, 0 if no match. 616 * Returns "true" if match, 0 if no match. If we do not find any
617 * semblance of an A->PTR->A loop, allow a simple #.#.#.# match to work.
618 *
619 * NI_WITHSCOPEID is useful for comparing sin6_scope_id portion
620 * if af == AF_INET6.
492 */ 621 */
493static int 622static int
494__icheckhost(raddr, lhost) 623__icheckhost(raddr, salen, lhost)
495 u_long raddr; 624 struct sockaddr *raddr;
625 socklen_t salen;
496 const char *lhost; 626 const char *lhost;
497{ 627{
498 register struct hostent *hp; 628 struct addrinfo hints, *res, *r;
499 register u_long laddr; 629 char h1[NI_MAXHOST], h2[NI_MAXHOST];
500 register char **pp; 630 int error;
631#ifdef NI_WITHSCOPEID
632 const int niflags = NI_NUMERICHOST | NI_WITHSCOPEID;
633#else
634 const int niflags = NI_NUMERICHOST;
635#endif
501 636
502 /* Try for raw ip address first. */ 637 h1[0] = '\0';
503 if (isdigit(*lhost) && (long)(laddr = inet_addr(lhost)) != -1) 638 if (getnameinfo(raddr, salen, h1, sizeof(h1), NULL, 0,
504 return (raddr == laddr); 639 niflags) != 0)
640 return (0);
505 641
506 /* Better be a hostname. */ 642 /* Resolve laddr into sockaddr */
507 if ((hp = gethostbyname(lhost)) == NULL) 643 memset(&hints, 0, sizeof(hints));
644 hints.ai_family = raddr->sa_family;
645 hints.ai_socktype = SOCK_DGRAM; /*dummy*/
646 res = NULL;
647 error = getaddrinfo(lhost, "0", &hints, &res);
648 if (error)
508 return (0); 649 return (0);
509 650
510 /* Spin through ip addresses. */ 651 /*
511 for (pp = hp->h_addr_list; *pp; ++pp) 652 * Try string comparisons between raddr and laddr.
512 if (!bcmp(&raddr, *pp, sizeof(u_long))) 653 */
654 for (r = res; r; r = r->ai_next) {
655 h2[0] = '\0';
656 if (getnameinfo(r->ai_addr, r->ai_addrlen, h2, sizeof(h2),
657 NULL, 0, niflags) != 0)
658 continue;
659 if (strcmp(h1, h2) == 0) {
660 freeaddrinfo(res);
513 return (1); 661 return (1);
662 }
663 }
514 664
515 /* No match. */ 665 /* No match. */
666 freeaddrinfo(res);
516 return (0); 667 return (0);
517} 668}
669
670/*
671 * Return the hostname associated with the supplied address.
672 * Do a reverse lookup as well for security. If a loop cannot
673 * be found, pack the result of inet_ntoa() into the string.
674 *
675 * NI_WITHSCOPEID is useful for comparing sin6_scope_id portion
676 * if af == AF_INET6.
677 */
678static char *
679__gethostloop(raddr, salen)
680 struct sockaddr *raddr;
681 socklen_t salen;
682{
683 static char remotehost[NI_MAXHOST];
684 char h1[NI_MAXHOST], h2[NI_MAXHOST];
685 struct addrinfo hints, *res, *r;
686 int error;
687#ifdef NI_WITHSCOPEID
688 const int niflags = NI_NUMERICHOST | NI_WITHSCOPEID;
689#else
690 const int niflags = NI_NUMERICHOST;
691#endif
692
693 h1[0] = remotehost[0] = '\0';
694 if (getnameinfo(raddr, salen, remotehost, sizeof(remotehost),
695 NULL, 0, NI_NAMEREQD) != 0)
696 return (NULL);
697 if (getnameinfo(raddr, salen, h1, sizeof(h1), NULL, 0,
698 niflags) != 0)
699 return (NULL);
700
701 /*
702 * Look up the name and check that the supplied
703 * address is in the list
704 */
705 memset(&hints, 0, sizeof(hints));
706 hints.ai_family = raddr->sa_family;
707 hints.ai_socktype = SOCK_DGRAM; /*dummy*/
708 hints.ai_flags = AI_CANONNAME;
709 res = NULL;
710 error = getaddrinfo(remotehost, "0", &hints, &res);
711 if (error)
712 return (NULL);
713
714 for (r = res; r; r = r->ai_next) {
715 h2[0] = '\0';
716 if (getnameinfo(r->ai_addr, r->ai_addrlen, h2, sizeof(h2),
717 NULL, 0, niflags) != 0)
718 continue;
719 if (strcmp(h1, h2) == 0) {
720 freeaddrinfo(res);
721 return (remotehost);
722 }
723 }
724
725 /*
726 * either the DNS adminstrator has made a configuration
727 * mistake, or someone has attempted to spoof us
728 */
729 syslog(LOG_NOTICE, "rcmd: address %s not listed for host %s",
730 h1, res->ai_canonname ? res->ai_canonname : remotehost);
731 freeaddrinfo(res);
732 return (NULL);
733}
diff --git a/src/lib/libc/string/index.3 b/src/lib/libc/net/rcmdsh.3
index 847b03628b..e993d2c9d5 100644
--- a/src/lib/libc/string/index.3
+++ b/src/lib/libc/net/rcmdsh.3
@@ -1,8 +1,8 @@
1.\" Copyright (c) 1990, 1991 The Regents of the University of California. 1.\" $OpenBSD: rcmdsh.3,v 1.9 2003/05/05 22:13:03 millert Exp $
2.\" All rights reserved. 2.\"
3.\" Copyright (c) 1983, 1991, 1993
4.\" The Regents of the University of California. All rights reserved.
3.\" 5.\"
4.\" This code is derived from software contributed to Berkeley by
5.\" Chris Torek.
6.\" Redistribution and use in source and binary forms, with or without 6.\" Redistribution and use in source and binary forms, with or without
7.\" modification, are permitted provided that the following conditions 7.\" modification, are permitted provided that the following conditions
8.\" are met: 8.\" are met:
@@ -31,53 +31,70 @@
31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32.\" SUCH DAMAGE. 32.\" SUCH DAMAGE.
33.\" 33.\"
34.\" from: @(#)index.3 5.3 (Berkeley) 4/19/91 34.Dd May 5, 2003
35.\" $Id: index.3,v 1.1.1.1 1995/10/18 08:42:21 deraadt Exp $ 35.Dt RCMDSH 3
36.\"
37.Dd April 19, 1991
38.Dt INDEX 3
39.Os 36.Os
40.Sh NAME 37.Sh NAME
41.Nm index 38.Nm rcmdsh
42.Nd locate character in string 39.Nd return a stream to a remote command without superuser
43.Sh SYNOPSIS 40.Sh SYNOPSIS
44.Fd #include <string.h> 41.Fd #include <unistd.h>
45.Ft char * 42.Ft int
46.Fn index "const char *s" "int c" 43.Fn rcmdsh "char **ahost" "int inport" "const char *locuser" "const char *remuser" "const char *cmd" "char *rshprog"
47.Sh DESCRIPTION 44.Sh DESCRIPTION
48The 45The
49.Fn index 46.Fn rcmdsh
50function 47function is used by normal users to execute a command on a remote machine
51locates the first character matching 48using an authentication scheme based on reserved port numbers using
52.Fa c 49.Xr rsh 1
53(converted to a 50or the value of
54.Em char ) 51.Fa rshprog
55in the null-terminated string 52(if non-null).
56.Fa s . 53.Fa rshprog
57.Sh RETURN VALUES 54may be a fully-qualified path, a non-qualified command, or a command containing
58The character 55space-separated command line arguments.
59.Fa c 56.Pp
60is returned if it is found; otherwise 57The
61.Dv NULL 58.Fn rcmdsh
62is returned. 59function looks up the host
63If 60.Fa *ahost
64.Fa c 61using
65is '\e0', 62.Xr gethostbyname 3 ,
66.Fn index 63returning \-1 if the host does not exist.
67locates the terminating '\e0'. 64Otherwise
65.Fa *ahost
66is set to the standard name of the host and a connection is established to
67a server residing at the well-known Internet port
68.Li shell/tcp
69(or whatever port is used by
70.Fa rshprog ) .
71The parameter
72.Fa inport
73is ignored; it is only included to provide an interface similar to
74.Xr rcmd 3 .
75.Pp
76If the connection succeeds, a socket in the
77.Tn UNIX
78domain of type
79.Dv SOCK_STREAM
80is returned to the caller, and given to the remote
81command as stdin and stdout, and stderr.
82.Sh DIAGNOSTICS
83The
84.Fn rcmdsh
85function returns a valid socket descriptor on success.
86It returns \-1 on error and prints a diagnostic message on the standard error.
68.Sh SEE ALSO 87.Sh SEE ALSO
69.Xr memchr 3 , 88.Xr rsh 1 ,
70.Xr rindex 3 , 89.Xr socketpair 2 ,
71.Xr strchr 3 , 90.Xr rcmd 3 ,
72.Xr strcspn 3 , 91.Xr rshd 8
73.Xr strpbrk 3 , 92.Sh BUGS
74.Xr strrchr 3 , 93If
75.Xr strsep 3 , 94.Xr rsh 1
76.Xr strspn 3 , 95encounters an error, a file descriptor is still returned instead of \-1.
77.Xr strstr 3 ,
78.Xr strtok 3
79.Sh HISTORY 96.Sh HISTORY
80A 97The
81.Fn index 98.Fn rcmdsh
82function appeared in 99function first appeared in
83.At v6 . 100.Ox 2.0 .
diff --git a/src/lib/libc/net/rcmdsh.c b/src/lib/libc/net/rcmdsh.c
new file mode 100644
index 0000000000..2a2a5d77fe
--- /dev/null
+++ b/src/lib/libc/net/rcmdsh.c
@@ -0,0 +1,192 @@
1/* $OpenBSD: rcmdsh.c,v 1.8 2003/05/05 22:13:03 millert Exp $ */
2
3/*
4 * Copyright (c) 2001, MagniComp
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the MagniComp nor the names of its contributors may
16 * be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
28 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31/*
32 * This is an rcmd() replacement originally by
33 * Chris Siebenmann <cks@utcc.utoronto.ca>.
34 */
35
36#if defined(LIBC_SCCS) && !defined(lint)
37static char *rcsid = "$OpenBSD: rcmdsh.c,v 1.8 2003/05/05 22:13:03 millert Exp $";
38#endif /* LIBC_SCCS and not lint */
39
40#include <sys/types.h>
41#include <sys/socket.h>
42#include <sys/wait.h>
43#include <signal.h>
44#include <errno.h>
45#include <netdb.h>
46#include <stdio.h>
47#include <stdlib.h>
48#include <string.h>
49#include <pwd.h>
50#include <paths.h>
51#include <unistd.h>
52
53/*
54 * This is a replacement rcmd() function that uses the rsh(1)
55 * program in place of a direct rcmd(3) function call so as to
56 * avoid having to be root. Note that rport is ignored.
57 */
58/* ARGSUSED */
59int
60rcmdsh(ahost, rport, locuser, remuser, cmd, rshprog)
61 char **ahost;
62 int rport;
63 const char *locuser, *remuser, *cmd;
64 char *rshprog;
65{
66 struct hostent *hp;
67 int sp[2];
68 pid_t cpid;
69 char *p;
70 struct passwd *pw;
71
72 /* What rsh/shell to use. */
73 if (rshprog == NULL)
74 rshprog = _PATH_RSH;
75
76 /* locuser must exist on this host. */
77 if ((pw = getpwnam(locuser)) == NULL) {
78 (void) fprintf(stderr, "rcmdsh: unknown user: %s\n", locuser);
79 return(-1);
80 }
81
82 /* Validate remote hostname. */
83 if (strcmp(*ahost, "localhost") != 0) {
84 if ((hp = gethostbyname(*ahost)) == NULL) {
85 herror(*ahost);
86 return(-1);
87 }
88 *ahost = hp->h_name;
89 }
90
91 /* Get a socketpair we'll use for stdin and stdout. */
92 if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, sp) < 0) {
93 perror("rcmdsh: socketpair");
94 return(-1);
95 }
96
97 cpid = fork();
98 if (cpid < 0) {
99 perror("rcmdsh: fork failed");
100 return(-1);
101 } else if (cpid == 0) {
102 /*
103 * Child. We use sp[1] to be stdin/stdout, and close sp[0].
104 */
105 (void) close(sp[0]);
106 if (dup2(sp[1], 0) < 0 || dup2(0, 1) < 0) {
107 perror("rcmdsh: dup2 failed");
108 _exit(255);
109 }
110 /* Fork again to lose parent. */
111 cpid = fork();
112 if (cpid < 0) {
113 perror("rcmdsh: fork to lose parent failed");
114 _exit(255);
115 }
116 if (cpid > 0)
117 _exit(0);
118
119 /* In grandchild here. Become local user for rshprog. */
120 if (setuid(pw->pw_uid)) {
121 (void) fprintf(stderr, "rcmdsh: setuid(%u): %s\n",
122 pw->pw_uid, strerror(errno));
123 _exit(255);
124 }
125
126 /*
127 * If remote host is "localhost" and local and remote user
128 * are the same, avoid running remote shell for efficiency.
129 */
130 if (!strcmp(*ahost, "localhost") && !strcmp(locuser, remuser)) {
131 char *argv[4];
132 if (pw->pw_shell[0] == '\0')
133 rshprog = _PATH_BSHELL;
134 else
135 rshprog = pw->pw_shell;
136 p = strrchr(rshprog, '/');
137 argv[0] = p ? p + 1 : rshprog;
138 argv[1] = "-c";
139 argv[2] = (char *)cmd;
140 argv[3] = NULL;
141 execvp(rshprog, argv);
142 } else if ((p = strchr(rshprog, ' ')) == NULL) {
143 /* simple case */
144 char *argv[6];
145 p = strrchr(rshprog, '/');
146 argv[0] = p ? p + 1 : rshprog;
147 argv[1] = "-l";
148 argv[2] = (char *)remuser;
149 argv[3] = *ahost;
150 argv[4] = (char *)cmd;
151 argv[5] = NULL;
152 execvp(rshprog, argv);
153 } else {
154 /* must pull args out of rshprog and dyn alloc argv */
155 char **argv, **ap;
156 int n;
157 for (n = 7; (p = strchr(++p, ' ')) != NULL; n++)
158 continue;
159 rshprog = strdup(rshprog);
160 ap = argv = malloc(sizeof(char *) * n);
161 if (rshprog == NULL || argv == NULL) {
162 perror("rcmdsh");
163 _exit(255);
164 }
165 while ((p = strsep(&rshprog, " ")) != NULL) {
166 if (*p == '\0')
167 continue;
168 *ap++ = p;
169 }
170 if (ap != argv) /* all spaces?!? */
171 rshprog = argv[0];
172 if ((p = strrchr(argv[0], '/')) != NULL)
173 argv[0] = p + 1;
174 *ap++ = "-l";
175 *ap++ = (char *)remuser;
176 *ap++ = *ahost;
177 *ap++ = (char *)cmd;
178 *ap++ = NULL;
179 execvp(rshprog, argv);
180 }
181 (void) fprintf(stderr, "rcmdsh: execvp %s failed: %s\n",
182 rshprog, strerror(errno));
183 _exit(255);
184 } else {
185 /* Parent. close sp[1], return sp[0]. */
186 (void) close(sp[1]);
187 /* Reap child. */
188 (void) wait(NULL);
189 return(sp[0]);
190 }
191 /* NOTREACHED */
192}
diff --git a/src/lib/libc/net/recv.c b/src/lib/libc/net/recv.c
index 44296378cb..d209a07213 100644
--- a/src/lib/libc/net/recv.c
+++ b/src/lib/libc/net/recv.c
@@ -1,5 +1,3 @@
1/* $NetBSD: recv.c,v 1.6 1995/02/25 06:20:54 cgd Exp $ */
2
3/* 1/*
4 * Copyright (c) 1988, 1993 2 * Copyright (c) 1988, 1993
5 * The Regents of the University of California. All rights reserved. 3 * The Regents of the University of California. All rights reserved.
@@ -34,11 +32,7 @@
34 */ 32 */
35 33
36#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
37#if 0 35static char rcsid[] = "$OpenBSD: recv.c,v 1.2 1996/08/19 08:29:40 tholo Exp $";
38static char sccsid[] = "@(#)recv.c 8.2 (Berkeley) 2/21/94";
39#else
40static char rcsid[] = "$NetBSD: recv.c,v 1.6 1995/02/25 06:20:54 cgd Exp $";
41#endif
42#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
43 37
44#include <sys/types.h> 38#include <sys/types.h>
diff --git a/src/lib/libc/net/res_comp.c b/src/lib/libc/net/res_comp.c
index 9d7bbecdda..25e196b2cf 100644
--- a/src/lib/libc/net/res_comp.c
+++ b/src/lib/libc/net/res_comp.c
@@ -1,9 +1,11 @@
1/* $NetBSD: res_comp.c,v 1.6 1995/02/25 06:20:55 cgd Exp $ */ 1/* $OpenBSD: res_comp.c,v 1.10 2002/02/19 19:39:36 millert Exp $ */
2 2
3/*- 3/*
4 * ++Copyright++ 1985, 1993
5 * -
4 * Copyright (c) 1985, 1993 6 * Copyright (c) 1985, 1993
5 * The Regents of the University of California. All rights reserved. 7 * The Regents of the University of California. All rights reserved.
6 * 8 *
7 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
9 * are met: 11 * are met:
@@ -14,12 +16,12 @@
14 * documentation and/or other materials provided with the distribution. 16 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software 17 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement: 18 * must display the following acknowledgement:
17 * This product includes software developed by the University of 19 * This product includes software developed by the University of
18 * California, Berkeley and its contributors. 20 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors 21 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software 22 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission. 23 * without specific prior written permission.
22 * 24 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -56,19 +58,25 @@
56#if defined(LIBC_SCCS) && !defined(lint) 58#if defined(LIBC_SCCS) && !defined(lint)
57#if 0 59#if 0
58static char sccsid[] = "@(#)res_comp.c 8.1 (Berkeley) 6/4/93"; 60static char sccsid[] = "@(#)res_comp.c 8.1 (Berkeley) 6/4/93";
59static char rcsid[] = "$Id: res_comp.c,v 4.9.1.1 1993/05/02 22:43:03 vixie Rel "; 61static char rcsid[] = "$From: res_comp.c,v 8.11 1996/12/02 09:17:22 vixie Exp $";
60#else 62#else
61static char rcsid[] = "$NetBSD: res_comp.c,v 1.6 1995/02/25 06:20:55 cgd Exp $"; 63static char rcsid[] = "$OpenBSD: res_comp.c,v 1.10 2002/02/19 19:39:36 millert Exp $";
62#endif 64#endif
63#endif /* LIBC_SCCS and not lint */ 65#endif /* LIBC_SCCS and not lint */
64 66
67#include <sys/types.h>
65#include <sys/param.h> 68#include <sys/param.h>
66#include <arpa/nameser.h>
67#include <netinet/in.h> 69#include <netinet/in.h>
68#include <resolv.h> 70#include <arpa/nameser.h>
71
69#include <stdio.h> 72#include <stdio.h>
73#include <resolv.h>
74#include <ctype.h>
75
76#include <unistd.h>
77#include <string.h>
70 78
71static int dn_find(); 79static int dn_find(u_char *, u_char *, u_char **, u_char **);
72 80
73/* 81/*
74 * Expand compressed domain name 'comp_dn' to full domain name. 82 * Expand compressed domain name 'comp_dn' to full domain name.
@@ -77,23 +85,27 @@ static int dn_find();
77 * 'exp_dn' is a pointer to a buffer of size 'length' for the result. 85 * 'exp_dn' is a pointer to a buffer of size 'length' for the result.
78 * Return size of compressed name or -1 if there was an error. 86 * Return size of compressed name or -1 if there was an error.
79 */ 87 */
88int
80dn_expand(msg, eomorig, comp_dn, exp_dn, length) 89dn_expand(msg, eomorig, comp_dn, exp_dn, length)
81 const u_char *msg, *eomorig, *comp_dn; 90 const u_char *msg, *eomorig, *comp_dn;
82 u_char *exp_dn; 91 char *exp_dn;
83 int length; 92 int length;
84{ 93{
85 register u_char *cp, *dn; 94 register const u_char *cp;
95 register char *dn;
86 register int n, c; 96 register int n, c;
87 u_char *eom; 97 char *eom;
88 int len = -1, checked = 0; 98 int len = -1, checked = 0;
89 99
90 dn = exp_dn; 100 dn = exp_dn;
91 cp = (u_char *)comp_dn; 101 cp = comp_dn;
102 if (length > MAXHOSTNAMELEN-1)
103 length = MAXHOSTNAMELEN-1;
92 eom = exp_dn + length; 104 eom = exp_dn + length;
93 /* 105 /*
94 * fetch next label in domain name 106 * fetch next label in domain name
95 */ 107 */
96 while (n = *cp++) { 108 while ((n = *cp++)) {
97 /* 109 /*
98 * Check for indirection 110 * Check for indirection
99 */ 111 */
@@ -108,23 +120,23 @@ dn_expand(msg, eomorig, comp_dn, exp_dn, length)
108 return (-1); 120 return (-1);
109 checked += n + 1; 121 checked += n + 1;
110 while (--n >= 0) { 122 while (--n >= 0) {
111 if ((c = *cp++) == '.') { 123 if (((c = *cp++) == '.') || (c == '\\')) {
112 if (dn + n + 2 >= eom) 124 if (dn + n + 2 >= eom)
113 return (-1); 125 return (-1);
114 *dn++ = '\\'; 126 *dn++ = '\\';
115 } 127 }
116 *dn++ = c; 128 *dn++ = c;
117 if (cp >= eomorig) /* out of range */ 129 if (cp >= eomorig) /* out of range */
118 return(-1); 130 return (-1);
119 } 131 }
120 break; 132 break;
121 133
122 case INDIR_MASK: 134 case INDIR_MASK:
123 if (len < 0) 135 if (len < 0)
124 len = cp - comp_dn + 1; 136 len = cp - comp_dn + 1;
125 cp = (u_char *)msg + (((n & 0x3f) << 8) | (*cp & 0xff)); 137 cp = msg + (((n & 0x3f) << 8) | (*cp & 0xff));
126 if (cp < msg || cp >= eomorig) /* out of range */ 138 if (cp < msg || cp >= eomorig) /* out of range */
127 return(-1); 139 return (-1);
128 checked += 2; 140 checked += 2;
129 /* 141 /*
130 * Check for loops in the compressed name; 142 * Check for loops in the compressed name;
@@ -157,8 +169,9 @@ dn_expand(msg, eomorig, comp_dn, exp_dn, length)
157 * If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr' 169 * If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr'
158 * is NULL, we don't update the list. 170 * is NULL, we don't update the list.
159 */ 171 */
172int
160dn_comp(exp_dn, comp_dn, length, dnptrs, lastdnptr) 173dn_comp(exp_dn, comp_dn, length, dnptrs, lastdnptr)
161 const u_char *exp_dn; 174 const char *exp_dn;
162 u_char *comp_dn, **dnptrs, **lastdnptr; 175 u_char *comp_dn, **dnptrs, **lastdnptr;
163 int length; 176 int length;
164{ 177{
@@ -170,6 +183,7 @@ dn_comp(exp_dn, comp_dn, length, dnptrs, lastdnptr)
170 dn = (u_char *)exp_dn; 183 dn = (u_char *)exp_dn;
171 cp = comp_dn; 184 cp = comp_dn;
172 eob = cp + length; 185 eob = cp + length;
186 lpp = cpp = NULL;
173 if (dnptrs != NULL) { 187 if (dnptrs != NULL) {
174 if ((msg = *dnptrs++) != NULL) { 188 if ((msg = *dnptrs++) != NULL) {
175 for (cpp = dnptrs; *cpp != NULL; cpp++) 189 for (cpp = dnptrs; *cpp != NULL; cpp++)
@@ -235,13 +249,14 @@ dn_comp(exp_dn, comp_dn, length, dnptrs, lastdnptr)
235/* 249/*
236 * Skip over a compressed domain name. Return the size or -1. 250 * Skip over a compressed domain name. Return the size or -1.
237 */ 251 */
252int
238__dn_skipname(comp_dn, eom) 253__dn_skipname(comp_dn, eom)
239 const u_char *comp_dn, *eom; 254 const u_char *comp_dn, *eom;
240{ 255{
241 register u_char *cp; 256 register const u_char *cp;
242 register int n; 257 register int n;
243 258
244 cp = (u_char *)comp_dn; 259 cp = comp_dn;
245 while (cp < eom && (n = *cp++)) { 260 while (cp < eom && (n = *cp++)) {
246 /* 261 /*
247 * check for indirection 262 * check for indirection
@@ -259,10 +274,19 @@ __dn_skipname(comp_dn, eom)
259 break; 274 break;
260 } 275 }
261 if (cp > eom) 276 if (cp > eom)
262 return -1; 277 return (-1);
263 return (cp - comp_dn); 278 return (cp - comp_dn);
264} 279}
265 280
281static int
282mklower(ch)
283 register int ch;
284{
285 if (isascii(ch) && isupper(ch))
286 return (tolower(ch));
287 return (ch);
288}
289
266/* 290/*
267 * Search for expanded name from a list of previously compressed names. 291 * Search for expanded name from a list of previously compressed names.
268 * Return the offset from msg if found or -1. 292 * Return the offset from msg if found or -1.
@@ -281,7 +305,7 @@ dn_find(exp_dn, msg, dnptrs, lastdnptr)
281 for (cpp = dnptrs; cpp < lastdnptr; cpp++) { 305 for (cpp = dnptrs; cpp < lastdnptr; cpp++) {
282 dn = exp_dn; 306 dn = exp_dn;
283 sp = cp = *cpp; 307 sp = cp = *cpp;
284 while (n = *cp++) { 308 while ((n = *cp++)) {
285 /* 309 /*
286 * check for indirection 310 * check for indirection
287 */ 311 */
@@ -292,7 +316,7 @@ dn_find(exp_dn, msg, dnptrs, lastdnptr)
292 goto next; 316 goto next;
293 if (*dn == '\\') 317 if (*dn == '\\')
294 dn++; 318 dn++;
295 if (*dn++ != *cp++) 319 if (mklower(*dn++) != mklower(*cp++))
296 goto next; 320 goto next;
297 } 321 }
298 if ((n = *dn++) == '\0' && *cp == '\0') 322 if ((n = *dn++) == '\0' && *cp == '\0')
@@ -301,11 +325,12 @@ dn_find(exp_dn, msg, dnptrs, lastdnptr)
301 continue; 325 continue;
302 goto next; 326 goto next;
303 327
304 default: /* illegal type */
305 return (-1);
306
307 case INDIR_MASK: /* indirection */ 328 case INDIR_MASK: /* indirection */
308 cp = msg + (((n & 0x3f) << 8) | *cp); 329 cp = msg + (((n & 0x3f) << 8) | *cp);
330 break;
331
332 default: /* illegal type */
333 return (-1);
309 } 334 }
310 } 335 }
311 if (*dn == '\0') 336 if (*dn == '\0')
@@ -316,16 +341,124 @@ dn_find(exp_dn, msg, dnptrs, lastdnptr)
316} 341}
317 342
318/* 343/*
319 * Routines to insert/extract short/long's. Must account for byte 344 * Verify that a domain name uses an acceptable character set.
320 * order and non-alignment problems. This code at least has the 345 */
321 * advantage of being portable. 346
322 * 347/*
323 * used by sendmail. 348 * Note the conspicuous absence of ctype macros in these definitions. On
349 * non-ASCII hosts, we can't depend on string literals or ctype macros to
350 * tell us anything about network-format data. The rest of the BIND system
351 * is not careful about this, but for some reason, we're doing it right here.
324 */ 352 */
353#define PERIOD 0x2e
354#define hyphenchar(c) ((c) == 0x2d)
355#define bslashchar(c) ((c) == 0x5c)
356#define periodchar(c) ((c) == PERIOD)
357#define asterchar(c) ((c) == 0x2a)
358#define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) \
359 || ((c) >= 0x61 && (c) <= 0x7a))
360#define digitchar(c) ((c) >= 0x30 && (c) <= 0x39)
361
362#define borderchar(c) (alphachar(c) || digitchar(c))
363#define middlechar(c) (borderchar(c) || hyphenchar(c))
364#define domainchar(c) ((c) > 0x20 && (c) < 0x7f)
365
366int
367res_hnok(dn)
368 const char *dn;
369{
370 int pch = PERIOD, ch = *dn++;
325 371
326u_short 372 while (ch != '\0') {
373 int nch = *dn++;
374
375 if (periodchar(ch)) {
376 ;
377 } else if (periodchar(pch)) {
378 if (!borderchar(ch))
379 return (0);
380 } else if (periodchar(nch) || nch == '\0') {
381 if (!borderchar(ch))
382 return (0);
383 } else {
384 if (!middlechar(ch))
385 return (0);
386 }
387 pch = ch, ch = nch;
388 }
389 return (1);
390}
391
392/*
393 * hostname-like (A, MX, WKS) owners can have "*" as their first label
394 * but must otherwise be as a host name.
395 */
396int
397res_ownok(dn)
398 const char *dn;
399{
400 if (asterchar(dn[0])) {
401 if (periodchar(dn[1]))
402 return (res_hnok(dn+2));
403 if (dn[1] == '\0')
404 return (1);
405 }
406 return (res_hnok(dn));
407}
408
409/*
410 * SOA RNAMEs and RP RNAMEs can have any printable character in their first
411 * label, but the rest of the name has to look like a host name.
412 */
413int
414res_mailok(dn)
415 const char *dn;
416{
417 int ch, escaped = 0;
418
419 /* "." is a valid missing representation */
420 if (*dn == '\0')
421 return(1);
422
423 /* otherwise <label>.<hostname> */
424 while ((ch = *dn++) != '\0') {
425 if (!domainchar(ch))
426 return (0);
427 if (!escaped && periodchar(ch))
428 break;
429 if (escaped)
430 escaped = 0;
431 else if (bslashchar(ch))
432 escaped = 1;
433 }
434 if (periodchar(ch))
435 return (res_hnok(dn));
436 return(0);
437}
438
439/*
440 * This function is quite liberal, since RFC 1034's character sets are only
441 * recommendations.
442 */
443int
444res_dnok(dn)
445 const char *dn;
446{
447 int ch;
448
449 while ((ch = *dn++) != '\0')
450 if (!domainchar(ch))
451 return (0);
452 return (1);
453}
454
455/*
456 * Routines to insert/extract short/long's.
457 */
458
459u_int16_t
327_getshort(msgp) 460_getshort(msgp)
328 register u_char *msgp; 461 register const u_char *msgp;
329{ 462{
330 register u_int16_t u; 463 register u_int16_t u;
331 464
@@ -333,9 +466,21 @@ _getshort(msgp)
333 return (u); 466 return (u);
334} 467}
335 468
469#ifdef NeXT
470/*
471 * nExt machines have some funky library conventions, which we must maintain.
472 */
473u_int16_t
474res_getshort(msgp)
475 register const u_char *msgp;
476{
477 return (_getshort(msgp));
478}
479#endif
480
336u_int32_t 481u_int32_t
337_getlong(msgp) 482_getlong(msgp)
338 register u_char *msgp; 483 register const u_char *msgp;
339{ 484{
340 register u_int32_t u; 485 register u_int32_t u;
341 486
@@ -344,13 +489,7 @@ _getlong(msgp)
344} 489}
345 490
346void 491void
347#if defined(__STDC__) || defined(__cplusplus)
348__putshort(register u_int16_t s, register u_char *msgp) 492__putshort(register u_int16_t s, register u_char *msgp)
349#else
350__putshort(s, msgp)
351 register u_int16_t s;
352 register u_char *msgp;
353#endif
354{ 493{
355 PUTSHORT(s, msgp); 494 PUTSHORT(s, msgp);
356} 495}
diff --git a/src/lib/libc/net/res_data.c b/src/lib/libc/net/res_data.c
new file mode 100644
index 0000000000..b0d19c36bb
--- /dev/null
+++ b/src/lib/libc/net/res_data.c
@@ -0,0 +1,117 @@
1/* $OpenBSD: res_data.c,v 1.1 1997/03/13 19:07:36 downsj Exp $ */
2
3/*
4 * ++Copyright++ 1995
5 * -
6 * Copyright (c) 1995
7 * The Regents of the University of California. All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by the University of
20 * California, Berkeley and its contributors.
21 * 4. Neither the name of the University nor the names of its contributors
22 * may be used to endorse or promote products derived from this software
23 * without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 * -
37 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
38 *
39 * Permission to use, copy, modify, and distribute this software for any
40 * purpose with or without fee is hereby granted, provided that the above
41 * copyright notice and this permission notice appear in all copies, and that
42 * the name of Digital Equipment Corporation not be used in advertising or
43 * publicity pertaining to distribution of the document or software without
44 * specific, written prior permission.
45 *
46 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
47 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
48 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
49 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
50 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
51 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
52 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
53 * SOFTWARE.
54 * -
55 * --Copyright--
56 */
57
58#if defined(LIBC_SCCS) && !defined(lint)
59#if 0
60static char rcsid[] = "$From: res_data.c,v 8.2 1996/08/05 08:31:35 vixie Exp $";
61#else
62static char rcsid[] = "$OpenBSD: res_data.c,v 1.1 1997/03/13 19:07:36 downsj Exp $";
63#endif
64#endif /* LIBC_SCCS and not lint */
65
66#include <sys/types.h>
67#include <sys/param.h>
68#include <sys/socket.h>
69#include <sys/time.h>
70#include <netinet/in.h>
71#include <arpa/inet.h>
72#include <arpa/nameser.h>
73
74#include <stdio.h>
75#include <ctype.h>
76#include <resolv.h>
77#include <unistd.h>
78#include <stdlib.h>
79#include <string.h>
80
81const char *_res_opcodes[] = {
82 "QUERY",
83 "IQUERY",
84 "CQUERYM",
85 "CQUERYU", /* experimental */
86 "NOTIFY", /* experimental */
87 "5",
88 "6",
89 "7",
90 "8",
91 "UPDATEA",
92 "UPDATED",
93 "UPDATEDA",
94 "UPDATEM",
95 "UPDATEMA",
96 "ZONEINIT",
97 "ZONEREF",
98};
99
100const char *_res_resultcodes[] = {
101 "NOERROR",
102 "FORMERR",
103 "SERVFAIL",
104 "NXDOMAIN",
105 "NOTIMP",
106 "REFUSED",
107 "6",
108 "7",
109 "8",
110 "9",
111 "10",
112 "11",
113 "12",
114 "13",
115 "14",
116 "NOCHANGE",
117};
diff --git a/src/lib/libc/net/res_debug.c b/src/lib/libc/net/res_debug.c
index d841293f18..b39e9a3b14 100644
--- a/src/lib/libc/net/res_debug.c
+++ b/src/lib/libc/net/res_debug.c
@@ -1,9 +1,11 @@
1/* $NetBSD: res_debug.c,v 1.7 1995/02/25 06:20:56 cgd Exp $ */ 1/* $OpenBSD: res_debug.c,v 1.16 2003/03/04 00:29:17 itojun Exp $ */
2 2
3/*- 3/*
4 * ++Copyright++ 1985, 1990, 1993
5 * -
4 * Copyright (c) 1985, 1990, 1993 6 * Copyright (c) 1985, 1990, 1993
5 * The Regents of the University of California. All rights reserved. 7 * The Regents of the University of California. All rights reserved.
6 * 8 *
7 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
9 * are met: 11 * are met:
@@ -50,174 +52,194 @@
50 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 52 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
51 * SOFTWARE. 53 * SOFTWARE.
52 * - 54 * -
55 * Portions Copyright (c) 1995 by International Business Machines, Inc.
56 *
57 * International Business Machines, Inc. (hereinafter called IBM) grants
58 * permission under its copyrights to use, copy, modify, and distribute this
59 * Software with or without fee, provided that the above copyright notice and
60 * all paragraphs of this notice appear in all copies, and that the name of IBM
61 * not be used in connection with the marketing of any product incorporating
62 * the Software or modifications thereof, without specific, written prior
63 * permission.
64 *
65 * To the extent it has a right to do so, IBM grants an immunity from suit
66 * under its patents, if any, for the use, sale or manufacture of products to
67 * the extent that such products are used for performing Domain Name System
68 * dynamic updates in TCP/IP networks by means of the Software. No immunity is
69 * granted for any product per se or for any other function of any product.
70 *
71 * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
72 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
73 * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
74 * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
75 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
76 * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
53 * --Copyright-- 77 * --Copyright--
54 */ 78 */
55 79
56#if defined(LIBC_SCCS) && !defined(lint) 80#if defined(LIBC_SCCS) && !defined(lint)
57#if 0 81#if 0
58static char sccsid[] = "@(#)res_debug.c 8.1 (Berkeley) 6/4/93"; 82static char sccsid[] = "@(#)res_debug.c 8.1 (Berkeley) 6/4/93";
83static char rcsid[] = "$From: res_debug.c,v 8.19 1996/11/26 10:11:23 vixie Exp $";
59#else 84#else
60static char rcsid[] = "$NetBSD: res_debug.c,v 1.7 1995/02/25 06:20:56 cgd Exp $"; 85static char rcsid[] = "$OpenBSD: res_debug.c,v 1.16 2003/03/04 00:29:17 itojun Exp $";
61#endif 86#endif
62#endif /* LIBC_SCCS and not lint */ 87#endif /* LIBC_SCCS and not lint */
63 88
64#include <sys/param.h> 89#include <sys/param.h>
90#include <sys/types.h>
91#include <sys/socket.h>
65#include <netinet/in.h> 92#include <netinet/in.h>
66#include <arpa/inet.h> 93#include <arpa/inet.h>
67#include <arpa/nameser.h> 94#include <arpa/nameser.h>
95
96#include <ctype.h>
97#include <netdb.h>
68#include <resolv.h> 98#include <resolv.h>
69#include <stdio.h> 99#include <stdio.h>
100#include <time.h>
101
102#include <stdlib.h>
70#include <string.h> 103#include <string.h>
71 104
72void __fp_query(); 105#include "thread_private.h"
73char *__p_class(), *__p_time(), *__p_type();
74char *p_cdname(), *p_fqname(), *p_rr();
75static char *p_option __P((u_int32_t));
76
77char *_res_opcodes[] = {
78 "QUERY",
79 "IQUERY",
80 "CQUERYM",
81 "CQUERYU",
82 "4",
83 "5",
84 "6",
85 "7",
86 "8",
87 "UPDATEA",
88 "UPDATED",
89 "UPDATEDA",
90 "UPDATEM",
91 "UPDATEMA",
92 "ZONEINIT",
93 "ZONEREF",
94};
95 106
96char *_res_resultcodes[] = { 107extern const char *_res_opcodes[];
97 "NOERROR", 108extern const char *_res_resultcodes[];
98 "FORMERR",
99 "SERVFAIL",
100 "NXDOMAIN",
101 "NOTIMP",
102 "REFUSED",
103 "6",
104 "7",
105 "8",
106 "9",
107 "10",
108 "11",
109 "12",
110 "13",
111 "14",
112 "NOCHANGE",
113};
114 109
115static char retbuf[16]; 110static const char *loc_ntoal(const u_char *binary, char *ascii, int ascii_len);
116 111
117static char * 112/* XXX: we should use getservbyport() instead. */
113static const char *
118dewks(wks) 114dewks(wks)
119 int wks; 115 int wks;
120{ 116{
117 static char nbuf[20];
118
121 switch (wks) { 119 switch (wks) {
122 case 5: return("rje"); 120 case 5: return "rje";
123 case 7: return("echo"); 121 case 7: return "echo";
124 case 9: return("discard"); 122 case 9: return "discard";
125 case 11: return("systat"); 123 case 11: return "systat";
126 case 13: return("daytime"); 124 case 13: return "daytime";
127 case 15: return("netstat"); 125 case 15: return "netstat";
128 case 17: return("qotd"); 126 case 17: return "qotd";
129 case 19: return("chargen"); 127 case 19: return "chargen";
130 case 20: return("ftp-data"); 128 case 20: return "ftp-data";
131 case 21: return("ftp"); 129 case 21: return "ftp";
132 case 23: return("telnet"); 130 case 23: return "telnet";
133 case 25: return("smtp"); 131 case 25: return "smtp";
134 case 37: return("time"); 132 case 37: return "time";
135 case 39: return("rlp"); 133 case 39: return "rlp";
136 case 42: return("name"); 134 case 42: return "name";
137 case 43: return("whois"); 135 case 43: return "whois";
138 case 53: return("domain"); 136 case 53: return "domain";
139 case 57: return("apts"); 137 case 57: return "apts";
140 case 59: return("apfs"); 138 case 59: return "apfs";
141 case 67: return("bootps"); 139 case 67: return "bootps";
142 case 68: return("bootpc"); 140 case 68: return "bootpc";
143 case 69: return("tftp"); 141 case 69: return "tftp";
144 case 77: return("rje"); 142 case 77: return "rje";
145 case 79: return("finger"); 143 case 79: return "finger";
146 case 87: return("link"); 144 case 87: return "link";
147 case 95: return("supdup"); 145 case 95: return "supdup";
148 case 100: return("newacct"); 146 case 100: return "newacct";
149 case 101: return("hostnames"); 147 case 101: return "hostnames";
150 case 102: return("iso-tsap"); 148 case 102: return "iso-tsap";
151 case 103: return("x400"); 149 case 103: return "x400";
152 case 104: return("x400-snd"); 150 case 104: return "x400-snd";
153 case 105: return("csnet-ns"); 151 case 105: return "csnet-ns";
154 case 109: return("pop-2"); 152 case 109: return "pop-2";
155 case 111: return("sunrpc"); 153 case 111: return "sunrpc";
156 case 113: return("auth"); 154 case 113: return "auth";
157 case 115: return("sftp"); 155 case 115: return "sftp";
158 case 117: return("uucp-path"); 156 case 117: return "uucp-path";
159 case 119: return("nntp"); 157 case 119: return "nntp";
160 case 121: return("erpc"); 158 case 121: return "erpc";
161 case 123: return("ntp"); 159 case 123: return "ntp";
162 case 133: return("statsrv"); 160 case 133: return "statsrv";
163 case 136: return("profile"); 161 case 136: return "profile";
164 case 144: return("NeWS"); 162 case 144: return "NeWS";
165 case 161: return("snmp"); 163 case 161: return "snmp";
166 case 162: return("snmp-trap"); 164 case 162: return "snmp-trap";
167 case 170: return("print-srv"); 165 case 170: return "print-srv";
168 default: (void) sprintf(retbuf, "%d", wks); return(retbuf); 166 default:
167 (void) snprintf(nbuf, sizeof nbuf, "%d", wks);
168 return (nbuf);
169 } 169 }
170} 170}
171 171
172static char * 172/* XXX: we should use getprotobynumber() instead. */
173static const char *
173deproto(protonum) 174deproto(protonum)
174 int protonum; 175 int protonum;
175{ 176{
177 static char nbuf[20];
178
176 switch (protonum) { 179 switch (protonum) {
177 case 1: return("icmp"); 180 case 1: return "icmp";
178 case 2: return("igmp"); 181 case 2: return "igmp";
179 case 3: return("ggp"); 182 case 3: return "ggp";
180 case 5: return("st"); 183 case 5: return "st";
181 case 6: return("tcp"); 184 case 6: return "tcp";
182 case 7: return("ucl"); 185 case 7: return "ucl";
183 case 8: return("egp"); 186 case 8: return "egp";
184 case 9: return("igp"); 187 case 9: return "igp";
185 case 11: return("nvp-II"); 188 case 11: return "nvp-II";
186 case 12: return("pup"); 189 case 12: return "pup";
187 case 16: return("chaos"); 190 case 16: return "chaos";
188 case 17: return("udp"); 191 case 17: return "udp";
189 default: (void) sprintf(retbuf, "%d", protonum); return(retbuf); 192 default:
193 (void) snprintf(nbuf, sizeof nbuf, "%d", protonum);
194 return (nbuf);
190 } 195 }
191} 196}
192 197
193static char * 198static const u_char *
194do_rrset(msg, cp, cnt, pflag, file, hs) 199do_rrset(msg, len, cp, cnt, pflag, file, hs)
195 int cnt, pflag; 200 int cnt, pflag, len;
196 char *cp,*msg, *hs; 201 const u_char *cp, *msg;
202 const char *hs;
197 FILE *file; 203 FILE *file;
198{ 204{
205 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
199 int n; 206 int n;
200 int sflag; 207 int sflag;
208
201 /* 209 /*
202 * Print answer records 210 * Print answer records.
203 */ 211 */
204 sflag = (_res.pfcode & pflag); 212 sflag = (_resp->pfcode & pflag);
205 if (n = ntohs(cnt)) { 213 if ((n = ntohs(cnt))) {
206 if ((!_res.pfcode) || ((sflag) && (_res.pfcode & RES_PRF_HEAD1))) 214 if ((!_resp->pfcode) ||
207 fprintf(file, hs); 215 ((sflag) && (_resp->pfcode & RES_PRF_HEAD1)))
216 fprintf(file, "%s", hs);
208 while (--n >= 0) { 217 while (--n >= 0) {
209 cp = p_rr(cp, msg, file); 218 if ((!_resp->pfcode) || sflag) {
210 if ((cp-msg) > PACKETSZ) 219 cp = p_rr(cp, msg, file);
220 } else {
221 unsigned int dlen;
222 cp += __dn_skipname(cp, cp + MAXCDNAME);
223 cp += INT16SZ;
224 cp += INT16SZ;
225 cp += INT32SZ;
226 dlen = _getshort((u_char*)cp);
227 cp += INT16SZ;
228 cp += dlen;
229 }
230 if ((cp - msg) > len)
211 return (NULL); 231 return (NULL);
212 } 232 }
213 if ((!_res.pfcode) || ((sflag) && (_res.pfcode & RES_PRF_HEAD1))) 233 if ((!_resp->pfcode) ||
234 ((sflag) && (_resp->pfcode & RES_PRF_HEAD1)))
214 putc('\n', file); 235 putc('\n', file);
215 } 236 }
216 return(cp); 237 return (cp);
217} 238}
218 239
240void
219__p_query(msg) 241__p_query(msg)
220 char *msg; 242 const u_char *msg;
221{ 243{
222 __fp_query(msg, stdout); 244 __fp_query(msg, stdout);
223} 245}
@@ -231,15 +253,14 @@ __fp_resstat(statp, file)
231 struct __res_state *statp; 253 struct __res_state *statp;
232 FILE *file; 254 FILE *file;
233{ 255{
234 int bit; 256 register u_long mask;
235 257
236 fprintf(file, ";; res options:"); 258 fprintf(file, ";; res options:");
237 if (!statp) 259 if (!statp)
238 statp = &_res; 260 statp = &_res;
239 for (bit = 0; bit < 32; bit++) { /* XXX 32 - bad assumption! */ 261 for (mask = 1; mask != 0; mask <<= 1)
240 if (statp->options & (1<<bit)) 262 if (statp->options & mask)
241 fprintf(file, " %s", p_option(1<<bit)); 263 fprintf(file, " %s", p_option(mask));
242 }
243 putc('\n', file); 264 putc('\n', file);
244} 265}
245 266
@@ -248,109 +269,152 @@ __fp_resstat(statp, file)
248 * This is intended to be primarily a debugging routine. 269 * This is intended to be primarily a debugging routine.
249 */ 270 */
250void 271void
251__fp_query(msg,file) 272__fp_nquery(msg, len, file)
252 char *msg; 273 const u_char *msg;
274 int len;
253 FILE *file; 275 FILE *file;
254{ 276{
255 register char *cp; 277 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
256 register HEADER *hp; 278 register const u_char *cp, *endMark;
279 register const HEADER *hp;
257 register int n; 280 register int n;
258 281
282 if ((_resp->options & RES_INIT) == 0 && res_init() == -1)
283 return;
284
285#define TruncTest(x) if (x > endMark) goto trunc
286#define ErrorTest(x) if (x == NULL) goto error
287
259 /* 288 /*
260 * Print header fields. 289 * Print header fields.
261 */ 290 */
262 hp = (HEADER *)msg; 291 hp = (HEADER *)msg;
263 cp = msg + sizeof(HEADER); 292 cp = msg + HFIXEDSZ;
264 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEADX) || hp->rcode) { 293 endMark = msg + len;
265 fprintf(file,";; ->>HEADER<<- opcode: %s, status: %s, id: %d", 294 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_HEADX) || hp->rcode) {
295 fprintf(file, ";; ->>HEADER<<- opcode: %s, status: %s, id: %u",
266 _res_opcodes[hp->opcode], 296 _res_opcodes[hp->opcode],
267 _res_resultcodes[hp->rcode], 297 _res_resultcodes[hp->rcode],
268 ntohs(hp->id)); 298 ntohs(hp->id));
269 putc('\n', file); 299 putc('\n', file);
270 } 300 }
271 putc(';', file); 301 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_HEADX))
272 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD2)) { 302 putc(';', file);
273 fprintf(file,"; flags:"); 303 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_HEAD2)) {
304 fprintf(file, "; flags:");
274 if (hp->qr) 305 if (hp->qr)
275 fprintf(file," qr"); 306 fprintf(file, " qr");
276 if (hp->aa) 307 if (hp->aa)
277 fprintf(file," aa"); 308 fprintf(file, " aa");
278 if (hp->tc) 309 if (hp->tc)
279 fprintf(file," tc"); 310 fprintf(file, " tc");
280 if (hp->rd) 311 if (hp->rd)
281 fprintf(file," rd"); 312 fprintf(file, " rd");
282 if (hp->ra) 313 if (hp->ra)
283 fprintf(file," ra"); 314 fprintf(file, " ra");
284 if (hp->pr) 315 if (hp->unused)
285 fprintf(file," pr"); 316 fprintf(file, " UNUSED-BIT-ON");
317 if (hp->ad)
318 fprintf(file, " ad");
319 if (hp->cd)
320 fprintf(file, " cd");
286 } 321 }
287 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD1)) { 322 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_HEAD1)) {
288 fprintf(file,"; Ques: %d", ntohs(hp->qdcount)); 323 fprintf(file, "; Ques: %u", ntohs(hp->qdcount));
289 fprintf(file,", Ans: %d", ntohs(hp->ancount)); 324 fprintf(file, ", Ans: %u", ntohs(hp->ancount));
290 fprintf(file,", Auth: %d", ntohs(hp->nscount)); 325 fprintf(file, ", Auth: %u", ntohs(hp->nscount));
291 fprintf(file,", Addit: %d\n", ntohs(hp->arcount)); 326 fprintf(file, ", Addit: %u", ntohs(hp->arcount));
292 } 327 }
293#if 0 328 if ((!_resp->pfcode) || (_resp->pfcode &
294 if (_res.pfcode & (RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1)) { 329 (RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) {
295 putc('\n',file); 330 putc('\n',file);
296 } 331 }
297#endif
298 /* 332 /*
299 * Print question records. 333 * Print question records.
300 */ 334 */
301 if (n = ntohs(hp->qdcount)) { 335 if ((n = ntohs(hp->qdcount))) {
302 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES)) 336 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_QUES))
303 fprintf(file,";; QUESTIONS:\n"); 337 fprintf(file, ";; QUESTIONS:\n");
304 while (--n >= 0) { 338 while (--n >= 0) {
305 fprintf(file,";;\t"); 339 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_QUES))
306 cp = p_cdname(cp, msg, file); 340 fprintf(file, ";;\t");
307 if (cp == NULL) 341 TruncTest(cp);
308 return; 342 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_QUES))
309 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES)) 343 cp = p_cdnname(cp, msg, len, file);
344 else {
345 int n;
346 char name[MAXDNAME];
347
348 if ((n = dn_expand(msg, msg+len, cp, name,
349 sizeof name)) < 0)
350 cp = NULL;
351 else
352 cp += n;
353 }
354 ErrorTest(cp);
355 TruncTest(cp);
356 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_QUES))
310 fprintf(file, ", type = %s", 357 fprintf(file, ", type = %s",
311 __p_type(_getshort(cp))); 358 __p_type(_getshort((u_char*)cp)));
312 cp += sizeof(u_int16_t); 359 cp += INT16SZ;
313 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES)) 360 TruncTest(cp);
314 fprintf(file, ", class = %s\n\n", 361 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_QUES))
315 __p_class(_getshort(cp))); 362 fprintf(file, ", class = %s\n",
316 cp += sizeof(u_int16_t); 363 __p_class(_getshort((u_char*)cp)));
364 cp += INT16SZ;
365 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_QUES))
366 putc('\n', file);
317 } 367 }
318 } 368 }
319 /* 369 /*
320 * Print authoritative answer records 370 * Print authoritative answer records
321 */ 371 */
322 cp = do_rrset(msg, cp, hp->ancount, RES_PRF_ANS, file, 372 TruncTest(cp);
373 cp = do_rrset(msg, len, cp, hp->ancount, RES_PRF_ANS, file,
323 ";; ANSWERS:\n"); 374 ";; ANSWERS:\n");
324 if (cp == NULL) 375 ErrorTest(cp);
325 return;
326 376
327 /* 377 /*
328 * print name server records 378 * print name server records
329 */ 379 */
330 cp = do_rrset(msg, cp, hp->nscount, RES_PRF_AUTH, file, 380 TruncTest(cp);
381 cp = do_rrset(msg, len, cp, hp->nscount, RES_PRF_AUTH, file,
331 ";; AUTHORITY RECORDS:\n"); 382 ";; AUTHORITY RECORDS:\n");
332 if (!cp) 383 ErrorTest(cp);
333 return;
334 384
385 TruncTest(cp);
335 /* 386 /*
336 * print additional records 387 * print additional records
337 */ 388 */
338 cp = do_rrset(msg, cp, hp->arcount, RES_PRF_ADD, file, 389 cp = do_rrset(msg, len, cp, hp->arcount, RES_PRF_ADD, file,
339 ";; ADDITIONAL RECORDS:\n"); 390 ";; ADDITIONAL RECORDS:\n");
340 if (!cp) 391 ErrorTest(cp);
341 return; 392 return;
393 trunc:
394 fprintf(file, "\n;; ...truncated\n");
395 return;
396 error:
397 fprintf(file, "\n;; ...malformed\n");
342} 398}
343 399
344char * 400void
345p_cdname(cp, msg, file) 401__fp_query(msg, file)
346 char *cp, *msg; 402 const u_char *msg;
403 FILE *file;
404{
405 fp_nquery(msg, PACKETSZ, file);
406}
407
408const u_char *
409__p_cdnname(cp, msg, len, file)
410 const u_char *cp, *msg;
411 int len;
347 FILE *file; 412 FILE *file;
348{ 413{
349 char name[MAXDNAME]; 414 char name[MAXDNAME];
350 int n; 415 int n;
351 416
352 if ((n = dn_expand((u_char *)msg, (u_char *)cp + MAXCDNAME, 417 if ((n = dn_expand(msg, msg + len, cp, name, sizeof name)) < 0)
353 (u_char *)cp, (u_char *)name, sizeof(name))) < 0)
354 return (NULL); 418 return (NULL);
355 if (name[0] == '\0') 419 if (name[0] == '\0')
356 putc('.', file); 420 putc('.', file);
@@ -359,55 +423,96 @@ p_cdname(cp, msg, file)
359 return (cp + n); 423 return (cp + n);
360} 424}
361 425
362char * 426const u_char *
363p_fqname(cp, msg, file) 427__p_cdname(cp, msg, file)
364 char *cp, *msg; 428 const u_char *cp, *msg;
365 FILE *file; 429 FILE *file;
366{ 430{
367 char name[MAXDNAME]; 431 return (p_cdnname(cp, msg, PACKETSZ, file));
368 int n, len; 432}
433
434
435/* Return a fully-qualified domain name from a compressed name (with
436 length supplied). */
437
438const u_char *
439__p_fqnname(cp, msg, msglen, name, namelen)
440 const u_char *cp, *msg;
441 int msglen;
442 char *name;
443 int namelen;
444{
445 int n, newlen;
369 446
370 if ((n = dn_expand((u_char *)msg, (u_char *)cp + MAXCDNAME, 447 if ((n = dn_expand(msg, cp + msglen, cp, name, namelen)) < 0)
371 (u_char *)cp, (u_char *)name, sizeof(name))) < 0)
372 return (NULL); 448 return (NULL);
373 if (name[0] == '\0') { 449 newlen = strlen(name);
374 putc('.', file); 450 if (newlen == 0 || name[newlen - 1] != '.') {
375 } else { 451 if (newlen + 1 >= namelen) /* Lack space for final dot */
376 fputs(name, file); 452 return (NULL);
377 if (name[strlen(name) - 1] != '.') 453 else
378 putc('.', file); 454 strlcpy(name + newlen, ".", namelen - newlen);
379 } 455 }
380 return (cp + n); 456 return (cp + n);
381} 457}
382 458
459/* XXX: the rest of these functions need to become length-limited, too. (vix)
460 */
461
462const u_char *
463__p_fqname(cp, msg, file)
464 const u_char *cp, *msg;
465 FILE *file;
466{
467 char name[MAXDNAME];
468 const u_char *n;
469
470 n = __p_fqnname(cp, msg, MAXCDNAME, name, sizeof name);
471 if (n == NULL)
472 return (NULL);
473 fputs(name, file);
474 return (n);
475}
476
383/* 477/*
384 * Print resource record fields in human readable form. 478 * Print resource record fields in human readable form.
385 */ 479 */
386char * 480const u_char *
387p_rr(cp, msg, file) 481__p_rr(cp, msg, file)
388 char *cp, *msg; 482 const u_char *cp, *msg;
389 FILE *file; 483 FILE *file;
390{ 484{
485 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
391 int type, class, dlen, n, c; 486 int type, class, dlen, n, c;
392 struct in_addr inaddr; 487 struct in_addr inaddr;
393 char *cp1, *cp2; 488 const u_char *cp1, *cp2;
394 u_int32_t tmpttl, t; 489 u_int32_t tmpttl, t;
395 int lcnt; 490 int lcnt;
491 u_int16_t keyflags;
492 char rrname[MAXDNAME]; /* The fqdn of this RR */
493 char base64_key[MAX_KEY_BASE64];
396 494
397 if ((cp = p_fqname(cp, msg, file)) == NULL) 495 if ((_resp->options & RES_INIT) == 0 && res_init() == -1) {
496 h_errno = NETDB_INTERNAL;
497 return (NULL);
498 }
499 cp = __p_fqnname(cp, msg, MAXCDNAME, rrname, sizeof rrname);
500 if (!cp)
398 return (NULL); /* compression error */ 501 return (NULL); /* compression error */
399 type = _getshort(cp); 502 fputs(rrname, file);
400 cp += sizeof(u_int16_t); 503
401 class = _getshort(cp); 504 type = _getshort((u_char*)cp);
402 cp += sizeof(u_int16_t); 505 cp += INT16SZ;
403 tmpttl = _getlong(cp); 506 class = _getshort((u_char*)cp);
404 cp += sizeof(u_int32_t); 507 cp += INT16SZ;
405 dlen = _getshort(cp); 508 tmpttl = _getlong((u_char*)cp);
406 cp += sizeof(u_int16_t); 509 cp += INT32SZ;
510 dlen = _getshort((u_char*)cp);
511 cp += INT16SZ;
407 cp1 = cp; 512 cp1 = cp;
408 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_TTLID)) 513 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_TTLID))
409 fprintf(file, "\t%lu", tmpttl); 514 fprintf(file, "\t%lu", (u_long)tmpttl);
410 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_CLASS)) 515 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_CLASS))
411 fprintf(file, "\t%s", __p_class(class)); 516 fprintf(file, "\t%s", __p_class(class));
412 fprintf(file, "\t%s", __p_type(type)); 517 fprintf(file, "\t%s", __p_type(type));
413 /* 518 /*
@@ -418,22 +523,22 @@ p_rr(cp, msg, file)
418 switch (class) { 523 switch (class) {
419 case C_IN: 524 case C_IN:
420 case C_HS: 525 case C_HS:
421 bcopy(cp, (char *)&inaddr, sizeof(inaddr)); 526 bcopy(cp, (char *)&inaddr, INADDRSZ);
422 if (dlen == 4) { 527 if (dlen == 4) {
423 fprintf(file,"\t%s", inet_ntoa(inaddr)); 528 fprintf(file, "\t%s", inet_ntoa(inaddr));
424 cp += dlen; 529 cp += dlen;
425 } else if (dlen == 7) { 530 } else if (dlen == 7) {
426 char *address; 531 char *address;
427 u_char protocol; 532 u_char protocol;
428 u_short port; 533 in_port_t port;
429 534
430 address = inet_ntoa(inaddr); 535 address = inet_ntoa(inaddr);
431 cp += sizeof(inaddr); 536 cp += INADDRSZ;
432 protocol = *(u_char*)cp; 537 protocol = *(u_char*)cp;
433 cp += sizeof(u_char); 538 cp += sizeof (u_char);
434 port = _getshort(cp); 539 port = _getshort((u_char*)cp);
435 cp += sizeof(u_int16_t); 540 cp += INT16SZ;
436 fprintf(file, "\t%s\t; proto %d, port %d", 541 fprintf(file, "\t%s\t; proto %u, port %u",
437 address, protocol, port); 542 address, protocol, port);
438 } 543 }
439 break; 544 break;
@@ -448,98 +553,205 @@ p_rr(cp, msg, file)
448 case T_NS: 553 case T_NS:
449 case T_PTR: 554 case T_PTR:
450 putc('\t', file); 555 putc('\t', file);
451 cp = p_fqname(cp, msg, file); 556 if ((cp = p_fqname(cp, msg, file)) == NULL)
557 return (NULL);
452 break; 558 break;
453 559
454 case T_HINFO: 560 case T_HINFO:
455 if (n = *cp++) { 561 case T_ISDN:
456 fprintf(file,"\t%.*s", n, cp); 562 cp2 = cp + dlen;
457 cp += n; 563 (void) fputs("\t\"", file);
564 if ((n = (unsigned char) *cp++) != 0) {
565 for (c = n; c > 0 && cp < cp2; c--) {
566 if (strchr("\n\"\\", *cp))
567 (void) putc('\\', file);
568 (void) putc(*cp++, file);
569 }
458 } 570 }
459 if (n = *cp++) { 571 putc('"', file);
460 fprintf(file,"\t%.*s", n, cp); 572 if (cp < cp2 && (n = (unsigned char) *cp++) != 0) {
461 cp += n; 573 (void) fputs ("\t\"", file);
574 for (c = n; c > 0 && cp < cp2; c--) {
575 if (strchr("\n\"\\", *cp))
576 (void) putc('\\', file);
577 (void) putc(*cp++, file);
578 }
579 putc('"', file);
580 } else if (type == T_HINFO) {
581 (void) fputs("\"?\"", file);
582 fprintf(file, "\n;; *** Warning *** OS-type missing");
462 } 583 }
463 break; 584 break;
464 585
465 case T_SOA: 586 case T_SOA:
466 putc('\t', file); 587 putc('\t', file);
467 cp = p_fqname(cp, msg, file); /* origin */ 588 if ((cp = p_fqname(cp, msg, file)) == NULL)
589 return (NULL);
468 putc(' ', file); 590 putc(' ', file);
469 cp = p_fqname(cp, msg, file); /* mail addr */ 591 if ((cp = p_fqname(cp, msg, file)) == NULL)
592 return (NULL);
470 fputs(" (\n", file); 593 fputs(" (\n", file);
471 t = _getlong(cp); cp += sizeof(u_int32_t); 594 t = _getlong((u_char*)cp); cp += INT32SZ;
472 fprintf(file,"\t\t\t%lu\t; serial\n", t); 595 fprintf(file, "\t\t\t%lu\t; serial\n", (u_long)t);
473 t = _getlong(cp); cp += sizeof(u_int32_t); 596 t = _getlong((u_char*)cp); cp += INT32SZ;
474 fprintf(file,"\t\t\t%lu\t; refresh (%s)\n", t, __p_time(t)); 597 fprintf(file, "\t\t\t%lu\t; refresh (%s)\n",
475 t = _getlong(cp); cp += sizeof(u_int32_t); 598 (u_long)t, __p_time(t));
476 fprintf(file,"\t\t\t%lu\t; retry (%s)\n", t, __p_time(t)); 599 t = _getlong((u_char*)cp); cp += INT32SZ;
477 t = _getlong(cp); cp += sizeof(u_int32_t); 600 fprintf(file, "\t\t\t%lu\t; retry (%s)\n",
478 fprintf(file,"\t\t\t%lu\t; expire (%s)\n", t, __p_time(t)); 601 (u_long)t, __p_time(t));
479 t = _getlong(cp); cp += sizeof(u_int32_t); 602 t = _getlong((u_char*)cp); cp += INT32SZ;
480 fprintf(file,"\t\t\t%lu )\t; minimum (%s)", t, __p_time(t)); 603 fprintf(file, "\t\t\t%lu\t; expire (%s)\n",
604 (u_long)t, __p_time(t));
605 t = _getlong((u_char*)cp); cp += INT32SZ;
606 fprintf(file, "\t\t\t%lu )\t; minimum (%s)",
607 (u_long)t, __p_time(t));
481 break; 608 break;
482 609
483 case T_MX: 610 case T_MX:
484 case T_AFSDB: 611 case T_AFSDB:
485 fprintf(file,"\t%d ", _getshort(cp)); 612 case T_RT:
486 cp += sizeof(u_int16_t); 613 fprintf(file, "\t%u ", _getshort((u_char*)cp));
487 cp = p_fqname(cp, msg, file); 614 cp += INT16SZ;
615 if ((cp = p_fqname(cp, msg, file)) == NULL)
616 return (NULL);
488 break; 617 break;
489 618
490 case T_TXT: 619 case T_PX:
620 fprintf(file, "\t%u ", _getshort((u_char*)cp));
621 cp += INT16SZ;
622 if ((cp = p_fqname(cp, msg, file)) == NULL)
623 return (NULL);
624 putc(' ', file);
625 if ((cp = p_fqname(cp, msg, file)) == NULL)
626 return (NULL);
627 break;
628
629 case T_X25:
630 cp2 = cp + dlen;
491 (void) fputs("\t\"", file); 631 (void) fputs("\t\"", file);
632 if ((n = (unsigned char) *cp++) != 0) {
633 for (c = n; c > 0 && cp < cp2; c--) {
634 if (strchr("\n\"\\", *cp))
635 (void) putc('\\', file);
636 (void) putc(*cp++, file);
637 }
638 }
639 putc('"', file);
640 break;
641
642 case T_TXT:
643 (void) putc('\t', file);
492 cp2 = cp1 + dlen; 644 cp2 = cp1 + dlen;
493 while (cp < cp2) { 645 while (cp < cp2) {
494 if (n = (unsigned char) *cp++) { 646 putc('"', file);
495 for (c = n; c > 0 && cp < cp2; c--) 647 if ((n = (unsigned char) *cp++)) {
496 if (*cp == '\n') { 648 for (c = n; c > 0 && cp < cp2; c--) {
497 (void) putc('\\', file); 649 if (strchr("\n\"\\", *cp))
498 (void) putc(*cp++, file); 650 (void) putc('\\', file);
499 } else 651 (void) putc(*cp++, file);
500 (void) putc(*cp++, file); 652 }
501 } 653 }
654 putc('"', file);
655 if (cp < cp2)
656 putc(' ', file);
502 } 657 }
503 putc('"', file); 658 break;
504 break; 659
660 case T_NSAP:
661 (void) fprintf(file, "\t%s", inet_nsap_ntoa(dlen, cp, NULL));
662 cp += dlen;
663 break;
664
665 case T_AAAA: {
666 char t[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"];
667
668 fprintf(file, "\t%s", inet_ntop(AF_INET6, cp, t, sizeof t));
669 cp += dlen;
670 break;
671 }
672
673 case T_LOC: {
674 char t[255];
675
676 fprintf(file, "\t%s", loc_ntoal(cp, t, sizeof t));
677 cp += dlen;
678 break;
679 }
680
681 case T_NAPTR: {
682 u_int order, preference;
683
684 order = _getshort(cp); cp += INT16SZ;
685 preference = _getshort(cp); cp += INT16SZ;
686 fprintf(file, "\t%u %u ",order, preference);
687 /* Flags */
688 n = *cp++;
689 fprintf(file,"\"%.*s\" ", (int)n, cp);
690 cp += n;
691 /* Service */
692 n = *cp++;
693 fprintf(file,"\"%.*s\" ", (int)n, cp);
694 cp += n;
695 /* Regexp */
696 n = *cp++;
697 fprintf(file,"\"%.*s\" ", (int)n, cp);
698 cp += n;
699 if ((cp = p_fqname(cp, msg, file)) == NULL)
700 return (NULL);
701 break;
702 }
703
704 case T_SRV: {
705 u_int priority, weight, port;
706
707 priority = _getshort(cp); cp += INT16SZ;
708 weight = _getshort(cp); cp += INT16SZ;
709 port = _getshort(cp); cp += INT16SZ;
710 fprintf(file, "\t%u %u %u ", priority, weight, port);
711 if ((cp = p_fqname(cp, msg, file)) == NULL)
712 return (NULL);
713 break;
714 }
505 715
506 case T_MINFO: 716 case T_MINFO:
507 case T_RP: 717 case T_RP:
508 putc('\t', file); 718 putc('\t', file);
509 cp = p_fqname(cp, msg, file); 719 if ((cp = p_fqname(cp, msg, file)) == NULL)
720 return (NULL);
510 putc(' ', file); 721 putc(' ', file);
511 cp = p_fqname(cp, msg, file); 722 if ((cp = p_fqname(cp, msg, file)) == NULL)
723 return (NULL);
512 break; 724 break;
513 725
514 case T_UINFO: 726 case T_UINFO:
515 putc('\t', file); 727 putc('\t', file);
516 fputs(cp, file); 728 fputs((char *)cp, file);
517 cp += dlen; 729 cp += dlen;
518 break; 730 break;
519 731
520 case T_UID: 732 case T_UID:
521 case T_GID: 733 case T_GID:
522 if (dlen == 4) { 734 if (dlen == 4) {
523 fprintf(file,"\t%u", _getlong(cp)); 735 fprintf(file, "\t%u", _getlong((u_char*)cp));
524 cp += sizeof(int32_t); 736 cp += INT32SZ;
525 } 737 }
526 break; 738 break;
527 739
528 case T_WKS: 740 case T_WKS:
529 if (dlen < sizeof(u_int32_t) + 1) 741 if (dlen < INT32SZ + 1)
530 break; 742 break;
531 bcopy(cp, (char *)&inaddr, sizeof(inaddr)); 743 bcopy(cp, (char *)&inaddr, INADDRSZ);
532 cp += sizeof(u_int32_t); 744 cp += INT32SZ;
533 fprintf(file, "\t%s %s ( ", 745 fprintf(file, "\t%s %s ( ",
534 inet_ntoa(inaddr), 746 inet_ntoa(inaddr),
535 deproto((int) *cp)); 747 deproto((int) *cp));
536 cp += sizeof(u_char); 748 cp += sizeof (u_char);
537 n = 0; 749 n = 0;
538 lcnt = 0; 750 lcnt = 0;
539 while (cp < cp1 + dlen) { 751 while (cp < cp1 + dlen) {
540 c = *cp++; 752 c = *cp++;
541 do { 753 do {
542 if (c & 0200) { 754 if (c & 0200) {
543 if (lcnt == 0) { 755 if (lcnt == 0) {
544 fputs("\n\t\t\t", file); 756 fputs("\n\t\t\t", file);
545 lcnt = 5; 757 lcnt = 5;
@@ -548,17 +760,83 @@ p_rr(cp, msg, file)
548 putc(' ', file); 760 putc(' ', file);
549 lcnt--; 761 lcnt--;
550 } 762 }
551 c <<= 1; 763 c <<= 1;
552 } while (++n & 07); 764 } while (++n & 07);
553 } 765 }
554 putc(')', file); 766 putc(')', file);
555 break; 767 break;
556 768
769 case T_KEY:
770 putc('\t', file);
771 keyflags = _getshort(cp);
772 cp += 2;
773 fprintf(file,"0x%04x", keyflags ); /* flags */
774 fprintf(file," %u", *cp++); /* protocol */
775 fprintf(file," %u (", *cp++); /* algorithm */
776
777 n = b64_ntop(cp, (cp1 + dlen) - cp,
778 base64_key, sizeof base64_key);
779 for (c = 0; c < n; ++c) {
780 if (0 == (c & 0x3F))
781 fprintf(file, "\n\t");
782 putc(base64_key[c], file); /* public key data */
783 }
784
785 fprintf(file, " )");
786 if (n < 0)
787 fprintf(file, "\t; BAD BASE64");
788 fflush(file);
789 cp = cp1 + dlen;
790 break;
791
792 case T_SIG:
793 type = _getshort((u_char*)cp);
794 cp += INT16SZ;
795 fprintf(file, " %s", p_type(type));
796 fprintf(file, "\t%u", *cp++); /* algorithm */
797 /* Check label value and print error if wrong. */
798 n = *cp++;
799 c = dn_count_labels (rrname);
800 if (n != c)
801 fprintf(file, "\t; LABELS WRONG (%d should be %d)\n\t",
802 n, c);
803 /* orig ttl */
804 n = _getlong((u_char*)cp);
805 if (n != tmpttl)
806 fprintf(file, " %u", n);
807 cp += INT32SZ;
808 /* sig expire */
809 fprintf(file, " (\n\t%s",
810 __p_secstodate(_getlong((u_char*)cp)));
811 cp += INT32SZ;
812 /* time signed */
813 fprintf(file, " %s", __p_secstodate(_getlong((u_char*)cp)));
814 cp += INT32SZ;
815 /* sig footprint */
816 fprintf(file," %u ", _getshort((u_char*)cp));
817 cp += INT16SZ;
818 /* signer's name */
819 cp = p_fqname(cp, msg, file);
820 n = b64_ntop(cp, (cp1 + dlen) - cp,
821 base64_key, sizeof base64_key);
822 for (c = 0; c < n; c++) {
823 if (0 == (c & 0x3F))
824 fprintf (file, "\n\t");
825 putc(base64_key[c], file); /* signature */
826 }
827 /* Clean up... */
828 fprintf(file, " )");
829 if (n < 0)
830 fprintf(file, "\t; BAD BASE64");
831 fflush(file);
832 cp = cp1+dlen;
833 break;
834
557#ifdef ALLOW_T_UNSPEC 835#ifdef ALLOW_T_UNSPEC
558 case T_UNSPEC: 836 case T_UNSPEC:
559 { 837 {
560 int NumBytes = 8; 838 int NumBytes = 8;
561 char *DataPtr; 839 u_char *DataPtr;
562 int i; 840 int i;
563 841
564 if (dlen < NumBytes) NumBytes = dlen; 842 if (dlen < NumBytes) NumBytes = dlen;
@@ -572,7 +850,7 @@ p_rr(cp, msg, file)
572#endif /* ALLOW_T_UNSPEC */ 850#endif /* ALLOW_T_UNSPEC */
573 851
574 default: 852 default:
575 fprintf(file,"\t?%d?", type); 853 fprintf(file, "\t?%d?", type);
576 cp += dlen; 854 cp += dlen;
577 } 855 }
578#if 0 856#if 0
@@ -581,136 +859,210 @@ p_rr(cp, msg, file)
581 putc('\n', file); 859 putc('\n', file);
582#endif 860#endif
583 if (cp - cp1 != dlen) { 861 if (cp - cp1 != dlen) {
584 fprintf(file,";; packet size error (found %d, dlen was %d)\n", 862 fprintf(file, ";; packet size error (found %ld, dlen was %d)\n",
585 cp - cp1, dlen); 863 (long)(cp - cp1), dlen);
586 cp = NULL; 864 cp = NULL;
587 } 865 }
588 return (cp); 866 return (cp);
589} 867}
590 868
591static char nbuf[40]; 869/*
870 * Names of RR classes and qclasses. Classes and qclasses are the same, except
871 * that C_ANY is a qclass but not a class. (You can ask for records of class
872 * C_ANY, but you can't have any records of that class in the database.)
873 */
874const struct res_sym __p_class_syms[] = {
875 {C_IN, "IN"},
876 {C_CHAOS, "CHAOS"},
877 {C_HS, "HS"},
878 {C_HS, "HESIOD"},
879 {C_ANY, "ANY"},
880 {C_IN, (char *)0}
881};
592 882
593/* 883/*
594 * Return a string for the type 884 * Names of RR types and qtypes. Types and qtypes are the same, except
885 * that T_ANY is a qtype but not a type. (You can ask for records of type
886 * T_ANY, but you can't have any records of that type in the database.)
595 */ 887 */
596char * 888const struct res_sym __p_type_syms[] = {
597__p_type(type) 889 {T_A, "A", "address"},
598 int type; 890 {T_NS, "NS", "name server"},
599{ 891 {T_MD, "MD", "mail destination (deprecated)"},
600 switch (type) { 892 {T_MF, "MF", "mail forwarder (deprecated)"},
601 case T_A: 893 {T_CNAME, "CNAME", "canonical name"},
602 return("A"); 894 {T_SOA, "SOA", "start of authority"},
603 case T_NS: /* authoritative server */ 895 {T_MB, "MB", "mailbox"},
604 return("NS"); 896 {T_MG, "MG", "mail group member"},
605 case T_CNAME: /* canonical name */ 897 {T_MR, "MR", "mail rename"},
606 return("CNAME"); 898 {T_NULL, "NULL", "null"},
607 case T_SOA: /* start of authority zone */ 899 {T_WKS, "WKS", "well-known service (deprecated)"},
608 return("SOA"); 900 {T_PTR, "PTR", "domain name pointer"},
609 case T_MB: /* mailbox domain name */ 901 {T_HINFO, "HINFO", "host information"},
610 return("MB"); 902 {T_MINFO, "MINFO", "mailbox information"},
611 case T_MG: /* mail group member */ 903 {T_MX, "MX", "mail exchanger"},
612 return("MG"); 904 {T_TXT, "TXT", "text"},
613 case T_MR: /* mail rename name */ 905 {T_RP, "RP", "responsible person"},
614 return("MR"); 906 {T_AFSDB, "AFSDB", "DCE or AFS server"},
615 case T_NULL: /* null resource record */ 907 {T_X25, "X25", "X25 address"},
616 return("NULL"); 908 {T_ISDN, "ISDN", "ISDN address"},
617 case T_WKS: /* well known service */ 909 {T_RT, "RT", "router"},
618 return("WKS"); 910 {T_NSAP, "NSAP", "nsap address"},
619 case T_PTR: /* domain name pointer */ 911 {T_NSAP_PTR, "NSAP_PTR", "domain name pointer"},
620 return("PTR"); 912 {T_SIG, "SIG", "signature"},
621 case T_HINFO: /* host information */ 913 {T_KEY, "KEY", "key"},
622 return("HINFO"); 914 {T_PX, "PX", "mapping information"},
623 case T_MINFO: /* mailbox information */ 915 {T_GPOS, "GPOS", "geographical position (withdrawn)"},
624 return("MINFO"); 916 {T_AAAA, "AAAA", "IPv6 address"},
625 case T_MX: /* mail routing info */ 917 {T_LOC, "LOC", "location"},
626 return("MX"); 918 {T_NXT, "NXT", "next valid name (unimplemented)"},
627 case T_TXT: /* text */ 919 {T_EID, "EID", "endpoint identifier (unimplemented)"},
628 return("TXT"); 920 {T_NIMLOC, "NIMLOC", "NIMROD locator (unimplemented)"},
629 case T_RP: /* responsible person */ 921 {T_SRV, "SRV", "server selection"},
630 return("RP"); 922 {T_ATMA, "ATMA", "ATM address (unimplemented)"},
631 case T_AFSDB: /* AFS cell database */ 923 {T_IXFR, "IXFR", "incremental zone transfer"},
632 return("AFSDB"); 924 {T_AXFR, "AXFR", "zone transfer"},
633 case T_AXFR: /* zone transfer */ 925 {T_MAILB, "MAILB", "mailbox-related data (deprecated)"},
634 return("AXFR"); 926 {T_MAILA, "MAILA", "mail agent (deprecated)"},
635 case T_MAILB: /* mail box */ 927 {T_UINFO, "UINFO", "user information (nonstandard)"},
636 return("MAILB"); 928 {T_UID, "UID", "user ID (nonstandard)"},
637 case T_MAILA: /* mail address */ 929 {T_GID, "GID", "group ID (nonstandard)"},
638 return("MAILA"); 930 {T_NAPTR, "NAPTR", "URN Naming Authority"},
639 case T_ANY: /* matches any type */
640 return("ANY");
641 case T_UINFO:
642 return("UINFO");
643 case T_UID:
644 return("UID");
645 case T_GID:
646 return("GID");
647#ifdef ALLOW_T_UNSPEC 931#ifdef ALLOW_T_UNSPEC
648 case T_UNSPEC: 932 {T_UNSPEC, "UNSPEC", "unspecified data (nonstandard)"},
649 return("UNSPEC");
650#endif /* ALLOW_T_UNSPEC */ 933#endif /* ALLOW_T_UNSPEC */
934 {T_ANY, "ANY", "\"any\""},
935 {0, NULL, NULL}
936};
651 937
652 default: 938int
653 (void)sprintf(nbuf, "%d", type); 939__sym_ston(syms, name, success)
654 return(nbuf); 940 const struct res_sym *syms;
941 char *name;
942 int *success;
943{
944 for (; syms->name != 0; syms++) {
945 if (strcasecmp (name, syms->name) == 0) {
946 if (success)
947 *success = 1;
948 return (syms->number);
949 }
950 }
951 if (success)
952 *success = 0;
953 return (syms->number); /* The default value. */
954}
955
956const char *
957__sym_ntos(syms, number, success)
958 const struct res_sym *syms;
959 int number;
960 int *success;
961{
962 static char unname[20];
963
964 for (; syms->name != 0; syms++) {
965 if (number == syms->number) {
966 if (success)
967 *success = 1;
968 return (syms->name);
969 }
970 }
971
972 snprintf(unname, sizeof unname, "%d", number);
973 if (success)
974 *success = 0;
975 return (unname);
976}
977
978
979const char *
980__sym_ntop(syms, number, success)
981 const struct res_sym *syms;
982 int number;
983 int *success;
984{
985 static char unname[20];
986
987 for (; syms->name != 0; syms++) {
988 if (number == syms->number) {
989 if (success)
990 *success = 1;
991 return (syms->humanname);
992 }
655 } 993 }
994 snprintf(unname, sizeof unname, "%d", number);
995 if (success)
996 *success = 0;
997 return (unname);
998}
999
1000/*
1001 * Return a string for the type
1002 */
1003const char *
1004__p_type(type)
1005 int type;
1006{
1007 return (__sym_ntos (__p_type_syms, type, (int *)0));
656} 1008}
657 1009
658/* 1010/*
659 * Return a mnemonic for class 1011 * Return a mnemonic for class
660 */ 1012 */
661char * 1013const char *
662__p_class(class) 1014__p_class(class)
663 int class; 1015 int class;
664{ 1016{
665 1017 return (__sym_ntos (__p_class_syms, class, (int *)0));
666 switch (class) {
667 case C_IN: /* internet class */
668 return("IN");
669 case C_HS: /* hesiod class */
670 return("HS");
671 case C_ANY: /* matches any class */
672 return("ANY");
673 default:
674 (void)sprintf(nbuf, "%d", class);
675 return(nbuf);
676 }
677} 1018}
678 1019
679/* 1020/*
680 * Return a mnemonic for an option 1021 * Return a mnemonic for an option
681 */ 1022 */
682static char * 1023const char *
683p_option(option) 1024__p_option(option)
684 u_int32_t option; 1025 u_long option;
685{ 1026{
1027 static char nbuf[40];
1028
686 switch (option) { 1029 switch (option) {
687 case RES_INIT: return "init"; 1030 case RES_INIT: return "init";
688 case RES_DEBUG: return "debug"; 1031 case RES_DEBUG: return "debug";
689 case RES_AAONLY: return "aaonly"; 1032 case RES_AAONLY: return "aaonly(unimpl)";
690 case RES_USEVC: return "usevc"; 1033 case RES_USEVC: return "usevc";
691 case RES_PRIMARY: return "primry"; 1034 case RES_PRIMARY: return "primry(unimpl)";
692 case RES_IGNTC: return "igntc"; 1035 case RES_IGNTC: return "igntc";
693 case RES_RECURSE: return "recurs"; 1036 case RES_RECURSE: return "recurs";
694 case RES_DEFNAMES: return "defnam"; 1037 case RES_DEFNAMES: return "defnam";
695 case RES_STAYOPEN: return "styopn"; 1038 case RES_STAYOPEN: return "styopn";
696 case RES_DNSRCH: return "dnsrch"; 1039 case RES_DNSRCH: return "dnsrch";
697 default: sprintf(nbuf, "?0x%x?", option); return nbuf; 1040 case RES_INSECURE1: return "insecure1";
1041 case RES_INSECURE2: return "insecure2";
1042 case RES_USE_INET6: return "inet6";
1043 case RES_USE_EDNS0: return "edns0";
1044 default:
1045 snprintf(nbuf, sizeof nbuf, "?0x%lx?", (u_long)option);
1046 return (nbuf);
698 } 1047 }
699} 1048}
700 1049
701/* 1050/*
702 * Return a mnemonic for a time to live 1051 * Return a mnemonic for a time to live
703 */ 1052 */
704char * 1053const char *
705__p_time(value) 1054p_time(value)
706 u_int32_t value; 1055 u_int32_t value;
707{ 1056{
1057 static char nbuf[40];
1058 char *ebuf;
708 int secs, mins, hours, days; 1059 int secs, mins, hours, days;
709 register char *p; 1060 register char *p;
1061 int tmp;
710 1062
711 if (value == 0) { 1063 if (value == 0) {
712 strcpy(nbuf, "0 secs"); 1064 strlcpy(nbuf, "0 secs", sizeof nbuf);
713 return(nbuf); 1065 return (nbuf);
714 } 1066 }
715 1067
716 secs = value % 60; 1068 secs = value % 60;
@@ -724,26 +1076,490 @@ __p_time(value)
724 1076
725#define PLURALIZE(x) x, (x == 1) ? "" : "s" 1077#define PLURALIZE(x) x, (x == 1) ? "" : "s"
726 p = nbuf; 1078 p = nbuf;
1079 ebuf = nbuf + sizeof(nbuf);
727 if (days) { 1080 if (days) {
728 (void)sprintf(p, "%d day%s", PLURALIZE(days)); 1081 if ((tmp = snprintf(p, ebuf - p, "%d day%s",
729 while (*++p); 1082 PLURALIZE(days))) >= ebuf - nbuf || tmp < 0)
1083 goto full;
1084 p += tmp;
730 } 1085 }
731 if (hours) { 1086 if (hours) {
732 if (days) 1087 if (days)
733 *p++ = ' '; 1088 *p++ = ' ';
734 (void)sprintf(p, "%d hour%s", PLURALIZE(hours)); 1089 if (p >= ebuf)
735 while (*++p); 1090 goto full;
1091 if ((tmp = snprintf(p, ebuf - p, "%d hour%s",
1092 PLURALIZE(hours))) >= ebuf - nbuf || tmp < 0)
1093 goto full;
1094 p += tmp;
736 } 1095 }
737 if (mins) { 1096 if (mins) {
738 if (days || hours) 1097 if (days || hours)
739 *p++ = ' '; 1098 *p++ = ' ';
740 (void)sprintf(p, "%d min%s", PLURALIZE(mins)); 1099 if (p >= ebuf)
741 while (*++p); 1100 goto full;
1101 if ((tmp = snprintf(p, ebuf - p, "%d min%s",
1102 PLURALIZE(mins))) >= ebuf - nbuf || tmp < 0)
1103 goto full;
1104 p += tmp;
742 } 1105 }
743 if (secs || ! (days || hours || mins)) { 1106 if (secs || ! (days || hours || mins)) {
744 if (days || hours || mins) 1107 if (days || hours || mins)
745 *p++ = ' '; 1108 *p++ = ' ';
746 (void)sprintf(p, "%d sec%s", PLURALIZE(secs)); 1109 if (p >= ebuf)
1110 goto full;
1111 if ((tmp = snprintf(p, ebuf - p, "%d sec%s",
1112 PLURALIZE(secs))) >= ebuf - nbuf || tmp < 0)
1113 goto full;
1114 }
1115 return (nbuf);
1116full:
1117 p = nbuf + sizeof(nbuf) - 4;
1118 *p++ = '.';
1119 *p++ = '.';
1120 *p++ = '.';
1121 *p++ = '\0';
1122 return (nbuf);
1123}
1124
1125/*
1126 * routines to convert between on-the-wire RR format and zone file format.
1127 * Does not contain conversion to/from decimal degrees; divide or multiply
1128 * by 60*60*1000 for that.
1129 */
1130
1131static unsigned int poweroften[10] = {1, 10, 100, 1000, 10000, 100000,
1132 1000000,10000000,100000000,1000000000};
1133
1134/* takes an XeY precision/size value, returns a string representation. */
1135static const char *
1136precsize_ntoa(prec)
1137 u_int8_t prec;
1138{
1139 static char retbuf[sizeof "90000000.00"];
1140 unsigned long val;
1141 int mantissa, exponent;
1142
1143 mantissa = (int)((prec >> 4) & 0x0f) % 10;
1144 exponent = (int)((prec >> 0) & 0x0f) % 10;
1145
1146 val = mantissa * poweroften[exponent];
1147
1148 (void) snprintf(retbuf, sizeof retbuf, "%ld.%.2ld", val/100, val%100);
1149 return (retbuf);
1150}
1151
1152/* converts ascii size/precision X * 10**Y(cm) to 0xXY. moves pointer. */
1153static u_int8_t
1154precsize_aton(strptr)
1155 char **strptr;
1156{
1157 unsigned int mval = 0, cmval = 0;
1158 u_int8_t retval = 0;
1159 register char *cp;
1160 register int exponent;
1161 register int mantissa;
1162
1163 cp = *strptr;
1164
1165 while (isdigit(*cp))
1166 mval = mval * 10 + (*cp++ - '0');
1167
1168 if (*cp == '.') { /* centimeters */
1169 cp++;
1170 if (isdigit(*cp)) {
1171 cmval = (*cp++ - '0') * 10;
1172 if (isdigit(*cp)) {
1173 cmval += (*cp++ - '0');
1174 }
1175 }
1176 }
1177 cmval = (mval * 100) + cmval;
1178
1179 for (exponent = 0; exponent < 9; exponent++)
1180 if (cmval < poweroften[exponent+1])
1181 break;
1182
1183 mantissa = cmval / poweroften[exponent];
1184 if (mantissa > 9)
1185 mantissa = 9;
1186
1187 retval = (mantissa << 4) | exponent;
1188
1189 *strptr = cp;
1190
1191 return (retval);
1192}
1193
1194/* converts ascii lat/lon to unsigned encoded 32-bit number. moves pointer. */
1195static u_int32_t
1196latlon2ul(latlonstrptr,which)
1197 char **latlonstrptr;
1198 int *which;
1199{
1200 register char *cp;
1201 u_int32_t retval;
1202 int deg = 0, min = 0, secs = 0, secsfrac = 0;
1203
1204 cp = *latlonstrptr;
1205
1206 while (isdigit(*cp))
1207 deg = deg * 10 + (*cp++ - '0');
1208
1209 while (isspace(*cp))
1210 cp++;
1211
1212 if (!(isdigit(*cp)))
1213 goto fndhemi;
1214
1215 while (isdigit(*cp))
1216 min = min * 10 + (*cp++ - '0');
1217
1218 while (isspace(*cp))
1219 cp++;
1220
1221 if (!(isdigit(*cp)))
1222 goto fndhemi;
1223
1224 while (isdigit(*cp))
1225 secs = secs * 10 + (*cp++ - '0');
1226
1227 if (*cp == '.') { /* decimal seconds */
1228 cp++;
1229 if (isdigit(*cp)) {
1230 secsfrac = (*cp++ - '0') * 100;
1231 if (isdigit(*cp)) {
1232 secsfrac += (*cp++ - '0') * 10;
1233 if (isdigit(*cp)) {
1234 secsfrac += (*cp++ - '0');
1235 }
1236 }
1237 }
1238 }
1239
1240 while (!isspace(*cp)) /* if any trailing garbage */
1241 cp++;
1242
1243 while (isspace(*cp))
1244 cp++;
1245
1246 fndhemi:
1247 switch (*cp) {
1248 case 'N': case 'n':
1249 case 'E': case 'e':
1250 retval = ((unsigned)1<<31)
1251 + (((((deg * 60) + min) * 60) + secs) * 1000)
1252 + secsfrac;
1253 break;
1254 case 'S': case 's':
1255 case 'W': case 'w':
1256 retval = ((unsigned)1<<31)
1257 - (((((deg * 60) + min) * 60) + secs) * 1000)
1258 - secsfrac;
1259 break;
1260 default:
1261 retval = 0; /* invalid value -- indicates error */
1262 break;
1263 }
1264
1265 switch (*cp) {
1266 case 'N': case 'n':
1267 case 'S': case 's':
1268 *which = 1; /* latitude */
1269 break;
1270 case 'E': case 'e':
1271 case 'W': case 'w':
1272 *which = 2; /* longitude */
1273 break;
1274 default:
1275 *which = 0; /* error */
1276 break;
1277 }
1278
1279 cp++; /* skip the hemisphere */
1280
1281 while (!isspace(*cp)) /* if any trailing garbage */
1282 cp++;
1283
1284 while (isspace(*cp)) /* move to next field */
1285 cp++;
1286
1287 *latlonstrptr = cp;
1288
1289 return (retval);
1290}
1291
1292/* converts a zone file representation in a string to an RDATA on-the-wire
1293 * representation. */
1294int
1295loc_aton(ascii, binary)
1296 const char *ascii;
1297 u_char *binary;
1298{
1299 const char *maxcp;
1300 u_char *bcp;
1301 char *cp;
1302
1303 u_int32_t latit = 0, longit = 0, alt = 0;
1304 u_int32_t lltemp1 = 0, lltemp2 = 0;
1305 int altmeters = 0, altfrac = 0, altsign = 1;
1306 u_int8_t hp = 0x16; /* default = 1e6 cm = 10000.00m = 10km */
1307 u_int8_t vp = 0x13; /* default = 1e3 cm = 10.00m */
1308 u_int8_t siz = 0x12; /* default = 1e2 cm = 1.00m */
1309 int which1 = 0, which2 = 0;
1310
1311 cp = (char *)ascii;
1312 maxcp = cp + strlen(ascii);
1313
1314 lltemp1 = latlon2ul(&cp, &which1);
1315
1316 lltemp2 = latlon2ul(&cp, &which2);
1317
1318 switch (which1 + which2) {
1319 case 3: /* 1 + 2, the only valid combination */
1320 if ((which1 == 1) && (which2 == 2)) { /* normal case */
1321 latit = lltemp1;
1322 longit = lltemp2;
1323 } else if ((which1 == 2) && (which2 == 1)) { /* reversed */
1324 longit = lltemp1;
1325 latit = lltemp2;
1326 } else { /* some kind of brokenness */
1327 return (0);
1328 }
1329 break;
1330 default: /* we didn't get one of each */
1331 return (0);
747 } 1332 }
748 return(nbuf); 1333
1334 /* altitude */
1335 if (*cp == '-') {
1336 altsign = -1;
1337 cp++;
1338 }
1339
1340 if (*cp == '+')
1341 cp++;
1342
1343 while (isdigit(*cp))
1344 altmeters = altmeters * 10 + (*cp++ - '0');
1345
1346 if (*cp == '.') { /* decimal meters */
1347 cp++;
1348 if (isdigit(*cp)) {
1349 altfrac = (*cp++ - '0') * 10;
1350 if (isdigit(*cp)) {
1351 altfrac += (*cp++ - '0');
1352 }
1353 }
1354 }
1355
1356 alt = (10000000 + (altsign * (altmeters * 100 + altfrac)));
1357
1358 while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
1359 cp++;
1360
1361 while (isspace(*cp) && (cp < maxcp))
1362 cp++;
1363
1364 if (cp >= maxcp)
1365 goto defaults;
1366
1367 siz = precsize_aton(&cp);
1368
1369 while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
1370 cp++;
1371
1372 while (isspace(*cp) && (cp < maxcp))
1373 cp++;
1374
1375 if (cp >= maxcp)
1376 goto defaults;
1377
1378 hp = precsize_aton(&cp);
1379
1380 while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
1381 cp++;
1382
1383 while (isspace(*cp) && (cp < maxcp))
1384 cp++;
1385
1386 if (cp >= maxcp)
1387 goto defaults;
1388
1389 vp = precsize_aton(&cp);
1390
1391 defaults:
1392
1393 bcp = binary;
1394 *bcp++ = (u_int8_t) 0; /* version byte */
1395 *bcp++ = siz;
1396 *bcp++ = hp;
1397 *bcp++ = vp;
1398 PUTLONG(latit,bcp);
1399 PUTLONG(longit,bcp);
1400 PUTLONG(alt,bcp);
1401
1402 return (16); /* size of RR in octets */
1403}
1404
1405const char *
1406loc_ntoa(binary, ascii)
1407 const u_char *binary;
1408 char *ascii;
1409{
1410 return loc_ntoal(binary, ascii, 255);
1411}
1412
1413/* takes an on-the-wire LOC RR and formats it in a human readable format. */
1414static const char *
1415loc_ntoal(binary, ascii, ascii_len)
1416 const u_char *binary;
1417 char *ascii;
1418 int ascii_len;
1419{
1420 static char *error = "?";
1421 register const u_char *cp = binary;
1422
1423 int latdeg, latmin, latsec, latsecfrac;
1424 int longdeg, longmin, longsec, longsecfrac;
1425 char northsouth, eastwest;
1426 int altmeters, altfrac, altsign;
1427
1428 const int referencealt = 100000 * 100;
1429
1430 int32_t latval, longval, altval;
1431 u_int32_t templ;
1432 u_int8_t sizeval, hpval, vpval, versionval;
1433
1434 char *sizestr, *hpstr, *vpstr;
1435
1436 versionval = *cp++;
1437
1438 if (versionval) {
1439 snprintf(ascii, ascii_len, "; error: unknown LOC RR version");
1440 return (ascii);
1441 }
1442
1443 sizeval = *cp++;
1444
1445 hpval = *cp++;
1446 vpval = *cp++;
1447
1448 GETLONG(templ, cp);
1449 latval = (templ - ((unsigned)1<<31));
1450
1451 GETLONG(templ, cp);
1452 longval = (templ - ((unsigned)1<<31));
1453
1454 GETLONG(templ, cp);
1455 if (templ < referencealt) { /* below WGS 84 spheroid */
1456 altval = referencealt - templ;
1457 altsign = -1;
1458 } else {
1459 altval = templ - referencealt;
1460 altsign = 1;
1461 }
1462
1463 if (latval < 0) {
1464 northsouth = 'S';
1465 latval = -latval;
1466 } else
1467 northsouth = 'N';
1468
1469 latsecfrac = latval % 1000;
1470 latval = latval / 1000;
1471 latsec = latval % 60;
1472 latval = latval / 60;
1473 latmin = latval % 60;
1474 latval = latval / 60;
1475 latdeg = latval;
1476
1477 if (longval < 0) {
1478 eastwest = 'W';
1479 longval = -longval;
1480 } else
1481 eastwest = 'E';
1482
1483 longsecfrac = longval % 1000;
1484 longval = longval / 1000;
1485 longsec = longval % 60;
1486 longval = longval / 60;
1487 longmin = longval % 60;
1488 longval = longval / 60;
1489 longdeg = longval;
1490
1491 altfrac = altval % 100;
1492 altmeters = (altval / 100) * altsign;
1493
1494 if ((sizestr = strdup(precsize_ntoa(sizeval))) == NULL)
1495 sizestr = error;
1496 if ((hpstr = strdup(precsize_ntoa(hpval))) == NULL)
1497 hpstr = error;
1498 if ((vpstr = strdup(precsize_ntoa(vpval))) == NULL)
1499 vpstr = error;
1500
1501 snprintf(ascii, ascii_len,
1502 "%d %.2d %.2d.%.3d %c %d %.2d %.2d.%.3d %c %d.%.2dm %sm %sm %sm",
1503 latdeg, latmin, latsec, latsecfrac, northsouth,
1504 longdeg, longmin, longsec, longsecfrac, eastwest,
1505 altmeters, altfrac, sizestr, hpstr, vpstr);
1506
1507 if (sizestr != error)
1508 free(sizestr);
1509 if (hpstr != error)
1510 free(hpstr);
1511 if (vpstr != error)
1512 free(vpstr);
1513
1514 return (ascii);
1515}
1516
1517
1518/* Return the number of DNS hierarchy levels in the name. */
1519int
1520__dn_count_labels(name)
1521 char *name;
1522{
1523 int i, len, count;
1524
1525 len = strlen(name);
1526
1527 for(i = 0, count = 0; i < len; i++) {
1528 if (name[i] == '.')
1529 count++;
1530 }
1531
1532 /* don't count initial wildcard */
1533 if (name[0] == '*')
1534 if (count)
1535 count--;
1536
1537 /* don't count the null label for root. */
1538 /* if terminating '.' not found, must adjust */
1539 /* count to include last label */
1540 if (len > 0 && name[len-1] != '.')
1541 count++;
1542 return (count);
1543}
1544
1545
1546/*
1547 * Make dates expressed in seconds-since-Jan-1-1970 easy to read.
1548 * SIG records are required to be printed like this, by the Secure DNS RFC.
1549 */
1550char *
1551__p_secstodate (secs)
1552 unsigned long secs;
1553{
1554 static char output[15]; /* YYYYMMDDHHMMSS and null */
1555 time_t clock = secs;
1556 struct tm *time;
1557
1558 time = gmtime(&clock);
1559 time->tm_year += 1900;
1560 time->tm_mon += 1;
1561 snprintf(output, sizeof output, "%04d%02d%02d%02d%02d%02d",
1562 time->tm_year, time->tm_mon, time->tm_mday,
1563 time->tm_hour, time->tm_min, time->tm_sec);
1564 return (output);
749} 1565}
diff --git a/src/lib/libc/net/res_init.c b/src/lib/libc/net/res_init.c
index 33cc8d39f1..a1d69f57b5 100644
--- a/src/lib/libc/net/res_init.c
+++ b/src/lib/libc/net/res_init.c
@@ -1,9 +1,11 @@
1/* $NetBSD: res_init.c,v 1.8 1995/06/03 22:33:36 mycroft Exp $ */ 1/* $OpenBSD: res_init.c,v 1.28 2003/01/28 04:58:00 marc Exp $ */
2 2
3/*- 3/*
4 * ++Copyright++ 1985, 1989, 1993
5 * -
4 * Copyright (c) 1985, 1989, 1993 6 * Copyright (c) 1985, 1989, 1993
5 * The Regents of the University of California. All rights reserved. 7 * The Regents of the University of California. All rights reserved.
6 * 8 *
7 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
9 * are met: 11 * are met:
@@ -14,12 +16,12 @@
14 * documentation and/or other materials provided with the distribution. 16 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software 17 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement: 18 * must display the following acknowledgement:
17 * This product includes software developed by the University of 19 * This product includes software developed by the University of
18 * California, Berkeley and its contributors. 20 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors 21 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software 22 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission. 23 * without specific prior written permission.
22 * 24 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -53,80 +55,181 @@
53 * --Copyright-- 55 * --Copyright--
54 */ 56 */
55 57
58#ifndef INET6
59#define INET6
60#endif
61
56#if defined(LIBC_SCCS) && !defined(lint) 62#if defined(LIBC_SCCS) && !defined(lint)
57#if 0 63#if 0
58static char sccsid[] = "@(#)res_init.c 8.1 (Berkeley) 6/7/93"; 64static char sccsid[] = "@(#)res_init.c 8.1 (Berkeley) 6/7/93";
59static char rcsid[] = "$Id: res_init.c,v 4.9.1.1 1993/05/02 22:43:03 vixie Rel "; 65static char rcsid[] = "$From: res_init.c,v 8.7 1996/09/28 06:51:07 vixie Exp $";
60#else 66#else
61static char rcsid[] = "$NetBSD: res_init.c,v 1.8 1995/06/03 22:33:36 mycroft Exp $"; 67static char rcsid[] = "$OpenBSD: res_init.c,v 1.28 2003/01/28 04:58:00 marc Exp $";
62#endif 68#endif
63#endif /* LIBC_SCCS and not lint */ 69#endif /* LIBC_SCCS and not lint */
64 70
71#include <sys/types.h>
65#include <sys/param.h> 72#include <sys/param.h>
66#include <sys/socket.h> 73#include <sys/socket.h>
74#include <sys/time.h>
67#include <netinet/in.h> 75#include <netinet/in.h>
68#include <arpa/inet.h> 76#include <arpa/inet.h>
69#include <arpa/nameser.h> 77#include <arpa/nameser.h>
78
79#include <stdio.h>
80#include <ctype.h>
70#include <resolv.h> 81#include <resolv.h>
71#include <unistd.h> 82#include <unistd.h>
72#include <stdio.h>
73#include <stdlib.h> 83#include <stdlib.h>
74#include <string.h> 84#include <string.h>
85#ifdef INET6
86#include <netdb.h>
87#endif /* INET6 */
88
89#include "thread_private.h"
90
91/*-------------------------------------- info about "sortlist" --------------
92 * Marc Majka 1994/04/16
93 * Allan Nathanson 1994/10/29 (BIND 4.9.3.x)
94 *
95 * NetInfo resolver configuration directory support.
96 *
97 * Allow a NetInfo directory to be created in the hierarchy which
98 * contains the same information as the resolver configuration file.
99 *
100 * - The local domain name is stored as the value of the "domain" property.
101 * - The Internet address(es) of the name server(s) are stored as values
102 * of the "nameserver" property.
103 * - The name server addresses are stored as values of the "nameserver"
104 * property.
105 * - The search list for host-name lookup is stored as values of the
106 * "search" property.
107 * - The sortlist comprised of IP address netmask pairs are stored as
108 * values of the "sortlist" property. The IP address and optional netmask
109 * should be separated by a slash (/) or ampersand (&) character.
110 * - Internal resolver variables can be set from the value of the "options"
111 * property.
112 */
113
114static void res_setoptions(char *, char *);
75 115
76static void res_setoptions __P((char *, char *)); 116#ifdef RESOLVSORT
77static u_int32_t net_mask __P((struct in_addr)); 117static const char sort_mask[] = "/&";
118#define ISSORTMASK(ch) (strchr(sort_mask, ch) != NULL)
119static u_int32_t net_mask(struct in_addr);
120#endif
78 121
79/* 122/*
80 * Resolver state default settings 123 * Resolver state default settings.
81 */ 124 */
125volatile struct _thread_private_key_struct __THREAD_KEY_NAME(_res) = {
126 PTHREAD_ONCE_INIT, 0
127};
82 128
83struct __res_state _res = { 129struct __res_state _res
84 RES_TIMEOUT, /* retransmition time interval */ 130# if defined(__BIND_RES_TEXT)
85 4, /* number of times to retransmit */ 131 = { RES_TIMEOUT, } /* Motorola, et al. */
86 RES_DEFAULT, /* options flags */ 132# endif
87 1, /* number of name servers */ 133 ;
134#ifdef INET6
135volatile struct _thread_private_key_struct __THREAD_KEY_NAME(_res_ext) = {
136 PTHREAD_ONCE_INIT, 0
88}; 137};
89 138
139struct __res_state_ext _res_ext;
140#endif /* INET6 */
141
90/* 142/*
91 * Set up default settings. If the configuration file exist, the values 143 * Set up default settings. If the configuration file exist, the values
92 * there will have precedence. Otherwise, the server address is set to 144 * there will have precedence. Otherwise, the server address is set to
93 * INADDR_ANY and the default domain name comes from the gethostname(). 145 * INADDR_ANY and the default domain name comes from the gethostname().
94 * 146 *
95 * The configuration file should only be used if you want to redefine your 147 * An interrim version of this code (BIND 4.9, pre-4.4BSD) used 127.0.0.1
96 * domain or run without a server on your machine. 148 * rather than INADDR_ANY ("0.0.0.0") as the default name server address
149 * since it was noted that INADDR_ANY actually meant ``the first interface
150 * you "ifconfig"'d at boot time'' and if this was a SLIP or PPP interface,
151 * it had to be "up" in order for you to reach your own name server. It
152 * was later decided that since the recommended practice is to always
153 * install local static routes through 127.0.0.1 for all your network
154 * interfaces, that we could solve this problem without a code change.
155 *
156 * The configuration file should always be used, since it is the only way
157 * to specify a default domain. If you are running a server on your local
158 * machine, you should say "nameserver 0.0.0.0" or "nameserver 127.0.0.1"
159 * in the configuration file.
97 * 160 *
98 * Return 0 if completes successfully, -1 on error 161 * Return 0 if completes successfully, -1 on error
99 */ 162 */
163int
100res_init() 164res_init()
101{ 165{
166 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
167#ifdef INET6
168 struct __res_state_ext *_res_extp = _THREAD_PRIVATE(_res_ext, _res_ext,
169 &_res_ext);
170#endif
102 register FILE *fp; 171 register FILE *fp;
103 register char *cp, **pp, *net; 172 register char *cp, **pp;
104 register int n; 173 register int n;
105 char buf[BUFSIZ], buf2[BUFSIZ]; 174 char buf[BUFSIZ];
106 int nserv = 0; /* number of nameserver records read from file */ 175 int nserv = 0; /* number of nameserver records read from file */
107 int haveenv = 0; 176 int haveenv = 0;
108 int havesearch = 0; 177 int havesearch = 0;
178 size_t len;
179#ifdef RESOLVSORT
109 int nsort = 0; 180 int nsort = 0;
110 u_long mask; 181 char *net;
182#endif
183#ifndef RFC1535
184 int dots;
185#endif
186
187 /*
188 * These three fields used to be statically initialized. This made
189 * it hard to use this code in a shared library. It is necessary,
190 * now that we're doing dynamic initialization here, that we preserve
191 * the old semantics: if an application modifies one of these three
192 * fields of _res before res_init() is called, res_init() will not
193 * alter them. Of course, if an application is setting them to
194 * _zero_ before calling res_init(), hoping to override what used
195 * to be the static default, we can't detect it and unexpected results
196 * will follow. Zero for any of these fields would make no sense,
197 * so one can safely assume that the applications were already getting
198 * unexpected results.
199 *
200 * _res.options is tricky since some apps were known to diddle the bits
201 * before res_init() was first called. We can't replicate that semantic
202 * with dynamic initialization (they may have turned bits off that are
203 * set in RES_DEFAULT). Our solution is to declare such applications
204 * "broken". They could fool us by setting RES_INIT but none do (yet).
205 */
206 if (!_resp->retrans)
207 _resp->retrans = RES_TIMEOUT;
208 if (!_resp->retry)
209 _resp->retry = 4;
210 if (!(_resp->options & RES_INIT))
211 _resp->options = RES_DEFAULT;
111 212
112 _res.nsaddr.sin_len = sizeof(struct sockaddr_in);
113 _res.nsaddr.sin_family = AF_INET;
114 _res.nsaddr.sin_port = htons(NAMESERVER_PORT);
115#ifdef USELOOPBACK 213#ifdef USELOOPBACK
116 _res.nsaddr.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1); 214 _resp->nsaddr.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1);
117#else 215#else
118 _res.nsaddr.sin_addr.s_addr = INADDR_ANY; 216 _resp->nsaddr.sin_addr.s_addr = INADDR_ANY;
217#endif
218 _resp->nsaddr.sin_family = AF_INET;
219 _resp->nsaddr.sin_port = htons(NAMESERVER_PORT);
220 _resp->nsaddr.sin_len = sizeof(struct sockaddr_in);
221#ifdef INET6
222 if (sizeof(_res_extp->nsaddr) >= _resp->nsaddr.sin_len)
223 memcpy(&_res_extp->nsaddr, &_resp->nsaddr, _resp->nsaddr.sin_len);
119#endif 224#endif
120 _res.nscount = 1; 225 _resp->nscount = 1;
121 _res.ndots = 1; 226 _resp->ndots = 1;
122 _res.pfcode = 0; 227 _resp->pfcode = 0;
123 strncpy(_res.lookups, "f", sizeof _res.lookups); 228 strlcpy(_resp->lookups, "f", sizeof _resp->lookups);
124 229
125 /* Allow user to override the local domain definition */ 230 /* Allow user to override the local domain definition */
126 if ((cp = getenv("LOCALDOMAIN")) != NULL) { 231 if (issetugid() == 0 && (cp = getenv("LOCALDOMAIN")) != NULL) {
127 (void)strncpy(_res.defdname, cp, sizeof(_res.defdname) - 1); 232 strlcpy(_resp->defdname, cp, sizeof(_resp->defdname));
128 if ((cp = strpbrk(_res.defdname, " \t\n")) != NULL)
129 *cp = '\0';
130 haveenv++; 233 haveenv++;
131 234
132 /* 235 /*
@@ -136,11 +239,11 @@ res_init()
136 * one that they want to use as an individual (even more 239 * one that they want to use as an individual (even more
137 * important now that the rfc1535 stuff restricts searches) 240 * important now that the rfc1535 stuff restricts searches)
138 */ 241 */
139 cp = _res.defdname; 242 cp = _resp->defdname;
140 pp = _res.dnsrch; 243 pp = _resp->dnsrch;
141 *pp++ = cp; 244 *pp++ = cp;
142 for (n = 0; *cp && pp < _res.dnsrch + MAXDNSRCH; cp++) { 245 for (n = 0; *cp && pp < _resp->dnsrch + MAXDNSRCH; cp++) {
143 if (*cp == '\n') /* silly backwards compat */ 246 if (*cp == '\n') /* silly backwards compat */
144 break; 247 break;
145 else if (*cp == ' ' || *cp == '\t') { 248 else if (*cp == ' ' || *cp == '\t') {
146 *cp = 0; 249 *cp = 0;
@@ -158,16 +261,29 @@ res_init()
158 *pp++ = 0; 261 *pp++ = 0;
159 } 262 }
160 263
264#define MATCH(line, name) \
265 (!strncmp(line, name, sizeof(name) - 1) && \
266 (line[sizeof(name) - 1] == ' ' || \
267 line[sizeof(name) - 1] == '\t'))
268
161 if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) { 269 if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) {
162 strncpy(_res.lookups, "bf", sizeof _res.lookups); 270 strlcpy(_resp->lookups, "bf", sizeof _resp->lookups);
163 271
164 /* read the config file */ 272 /* read the config file */
165 while (fgets(buf, sizeof(buf), fp) != NULL) { 273 buf[0] = '\0';
274 while ((cp = fgetln(fp, &len)) != NULL) {
275 /* skip lines that are too long or zero length */
276 if (len >= sizeof(buf) || len == 0)
277 continue;
278 (void)memcpy(buf, cp, len);
279 buf[len] = '\0';
166 /* skip comments */ 280 /* skip comments */
167 if ((*buf == ';') || (*buf == '#')) 281 if ((cp = strpbrk(buf, ";#")) != NULL)
282 *cp = '\0';
283 if (buf[0] == '\0')
168 continue; 284 continue;
169 /* read default domain name */ 285 /* read default domain name */
170 if (!strncmp(buf, "domain", sizeof("domain") - 1)) { 286 if (MATCH(buf, "domain")) {
171 if (haveenv) /* skip if have from environ */ 287 if (haveenv) /* skip if have from environ */
172 continue; 288 continue;
173 cp = buf + sizeof("domain") - 1; 289 cp = buf + sizeof("domain") - 1;
@@ -175,18 +291,17 @@ res_init()
175 cp++; 291 cp++;
176 if ((*cp == '\0') || (*cp == '\n')) 292 if ((*cp == '\0') || (*cp == '\n'))
177 continue; 293 continue;
178 (void)strncpy(_res.defdname, cp, 294 strlcpy(_resp->defdname, cp, sizeof(_resp->defdname));
179 sizeof(_res.defdname) - 1); 295 if ((cp = strpbrk(_resp->defdname, " \t\n")) != NULL)
180 if ((cp = strpbrk(_res.defdname, " \t\n")) != NULL)
181 *cp = '\0'; 296 *cp = '\0';
182 havesearch = 0; 297 havesearch = 0;
183 continue; 298 continue;
184 } 299 }
185 /* lookup types */ 300 /* lookup types */
186 if (!strncmp(buf, "lookup", sizeof("lookup") -1)) { 301 if (MATCH(buf, "lookup")) {
187 char *sp = NULL; 302 char *sp = NULL;
188 303
189 bzero(_res.lookups, sizeof _res.lookups); 304 bzero(_resp->lookups, sizeof _resp->lookups);
190 cp = buf + sizeof("lookup") - 1; 305 cp = buf + sizeof("lookup") - 1;
191 for (n = 0;; cp++) { 306 for (n = 0;; cp++) {
192 if (n == MAXDNSLUS) 307 if (n == MAXDNSLUS)
@@ -194,14 +309,14 @@ res_init()
194 if ((*cp == '\0') || (*cp == '\n')) { 309 if ((*cp == '\0') || (*cp == '\n')) {
195 if (sp) { 310 if (sp) {
196 if (*sp=='y' || *sp=='b' || *sp=='f') 311 if (*sp=='y' || *sp=='b' || *sp=='f')
197 _res.lookups[n++] = *sp; 312 _resp->lookups[n++] = *sp;
198 sp = NULL; 313 sp = NULL;
199 } 314 }
200 break; 315 break;
201 } else if ((*cp == ' ') || (*cp == '\t') || (*cp == ',')) { 316 } else if ((*cp == ' ') || (*cp == '\t') || (*cp == ',')) {
202 if (sp) { 317 if (sp) {
203 if (*sp=='y' || *sp=='b' || *sp=='f') 318 if (*sp=='y' || *sp=='b' || *sp=='f')
204 _res.lookups[n++] = *sp; 319 _resp->lookups[n++] = *sp;
205 sp = NULL; 320 sp = NULL;
206 } 321 }
207 } else if (sp == NULL) 322 } else if (sp == NULL)
@@ -210,7 +325,7 @@ res_init()
210 continue; 325 continue;
211 } 326 }
212 /* set search list */ 327 /* set search list */
213 if (!strncmp(buf, "search", sizeof("search") - 1)) { 328 if (MATCH(buf, "search")) {
214 if (haveenv) /* skip if have from environ */ 329 if (haveenv) /* skip if have from environ */
215 continue; 330 continue;
216 cp = buf + sizeof("search") - 1; 331 cp = buf + sizeof("search") - 1;
@@ -218,18 +333,17 @@ res_init()
218 cp++; 333 cp++;
219 if ((*cp == '\0') || (*cp == '\n')) 334 if ((*cp == '\0') || (*cp == '\n'))
220 continue; 335 continue;
221 (void)strncpy(_res.defdname, cp, 336 strlcpy(_resp->defdname, cp, sizeof(_resp->defdname));
222 sizeof(_res.defdname) - 1); 337 if ((cp = strchr(_resp->defdname, '\n')) != NULL)
223 if ((cp = strchr(_res.defdname, '\n')) != NULL)
224 *cp = '\0'; 338 *cp = '\0';
225 /* 339 /*
226 * Set search list to be blank-separated strings 340 * Set search list to be blank-separated strings
227 * on rest of line. 341 * on rest of line.
228 */ 342 */
229 cp = _res.defdname; 343 cp = _resp->defdname;
230 pp = _res.dnsrch; 344 pp = _resp->dnsrch;
231 *pp++ = cp; 345 *pp++ = cp;
232 for (n = 0; *cp && pp < _res.dnsrch + MAXDNSRCH; cp++) { 346 for (n = 0; *cp && pp < _resp->dnsrch + MAXDNSRCH; cp++) {
233 if (*cp == ' ' || *cp == '\t') { 347 if (*cp == ' ' || *cp == '\t') {
234 *cp = 0; 348 *cp = 0;
235 n = 1; 349 n = 1;
@@ -247,130 +361,273 @@ res_init()
247 continue; 361 continue;
248 } 362 }
249 /* read nameservers to query */ 363 /* read nameservers to query */
250 if (!strncmp(buf, "nameserver", sizeof("nameserver") - 1) && 364 if (MATCH(buf, "nameserver") && nserv < MAXNS) {
251 nserv < MAXNS) { 365#ifdef INET6
252 struct in_addr a; 366 char *q;
367 struct addrinfo hints, *res;
368 char pbuf[NI_MAXSERV];
369#else
370 struct in_addr a;
371#endif /* INET6 */
253 372
254 cp = buf + sizeof("nameserver") - 1; 373 cp = buf + sizeof("nameserver") - 1;
255 while (*cp == ' ' || *cp == '\t') 374 while (*cp == ' ' || *cp == '\t')
256 cp++; 375 cp++;
376#ifdef INET6
377 if ((*cp == '\0') || (*cp == '\n'))
378 continue;
379 for (q = cp; *q; q++) {
380 if (isspace(*q)) {
381 *q = '\0';
382 break;
383 }
384 }
385 memset(&hints, 0, sizeof(hints));
386 hints.ai_flags = AI_NUMERICHOST;
387 hints.ai_socktype = SOCK_DGRAM;
388 snprintf(pbuf, sizeof(pbuf), "%u", NAMESERVER_PORT);
389 res = NULL;
390 if (getaddrinfo(cp, pbuf, &hints, &res) == 0 &&
391 res->ai_next == NULL) {
392 if (res->ai_addrlen <= sizeof(_res_extp->nsaddr_list[nserv])) {
393 memcpy(&_res_extp->nsaddr_list[nserv], res->ai_addr,
394 res->ai_addrlen);
395 } else {
396 memset(&_res_extp->nsaddr_list[nserv], 0,
397 sizeof(_res_extp->nsaddr_list[nserv]));
398 }
399 if (res->ai_addrlen <= sizeof(_resp->nsaddr_list[nserv])) {
400 memcpy(&_resp->nsaddr_list[nserv], res->ai_addr,
401 res->ai_addrlen);
402 } else {
403 memset(&_resp->nsaddr_list[nserv], 0,
404 sizeof(_resp->nsaddr_list[nserv]));
405 }
406 nserv++;
407 }
408 if (res)
409 freeaddrinfo(res);
410#else /* INET6 */
257 if ((*cp != '\0') && (*cp != '\n') && inet_aton(cp, &a)) { 411 if ((*cp != '\0') && (*cp != '\n') && inet_aton(cp, &a)) {
258 _res.nsaddr_list[nserv].sin_len = sizeof(struct sockaddr_in); 412 _resp->nsaddr_list[nserv].sin_addr = a;
259 _res.nsaddr_list[nserv].sin_family = AF_INET; 413 _resp->nsaddr_list[nserv].sin_family = AF_INET;
260 _res.nsaddr_list[nserv].sin_port = 414 _resp->nsaddr_list[nserv].sin_port =
261 htons(NAMESERVER_PORT); 415 htons(NAMESERVER_PORT);
262 _res.nsaddr_list[nserv].sin_addr = a; 416 _resp->nsaddr_list[nserv].sin_len =
417 sizeof(struct sockaddr_in);
263 nserv++; 418 nserv++;
264 } 419 }
420#endif /* INET6 */
265 continue; 421 continue;
266 } 422 }
267 if (!strncmp(buf, "sortlist", sizeof("sortlist") - 1)) { 423#ifdef RESOLVSORT
424 if (MATCH(buf, "sortlist")) {
268 struct in_addr a; 425 struct in_addr a;
426#ifdef INET6
427 struct in6_addr a6;
428 int m, i;
429 u_char *u;
430#endif /* INET6 */
269 431
270 cp = buf + sizeof("sortlist") - 1; 432 cp = buf + sizeof("sortlist") - 1;
271 while (*cp == ' ' || *cp == '\t') 433 while (nsort < MAXRESOLVSORT) {
272 cp++; 434 while (*cp == ' ' || *cp == '\t')
273 while (sscanf(cp,"%[0-9./]s", buf2) && nsort < MAXRESOLVSORT) { 435 cp++;
274 if (net = strchr(buf2, '/')) 436 if (*cp == '\0' || *cp == '\n' || *cp == ';')
275 *net = '\0'; 437 break;
276 if (inet_aton(buf2, &a)) { 438 net = cp;
277 _res.sort_list[nsort].addr = a; 439 while (*cp && !ISSORTMASK(*cp) && *cp != ';' &&
278 if (net && inet_aton(net+1, &a)) { 440 isascii(*cp) && !isspace(*cp))
279 _res.sort_list[nsort].mask = a.s_addr; 441 cp++;
442 n = *cp;
443 *cp = 0;
444 if (inet_aton(net, &a)) {
445 _resp->sort_list[nsort].addr = a;
446 if (ISSORTMASK(n)) {
447 *cp++ = n;
448 net = cp;
449 while (*cp && *cp != ';' &&
450 isascii(*cp) && !isspace(*cp))
451 cp++;
452 n = *cp;
453 *cp = 0;
454 if (inet_aton(net, &a)) {
455 _resp->sort_list[nsort].mask = a.s_addr;
456 } else {
457 _resp->sort_list[nsort].mask =
458 net_mask(_resp->sort_list[nsort].addr);
459 }
280 } else { 460 } else {
281 _res.sort_list[nsort].mask = 461 _resp->sort_list[nsort].mask =
282 net_mask(_res.sort_list[nsort].addr); 462 net_mask(_resp->sort_list[nsort].addr);
283 } 463 }
464#ifdef INET6
465 _res_extp->sort_list[nsort].af = AF_INET;
466 _res_extp->sort_list[nsort].addr.ina =
467 _resp->sort_list[nsort].addr;
468 _res_extp->sort_list[nsort].mask.ina.s_addr =
469 _resp->sort_list[nsort].mask;
470#endif /* INET6 */
284 nsort++; 471 nsort++;
285 } 472 }
286 if (net) 473#ifdef INET6
287 *net = '/'; 474 else if (inet_pton(AF_INET6, net, &a6) == 1) {
288 cp += strlen(buf2); 475 _res_extp->sort_list[nsort].af = AF_INET6;
289 while (*cp == ' ' || *cp == '\t') 476 _res_extp->sort_list[nsort].addr.in6a = a6;
290 cp++; 477 u = (u_char *)&_res_extp->sort_list[nsort].mask.in6a;
478 *cp++ = n;
479 net = cp;
480 while (*cp && *cp != ';' &&
481 isascii(*cp) && !isspace(*cp))
482 cp++;
483 m = n;
484 n = *cp;
485 *cp = 0;
486 switch (m) {
487 case '/':
488 m = atoi(net);
489 break;
490 case '&':
491 if (inet_pton(AF_INET6, net, u) == 1) {
492 m = -1;
493 break;
494 }
495 /*FALLTHRU*/
496 default:
497 m = sizeof(struct in6_addr) * NBBY;
498 break;
499 }
500 if (m >= 0) {
501 for (i = 0; i < sizeof(struct in6_addr); i++) {
502 if (m <= 0) {
503 *u = 0;
504 } else {
505 m -= NBBY;
506 *u = (u_char)~0;
507 if (m < 0)
508 *u <<= -m;
509 }
510 u++;
511 }
512 }
513 nsort++;
514 }
515#endif /* INET6 */
516 *cp = n;
291 } 517 }
292 continue; 518 continue;
293 } 519 }
294 if (!strncmp(buf, "options", sizeof("options") -1)) { 520#endif
521 if (MATCH(buf, "options")) {
295 res_setoptions(buf + sizeof("options") - 1, "conf"); 522 res_setoptions(buf + sizeof("options") - 1, "conf");
296 continue; 523 continue;
297 } 524 }
298 } 525 }
299 if (nserv > 1) 526 if (nserv > 1)
300 _res.nscount = nserv; 527 _resp->nscount = nserv;
301 _res.nsort = nsort; 528#ifdef RESOLVSORT
529 _resp->nsort = nsort;
530#endif
302 (void) fclose(fp); 531 (void) fclose(fp);
303 } 532 }
304 if (_res.defdname[0] == 0) { 533 if (_resp->defdname[0] == 0 &&
305 if (gethostname(buf, sizeof(_res.defdname) - 1) == 0 && 534 gethostname(buf, sizeof(_resp->defdname) - 1) == 0 &&
306 (cp = strchr(buf, '.'))) 535 (cp = strchr(buf, '.')) != NULL)
307 (void)strcpy(_res.defdname, cp + 1); 536 {
537 strlcpy(_resp->defdname, cp + 1,
538 sizeof(_resp->defdname));
308 } 539 }
309 540
310 /* find components of local domain that might be searched */ 541 /* find components of local domain that might be searched */
311 if (havesearch == 0) { 542 if (havesearch == 0) {
312 pp = _res.dnsrch; 543 pp = _resp->dnsrch;
313 *pp++ = _res.defdname; 544 *pp++ = _resp->defdname;
314#ifndef SEARCH_LOCAL_DOMAINS
315 *pp = NULL; 545 *pp = NULL;
316#else 546
317 for (cp = _res.defdname, n = 0; *cp; cp++) 547#ifndef RFC1535
318 if (*cp == '.') 548 dots = 0;
319 n++; 549 for (cp = _resp->defdname; *cp; cp++)
320 cp = _res.defdname; 550 dots += (*cp == '.');
321 for (; n >= LOCALDOMAINPARTS && pp < _res.dnsrch + MAXDFLSRCH; 551
322 n--) { 552 cp = _resp->defdname;
323 cp = strchr(cp, '.'); 553 while (pp < _resp->dnsrch + MAXDFLSRCH) {
324 *pp++ = ++cp; 554 if (dots < LOCALDOMAINPARTS)
555 break;
556 cp = strchr(cp, '.') + 1; /* we know there is one */
557 *pp++ = cp;
558 dots--;
325 } 559 }
326 *pp++ = 0; 560 *pp = NULL;
327#endif 561#ifdef DEBUG
562 if (_resp->options & RES_DEBUG) {
563 printf(";; res_init()... default dnsrch list:\n");
564 for (pp = _resp->dnsrch; *pp; pp++)
565 printf(";;\t%s\n", *pp);
566 printf(";;\t..END..\n");
567 }
568#endif /* DEBUG */
569#endif /* !RFC1535 */
328 } 570 }
329 571
330 if ((cp = getenv("RES_OPTIONS")) != NULL) 572 if (issetugid())
573 _resp->options |= RES_NOALIASES;
574 else if ((cp = getenv("RES_OPTIONS")) != NULL)
331 res_setoptions(cp, "env"); 575 res_setoptions(cp, "env");
332 _res.options |= RES_INIT; 576 _resp->options |= RES_INIT;
333 return (0); 577 return (0);
334} 578}
335 579
580/* ARGSUSED */
336static void 581static void
337res_setoptions(options, source) 582res_setoptions(options, source)
338 char *options, *source; 583 char *options, *source;
339{ 584{
585 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
340 char *cp = options; 586 char *cp = options;
341 int i; 587 char *endp;
588 long l;
342 589
343#ifdef DEBUG 590#ifdef DEBUG
344 if (_res.options & RES_DEBUG) { 591 if (_resp->options & RES_DEBUG)
345 printf(";; res_setoptions(\"%s\", \"%s\")...\n", 592 printf(";; res_setoptions(\"%s\", \"%s\")...\n",
346 options, source); 593 options, source);
347 }
348#endif 594#endif
349 while (*cp) { 595 while (*cp) {
350 /* skip leading and inner runs of spaces */ 596 /* skip leading and inner runs of spaces */
351 while (*cp == ' ' || *cp == '\t') 597 while (*cp == ' ' || *cp == '\t')
352 cp++; 598 cp++;
353 /* search for and process individual options */ 599 /* search for and process individual options */
354 if (!strncmp(cp, "ndots:", sizeof("ndots:")-1)) { 600 if (!strncmp(cp, "ndots:", sizeof("ndots:") - 1)) {
355 i = atoi(cp + sizeof("ndots:") - 1); 601 char *p = cp + sizeof("ndots:") - 1;
356 if (i <= RES_MAXNDOTS) 602 l = strtol(p, &endp, 10);
357 _res.ndots = i; 603 if (l >= 0 && endp != p &&
358 else 604 (*endp = '\0' || isspace(*endp))) {
359 _res.ndots = RES_MAXNDOTS; 605 if (l <= RES_MAXNDOTS)
606 _resp->ndots = l;
607 else
608 _resp->ndots = RES_MAXNDOTS;
360#ifdef DEBUG 609#ifdef DEBUG
361 if (_res.options & RES_DEBUG) { 610 if (_resp->options & RES_DEBUG)
362 printf(";;\tndots=%d\n", _res.ndots); 611 printf(";;\tndots=%u\n", _resp->ndots);
363 }
364#endif 612#endif
365 } else if (!strncmp(cp, "debug", sizeof("debug")-1)) { 613 }
614 } else if (!strncmp(cp, "debug", sizeof("debug") - 1)) {
366#ifdef DEBUG 615#ifdef DEBUG
367 if (!(_res.options & RES_DEBUG)) { 616 if (!(_resp->options & RES_DEBUG)) {
368 printf(";; res_setoptions(\"%s\", \"%s\")..\n", 617 printf(";; res_setoptions(\"%s\", \"%s\")..\n",
369 options, source); 618 options, source);
370 _res.options |= RES_DEBUG; 619 _resp->options |= RES_DEBUG;
371 } 620 }
372 printf(";;\tdebug\n"); 621 printf(";;\tdebug\n");
373#endif 622#endif
623 } else if (!strncmp(cp, "inet6", sizeof("inet6") - 1)) {
624 _resp->options |= RES_USE_INET6;
625 } else if (!strncmp(cp, "insecure1", sizeof("insecure1") - 1)) {
626 _resp->options |= RES_INSECURE1;
627 } else if (!strncmp(cp, "insecure2", sizeof("insecure2") - 1)) {
628 _resp->options |= RES_INSECURE2;
629 } else if (!strncmp(cp, "edns0", sizeof("edns0") - 1)) {
630 _resp->options |= RES_USE_EDNS0;
374 } else { 631 } else {
375 /* XXX - print a warning here? */ 632 /* XXX - print a warning here? */
376 } 633 }
@@ -380,6 +637,8 @@ res_setoptions(options, source)
380 } 637 }
381} 638}
382 639
640#ifdef RESOLVSORT
641/* XXX - should really support CIDR which means explicit masks always. */
383static u_int32_t 642static u_int32_t
384net_mask(in) /* XXX - should really use system's version of this */ 643net_mask(in) /* XXX - should really use system's version of this */
385 struct in_addr in; 644 struct in_addr in;
@@ -388,7 +647,8 @@ net_mask(in) /* XXX - should really use system's version of this */
388 647
389 if (IN_CLASSA(i)) 648 if (IN_CLASSA(i))
390 return (htonl(IN_CLASSA_NET)); 649 return (htonl(IN_CLASSA_NET));
391 if (IN_CLASSB(i)) 650 else if (IN_CLASSB(i))
392 return (htonl(IN_CLASSB_NET)); 651 return (htonl(IN_CLASSB_NET));
393 return (htonl(IN_CLASSC_NET)); 652 return (htonl(IN_CLASSC_NET));
394} 653}
654#endif
diff --git a/src/lib/libc/net/res_mkquery.c b/src/lib/libc/net/res_mkquery.c
index 25f025e147..bb8f1f0725 100644
--- a/src/lib/libc/net/res_mkquery.c
+++ b/src/lib/libc/net/res_mkquery.c
@@ -1,9 +1,11 @@
1/* $NetBSD: res_mkquery.c,v 1.5 1995/02/25 06:20:58 cgd Exp $ */ 1/* $OpenBSD: res_mkquery.c,v 1.13 2003/01/28 04:58:00 marc Exp $ */
2 2
3/*- 3/*
4 * ++Copyright++ 1985, 1993
5 * -
4 * Copyright (c) 1985, 1993 6 * Copyright (c) 1985, 1993
5 * The Regents of the University of California. All rights reserved. 7 * The Regents of the University of California. All rights reserved.
6 * 8 *
7 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
9 * are met: 11 * are met:
@@ -14,12 +16,12 @@
14 * documentation and/or other materials provided with the distribution. 16 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software 17 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement: 18 * must display the following acknowledgement:
17 * This product includes software developed by the University of 19 * This product includes software developed by the University of
18 * California, Berkeley and its contributors. 20 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors 21 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software 22 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission. 23 * without specific prior written permission.
22 * 24 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -56,98 +58,115 @@
56#if defined(LIBC_SCCS) && !defined(lint) 58#if defined(LIBC_SCCS) && !defined(lint)
57#if 0 59#if 0
58static char sccsid[] = "@(#)res_mkquery.c 8.1 (Berkeley) 6/4/93"; 60static char sccsid[] = "@(#)res_mkquery.c 8.1 (Berkeley) 6/4/93";
59static char rcsid[] = "$Id: res_mkquery.c,v 4.9.1.2 1993/05/17 10:00:01 vixie Exp "; 61static char rcsid[] = "$From: res_mkquery.c,v 8.5 1996/08/27 08:33:28 vixie Exp $";
60#else 62#else
61static char rcsid[] = "$NetBSD: res_mkquery.c,v 1.5 1995/02/25 06:20:58 cgd Exp $"; 63static char rcsid[] = "$OpenBSD: res_mkquery.c,v 1.13 2003/01/28 04:58:00 marc Exp $";
62#endif 64#endif
63#endif /* LIBC_SCCS and not lint */ 65#endif /* LIBC_SCCS and not lint */
64 66
67#include <sys/types.h>
65#include <sys/param.h> 68#include <sys/param.h>
66#include <netinet/in.h> 69#include <netinet/in.h>
67#include <arpa/nameser.h> 70#include <arpa/nameser.h>
68#include <resolv.h> 71
69#include <stdio.h> 72#include <stdio.h>
73#include <netdb.h>
74#include <resolv.h>
70#include <string.h> 75#include <string.h>
71 76
77#include "thread_private.h"
78
72/* 79/*
73 * Form all types of queries. 80 * Form all types of queries.
74 * Returns the size of the result or -1. 81 * Returns the size of the result or -1.
75 */ 82 */
83/* ARGSUSED */
84int
76res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen) 85res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen)
77 int op; /* opcode of query */ 86 int op; /* opcode of query */
78 const char *dname; /* domain name */ 87 const char *dname; /* domain name */
79 int class, type; /* class and type of query */ 88 int class, type; /* class and type of query */
80 const char *data; /* resource record data */ 89 const u_char *data; /* resource record data */
81 int datalen; /* length of data */ 90 int datalen; /* length of data */
82 const char *newrr_in; /* new rr for modify or append */ 91 const u_char *newrr_in; /* new rr for modify or append */
83 char *buf; /* buffer to put query */ 92 u_char *buf; /* buffer to put query */
84 int buflen; /* size of buffer */ 93 int buflen; /* size of buffer */
85{ 94{
95 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
86 register HEADER *hp; 96 register HEADER *hp;
87 register char *cp; 97 register u_char *cp, *ep;
88 register int n; 98 register int n;
89 struct rrec *newrr = (struct rrec *) newrr_in; 99 u_char *dnptrs[20], **dpp, **lastdnptr;
90 char *dnptrs[10], **dpp, **lastdnptr;
91 100
101 if ((_resp->options & RES_INIT) == 0 && res_init() == -1) {
102 h_errno = NETDB_INTERNAL;
103 return (-1);
104 }
92#ifdef DEBUG 105#ifdef DEBUG
93 if (_res.options & RES_DEBUG) 106 if (_resp->options & RES_DEBUG)
94 printf(";; res_mkquery(%d, %s, %d, %d)\n", 107 printf(";; res_mkquery(%d, %s, %d, %d)\n",
95 op, dname, class, type); 108 op, dname, class, type);
96#endif 109#endif
97 /* 110 /*
98 * Initialize header fields. 111 * Initialize header fields.
112 *
113 * A special random number generator is used to create non predictable
114 * and non repeating ids over a long period. It also avoids reuse
115 * by switching between two distinct number cycles.
99 */ 116 */
100 if ((buf == NULL) || (buflen < sizeof(HEADER))) 117
101 return(-1); 118 if ((buf == NULL) || (buflen < HFIXEDSZ))
102 bzero(buf, sizeof(HEADER)); 119 return (-1);
120 bzero(buf, HFIXEDSZ);
103 hp = (HEADER *) buf; 121 hp = (HEADER *) buf;
104 hp->id = htons(++_res.id); 122 _resp->id = res_randomid();
123 hp->id = htons(_resp->id);
105 hp->opcode = op; 124 hp->opcode = op;
106 hp->pr = (_res.options & RES_PRIMARY) != 0; 125 hp->rd = (_resp->options & RES_RECURSE) != 0;
107 hp->rd = (_res.options & RES_RECURSE) != 0;
108 hp->rcode = NOERROR; 126 hp->rcode = NOERROR;
109 cp = buf + sizeof(HEADER); 127 cp = buf + HFIXEDSZ;
110 buflen -= sizeof(HEADER); 128 ep = buf + buflen;
111 dpp = dnptrs; 129 dpp = dnptrs;
112 *dpp++ = buf; 130 *dpp++ = buf;
113 *dpp++ = NULL; 131 *dpp++ = NULL;
114 lastdnptr = dnptrs + sizeof(dnptrs)/sizeof(dnptrs[0]); 132 lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0];
115 /* 133 /*
116 * perform opcode specific processing 134 * perform opcode specific processing
117 */ 135 */
118 switch (op) { 136 switch (op) {
119 case QUERY: 137 case QUERY: /*FALLTHROUGH*/
120 if ((buflen -= QFIXEDSZ) < 0) 138 case NS_NOTIFY_OP:
121 return(-1); 139 if (ep - cp < QFIXEDSZ)
122 if ((n = dn_comp((u_char *)dname, (u_char *)cp, buflen, 140 return (-1);
123 (u_char **)dnptrs, (u_char **)lastdnptr)) < 0) 141 if ((n = dn_comp(dname, cp, ep - cp - QFIXEDSZ, dnptrs,
142 lastdnptr)) < 0)
124 return (-1); 143 return (-1);
125 cp += n; 144 cp += n;
126 buflen -= n; 145 __putshort(type, cp);
127 __putshort(type, (u_char *)cp); 146 cp += INT16SZ;
128 cp += sizeof(u_int16_t); 147 __putshort(class, cp);
129 __putshort(class, (u_char *)cp); 148 cp += INT16SZ;
130 cp += sizeof(u_int16_t);
131 hp->qdcount = htons(1); 149 hp->qdcount = htons(1);
132 if (op == QUERY || data == NULL) 150 if (op == QUERY || data == NULL)
133 break; 151 break;
134 /* 152 /*
135 * Make an additional record for completion domain. 153 * Make an additional record for completion domain.
136 */ 154 */
137 buflen -= RRFIXEDSZ; 155 if (ep - cp < RRFIXEDSZ)
138 if ((n = dn_comp((u_char *)data, (u_char *)cp, buflen, 156 return (-1);
139 (u_char **)dnptrs, (u_char **)lastdnptr)) < 0) 157 n = dn_comp((char *)data, cp, ep - cp - RRFIXEDSZ, dnptrs,
158 lastdnptr);
159 if (n < 0)
140 return (-1); 160 return (-1);
141 cp += n; 161 cp += n;
142 buflen -= n; 162 __putshort(T_NULL, cp);
143 __putshort(T_NULL, (u_char *)cp); 163 cp += INT16SZ;
144 cp += sizeof(u_int16_t); 164 __putshort(class, cp);
145 __putshort(class, (u_char *)cp); 165 cp += INT16SZ;
146 cp += sizeof(u_int16_t); 166 __putlong(0, cp);
147 __putlong(0, (u_char *)cp); 167 cp += INT32SZ;
148 cp += sizeof(u_int32_t); 168 __putshort(0, cp);
149 __putshort(0, (u_char *)cp); 169 cp += INT16SZ;
150 cp += sizeof(u_int16_t);
151 hp->arcount = htons(1); 170 hp->arcount = htons(1);
152 break; 171 break;
153 172
@@ -155,82 +174,73 @@ res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen)
155 /* 174 /*
156 * Initialize answer section 175 * Initialize answer section
157 */ 176 */
158 if (buflen < 1 + RRFIXEDSZ + datalen) 177 if (ep - cp < 1 + RRFIXEDSZ + datalen)
159 return (-1); 178 return (-1);
160 *cp++ = '\0'; /* no domain name */ 179 *cp++ = '\0'; /* no domain name */
161 __putshort(type, (u_char *)cp);
162 cp += sizeof(u_int16_t);
163 __putshort(class, (u_char *)cp);
164 cp += sizeof(u_int16_t);
165 __putlong(0, (u_char *)cp);
166 cp += sizeof(u_int32_t);
167 __putshort(datalen, (u_char *)cp);
168 cp += sizeof(u_int16_t);
169 if (datalen) {
170 bcopy(data, cp, datalen);
171 cp += datalen;
172 }
173 hp->ancount = htons(1);
174 break;
175
176#ifdef ALLOW_UPDATES
177 /*
178 * For UPDATEM/UPDATEMA, do UPDATED/UPDATEDA followed by UPDATEA
179 * (Record to be modified is followed by its replacement in msg.)
180 */
181 case UPDATEM:
182 case UPDATEMA:
183
184 case UPDATED:
185 /*
186 * The res code for UPDATED and UPDATEDA is the same; user
187 * calls them differently: specifies data for UPDATED; server
188 * ignores data if specified for UPDATEDA.
189 */
190 case UPDATEDA:
191 buflen -= RRFIXEDSZ + datalen;
192 if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
193 return (-1);
194 cp += n;
195 __putshort(type, cp); 180 __putshort(type, cp);
196 cp += sizeof(u_int16_t); 181 cp += INT16SZ;
197 __putshort(class, cp); 182 __putshort(class, cp);
198 cp += sizeof(u_int16_t); 183 cp += INT16SZ;
199 __putlong(0, cp); 184 __putlong(0, cp);
200 cp += sizeof(u_int32_t); 185 cp += INT32SZ;
201 __putshort(datalen, cp); 186 __putshort(datalen, cp);
202 cp += sizeof(u_int16_t); 187 cp += INT16SZ;
203 if (datalen) { 188 if (datalen) {
204 bcopy(data, cp, datalen); 189 bcopy(data, cp, datalen);
205 cp += datalen; 190 cp += datalen;
206 } 191 }
207 if ( (op == UPDATED) || (op == UPDATEDA) ) { 192 hp->ancount = htons(1);
208 hp->ancount = htons(0);
209 break;
210 }
211 /* Else UPDATEM/UPDATEMA, so drop into code for UPDATEA */
212
213 case UPDATEA: /* Add new resource record */
214 buflen -= RRFIXEDSZ + datalen;
215 if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
216 return (-1);
217 cp += n;
218 __putshort(newrr->r_type, cp);
219 cp += sizeof(u_int16_t);
220 __putshort(newrr->r_class, cp);
221 cp += sizeof(u_int16_t);
222 __putlong(0, cp);
223 cp += sizeof(u_int32_t);
224 __putshort(newrr->r_size, cp);
225 cp += sizeof(u_int16_t);
226 if (newrr->r_size) {
227 bcopy(newrr->r_data, cp, newrr->r_size);
228 cp += newrr->r_size;
229 }
230 hp->ancount = htons(0);
231 break; 193 break;
232 194
233#endif /* ALLOW_UPDATES */ 195 default:
196 return (-1);
234 } 197 }
235 return (cp - buf); 198 return (cp - buf);
236} 199}
200
201/* attach OPT pseudo-RR, as documented in RFC2671 (EDNS0). */
202int
203res_opt(n0, buf, buflen, anslen)
204 int n0;
205 u_char *buf; /* buffer to put query */
206 int buflen; /* size of buffer */
207 int anslen; /* answer buffer length */
208{
209 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
210 register HEADER *hp;
211 register u_char *cp, *ep;
212
213 hp = (HEADER *) buf;
214 cp = buf + n0;
215 ep = buf + buflen;
216
217 if (ep - cp < 1 + RRFIXEDSZ)
218 return -1;
219
220 *cp++ = 0; /* "." */
221
222 __putshort(T_OPT, cp); /* TYPE */
223 cp += INT16SZ;
224 if (anslen > 0xffff)
225 anslen = 0xffff; /* limit to 16bit value */
226 __putshort(anslen & 0xffff, cp); /* CLASS = UDP payload size */
227 cp += INT16SZ;
228 *cp++ = NOERROR; /* extended RCODE */
229 *cp++ = 0; /* EDNS version */
230 if (_resp->options & RES_USE_DNSSEC) {
231#ifdef DEBUG
232 if (_resp->options & RES_DEBUG)
233 printf(";; res_opt()... ENDS0 DNSSEC OK\n");
234#endif /* DEBUG */
235 __putshort(DNS_MESSAGEEXTFLAG_DO, cp); /* EDNS Z field */
236 cp += INT16SZ;
237 } else {
238 __putshort(0, cp); /* EDNS Z field */
239 cp += INT16SZ;
240 }
241 __putshort(0, cp); /* RDLEN */
242 cp += INT16SZ;
243 hp->arcount = htons(ntohs(hp->arcount) + 1);
244
245 return cp - buf;
246}
diff --git a/src/lib/libc/net/res_query.c b/src/lib/libc/net/res_query.c
index 7649462e56..1e949e8efa 100644
--- a/src/lib/libc/net/res_query.c
+++ b/src/lib/libc/net/res_query.c
@@ -1,9 +1,11 @@
1/* $NetBSD: res_query.c,v 1.9 1995/02/25 06:58:58 cgd Exp $ */ 1/* $OpenBSD: res_query.c,v 1.20 2003/01/28 04:58:00 marc Exp $ */
2 2
3/*- 3/*
4 * ++Copyright++ 1988, 1993
5 * -
4 * Copyright (c) 1988, 1993 6 * Copyright (c) 1988, 1993
5 * The Regents of the University of California. All rights reserved. 7 * The Regents of the University of California. All rights reserved.
6 * 8 *
7 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
9 * are met: 11 * are met:
@@ -14,12 +16,12 @@
14 * documentation and/or other materials provided with the distribution. 16 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software 17 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement: 18 * must display the following acknowledgement:
17 * This product includes software developed by the University of 19 * This product includes software developed by the University of
18 * California, Berkeley and its contributors. 20 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors 21 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software 22 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission. 23 * without specific prior written permission.
22 * 24 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -56,23 +58,28 @@
56#if defined(LIBC_SCCS) && !defined(lint) 58#if defined(LIBC_SCCS) && !defined(lint)
57#if 0 59#if 0
58static char sccsid[] = "@(#)res_query.c 8.1 (Berkeley) 6/4/93"; 60static char sccsid[] = "@(#)res_query.c 8.1 (Berkeley) 6/4/93";
59static char rcsid[] = "$Id: res_query.c,v 1.1 1993/06/01 09:42:14 vixie Exp vixie "; 61static char rcsid[] = "$From: res_query.c,v 8.9 1996/09/22 00:13:28 vixie Exp $";
60#else 62#else
61static char rcsid[] = "$NetBSD: res_query.c,v 1.9 1995/02/25 06:58:58 cgd Exp $"; 63static char rcsid[] = "$OpenBSD: res_query.c,v 1.20 2003/01/28 04:58:00 marc Exp $";
62#endif 64#endif
63#endif /* LIBC_SCCS and not lint */ 65#endif /* LIBC_SCCS and not lint */
64 66
67#include <sys/types.h>
65#include <sys/param.h> 68#include <sys/param.h>
66#include <netinet/in.h> 69#include <netinet/in.h>
67#include <arpa/inet.h> 70#include <arpa/inet.h>
68#include <arpa/nameser.h> 71#include <arpa/nameser.h>
72
73#include <stdio.h>
69#include <netdb.h> 74#include <netdb.h>
70#include <resolv.h> 75#include <resolv.h>
71#include <stdio.h>
72#include <ctype.h> 76#include <ctype.h>
73#include <errno.h> 77#include <errno.h>
74#include <stdlib.h> 78#include <stdlib.h>
75#include <string.h> 79#include <string.h>
80#include <unistd.h>
81
82#include "thread_private.h"
76 83
77#if PACKETSZ > 1024 84#if PACKETSZ > 1024
78#define MAXPACKET PACKETSZ 85#define MAXPACKET PACKETSZ
@@ -80,8 +87,9 @@ static char rcsid[] = "$NetBSD: res_query.c,v 1.9 1995/02/25 06:58:58 cgd Exp $"
80#define MAXPACKET 1024 87#define MAXPACKET 1024
81#endif 88#endif
82 89
83char *__hostalias __P((const char *)); 90const char *hostalias(const char *);
84int h_errno; 91int h_errno;
92extern int res_opt(int, u_char *, int, int);
85 93
86/* 94/*
87 * Formulate a normal query, send, and await answer. 95 * Formulate a normal query, send, and await answer.
@@ -90,68 +98,79 @@ int h_errno;
90 * if no error is indicated and the answer count is nonzero. 98 * if no error is indicated and the answer count is nonzero.
91 * Return the size of the response on success, -1 on error. 99 * Return the size of the response on success, -1 on error.
92 * Error number is left in h_errno. 100 * Error number is left in h_errno.
101 *
93 * Caller must parse answer and determine whether it answers the question. 102 * Caller must parse answer and determine whether it answers the question.
94 */ 103 */
104int
95res_query(name, class, type, answer, anslen) 105res_query(name, class, type, answer, anslen)
96 char *name; /* domain name */ 106 const char *name; /* domain name */
97 int class, type; /* class and type of query */ 107 int class, type; /* class and type of query */
98 u_char *answer; /* buffer to put answer */ 108 u_char *answer; /* buffer to put answer */
99 int anslen; /* size of answer buffer */ 109 int anslen; /* size of answer buffer */
100{ 110{
101 char buf[MAXPACKET]; 111 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
102 HEADER *hp; 112 u_char buf[MAXPACKET];
113 register HEADER *hp = (HEADER *) answer;
103 int n; 114 int n;
104 115
105 if ((_res.options & RES_INIT) == 0 && res_init() == -1) 116 hp->rcode = NOERROR; /* default */
117
118 if ((_resp->options & RES_INIT) == 0 && res_init() == -1) {
119 h_errno = NETDB_INTERNAL;
106 return (-1); 120 return (-1);
121 }
107#ifdef DEBUG 122#ifdef DEBUG
108 if (_res.options & RES_DEBUG) 123 if (_resp->options & RES_DEBUG)
109 printf(";; res_query(%s, %d, %d)\n", name, class, type); 124 printf(";; res_query(%s, %d, %d)\n", name, class, type);
110#endif 125#endif
111 n = res_mkquery(QUERY, name, class, type, (char *)NULL, 0, NULL, 126
112 buf, sizeof(buf)); 127 n = res_mkquery(QUERY, name, class, type, NULL, 0, NULL,
128 buf, sizeof(buf));
129 if (n > 0 && ((_resp->options & RES_USE_EDNS0) ||
130 (_resp->options & RES_USE_DNSSEC))) {
131 n = res_opt(n, buf, sizeof(buf), anslen);
132 }
113 133
114 if (n <= 0) { 134 if (n <= 0) {
115#ifdef DEBUG 135#ifdef DEBUG
116 if (_res.options & RES_DEBUG) 136 if (_resp->options & RES_DEBUG)
117 printf(";; res_query: mkquery failed\n"); 137 printf(";; res_query: mkquery failed\n");
118#endif 138#endif
119 h_errno = NO_RECOVERY; 139 h_errno = NO_RECOVERY;
120 return (n); 140 return (n);
121 } 141 }
122 n = res_send(buf, n, (char *)answer, anslen); 142 n = res_send(buf, n, answer, anslen);
123 if (n < 0) { 143 if (n < 0) {
124#ifdef DEBUG 144#ifdef DEBUG
125 if (_res.options & RES_DEBUG) 145 if (_resp->options & RES_DEBUG)
126 printf(";; res_query: send error\n"); 146 printf(";; res_query: send error\n");
127#endif 147#endif
128 h_errno = TRY_AGAIN; 148 h_errno = TRY_AGAIN;
129 return (n); 149 return (n);
130 } 150 }
131 151
132 hp = (HEADER *) answer;
133 if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) { 152 if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
134#ifdef DEBUG 153#ifdef DEBUG
135 if (_res.options & RES_DEBUG) 154 if (_resp->options & RES_DEBUG)
136 printf(";; rcode = %d, ancount=%d\n", hp->rcode, 155 printf(";; rcode = %u, ancount=%u\n", hp->rcode,
137 ntohs(hp->ancount)); 156 ntohs(hp->ancount));
138#endif 157#endif
139 switch (hp->rcode) { 158 switch (hp->rcode) {
140 case NXDOMAIN: 159 case NXDOMAIN:
141 h_errno = HOST_NOT_FOUND; 160 h_errno = HOST_NOT_FOUND;
142 break; 161 break;
143 case SERVFAIL: 162 case SERVFAIL:
144 h_errno = TRY_AGAIN; 163 h_errno = TRY_AGAIN;
145 break; 164 break;
146 case NOERROR: 165 case NOERROR:
147 h_errno = NO_DATA; 166 h_errno = NO_DATA;
148 break; 167 break;
149 case FORMERR: 168 case FORMERR:
150 case NOTIMP: 169 case NOTIMP:
151 case REFUSED: 170 case REFUSED:
152 default: 171 default:
153 h_errno = NO_RECOVERY; 172 h_errno = NO_RECOVERY;
154 break; 173 break;
155 } 174 }
156 return (-1); 175 return (-1);
157 } 176 }
@@ -162,9 +181,7 @@ res_query(name, class, type, answer, anslen)
162 * Formulate a normal query, send, and retrieve answer in supplied buffer. 181 * Formulate a normal query, send, and retrieve answer in supplied buffer.
163 * Return the size of the response on success, -1 on error. 182 * Return the size of the response on success, -1 on error.
164 * If enabled, implement search rules until answer or unrecoverable failure 183 * If enabled, implement search rules until answer or unrecoverable failure
165 * is detected. Error number is left in h_errno. 184 * is detected. Error code, if any, is left in h_errno.
166 * Only useful for queries in the same name hierarchy as the local host
167 * (not, for example, for host address-to-name lookups in domain in-addr.arpa).
168 */ 185 */
169int 186int
170res_search(name, class, type, answer, anslen) 187res_search(name, class, type, answer, anslen)
@@ -173,28 +190,30 @@ res_search(name, class, type, answer, anslen)
173 u_char *answer; /* buffer to put answer */ 190 u_char *answer; /* buffer to put answer */
174 int anslen; /* size of answer */ 191 int anslen; /* size of answer */
175{ 192{
176 register char *cp, **domain; 193 register const char *cp, * const *domain;
177 int dots, trailing_dot, ret, got_nodata, saved_herrno, tried_as_is; 194 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
195 HEADER *hp = (HEADER *) answer;
196 u_int dots;
197 int trailing_dot, ret, saved_herrno;
198 int got_nodata = 0, got_servfail = 0, tried_as_is = 0;
178 199
179 if ((_res.options & RES_INIT) == 0 && res_init() == -1) 200 if ((_resp->options & RES_INIT) == 0 && res_init() == -1) {
201 h_errno = NETDB_INTERNAL;
180 return (-1); 202 return (-1);
181 203 }
182 got_nodata = 0;
183 errno = 0; 204 errno = 0;
184 h_errno = HOST_NOT_FOUND; /* default, if we never query */ 205 h_errno = HOST_NOT_FOUND; /* default, if we never query */
185 dots = 0; 206 dots = 0;
186 for (cp = (char *)name; *cp; cp++) { 207 for (cp = name; *cp; cp++)
187 if (*cp == '.') 208 dots += (*cp == '.');
188 dots++;
189 }
190 trailing_dot = 0; 209 trailing_dot = 0;
191 if ((cp > name) && (*--cp == '.')) 210 if (cp > name && *--cp == '.')
192 trailing_dot++; 211 trailing_dot++;
193 212
194 /* 213 /*
195 * if there aren't any dots, it could be a user-level alias 214 * if there aren't any dots, it could be a user-level alias
196 */ 215 */
197 if (!dots && (cp = __hostalias(name))) 216 if (!dots && (cp = __hostalias(name)) != NULL)
198 return (res_query(cp, class, type, answer, anslen)); 217 return (res_query(cp, class, type, answer, anslen));
199 218
200 /* 219 /*
@@ -202,8 +221,7 @@ res_search(name, class, type, answer, anslen)
202 * 'as is'. The threshold can be set with the "ndots" option. 221 * 'as is'. The threshold can be set with the "ndots" option.
203 */ 222 */
204 saved_herrno = -1; 223 saved_herrno = -1;
205 tried_as_is = 0; 224 if (dots >= _resp->ndots) {
206 if (dots >= _res.ndots) {
207 ret = res_querydomain(name, NULL, class, type, answer, anslen); 225 ret = res_querydomain(name, NULL, class, type, answer, anslen);
208 if (ret > 0) 226 if (ret > 0)
209 return (ret); 227 return (ret);
@@ -217,15 +235,19 @@ res_search(name, class, type, answer, anslen)
217 * - there is at least one dot, there is no trailing dot, 235 * - there is at least one dot, there is no trailing dot,
218 * and RES_DNSRCH is set. 236 * and RES_DNSRCH is set.
219 */ 237 */
220 if ((!dots && (_res.options & RES_DEFNAMES)) || 238 if ((!dots && (_resp->options & RES_DEFNAMES)) ||
221 (dots && !trailing_dot && (_res.options & RES_DNSRCH))) { 239 (dots && !trailing_dot && (_resp->options & RES_DNSRCH))) {
222 for (domain = _res.dnsrch; *domain; domain++) { 240 int done = 0;
223 int done = 0; 241
242 for (domain = (const char * const *)_resp->dnsrch;
243 *domain && !done;
244 domain++) {
224 245
225 ret = res_querydomain(name, *domain, class, type, 246 ret = res_querydomain(name, *domain, class, type,
226 answer, anslen); 247 answer, anslen);
227 if (ret > 0) 248 if (ret > 0)
228 return (ret); 249 return (ret);
250
229 /* 251 /*
230 * If no server present, give up. 252 * If no server present, give up.
231 * If name isn't found in this domain, 253 * If name isn't found in this domain,
@@ -251,24 +273,27 @@ res_search(name, class, type, answer, anslen)
251 case HOST_NOT_FOUND: 273 case HOST_NOT_FOUND:
252 /* keep trying */ 274 /* keep trying */
253 break; 275 break;
276 case TRY_AGAIN:
277 if (hp->rcode == SERVFAIL) {
278 /* try next search element, if any */
279 got_servfail++;
280 break;
281 }
282 /* FALLTHROUGH */
254 default: 283 default:
255 /* anything else implies that we're done */ 284 /* anything else implies that we're done */
256 done++; 285 done++;
257 } 286 }
258 /* 287
259 * if we got here for some reason other than DNSRCH, 288 /* if we got here for some reason other than DNSRCH,
260 * we only wanted one iteration of the loop, so stop. 289 * we only wanted one iteration of the loop, so stop.
261 */ 290 */
262 if (!(_res.options & RES_DNSRCH)) 291 if (!(_resp->options & RES_DNSRCH))
263 done++; 292 done++;
264
265 if (done)
266 break;
267 } 293 }
268 } 294 }
269 295
270 /* 296 /* if we have not already tried the name "as is", do that now.
271 * if we have not already tried the name "as is", do that now.
272 * note that we do this regardless of how many dots were in the 297 * note that we do this regardless of how many dots were in the
273 * name or whether it ends with a dot. 298 * name or whether it ends with a dot.
274 */ 299 */
@@ -276,11 +301,9 @@ res_search(name, class, type, answer, anslen)
276 ret = res_querydomain(name, NULL, class, type, answer, anslen); 301 ret = res_querydomain(name, NULL, class, type, answer, anslen);
277 if (ret > 0) 302 if (ret > 0)
278 return (ret); 303 return (ret);
279 saved_herrno = h_errno;
280 } 304 }
281 305
282 /* 306 /* if we got here, we didn't satisfy the search.
283 * if we got here, we didn't satisfy the search.
284 * if we did an initial full query, return that query's h_errno 307 * if we did an initial full query, return that query's h_errno
285 * (note that we wouldn't be here if that query had succeeded). 308 * (note that we wouldn't be here if that query had succeeded).
286 * else if we ever got a nodata, send that back as the reason. 309 * else if we ever got a nodata, send that back as the reason.
@@ -291,6 +314,8 @@ res_search(name, class, type, answer, anslen)
291 h_errno = saved_herrno; 314 h_errno = saved_herrno;
292 else if (got_nodata) 315 else if (got_nodata)
293 h_errno = NO_DATA; 316 h_errno = NO_DATA;
317 else if (got_servfail)
318 h_errno = TRY_AGAIN;
294 return (-1); 319 return (-1);
295} 320}
296 321
@@ -298,20 +323,26 @@ res_search(name, class, type, answer, anslen)
298 * Perform a call on res_query on the concatenation of name and domain, 323 * Perform a call on res_query on the concatenation of name and domain,
299 * removing a trailing dot from name if domain is NULL. 324 * removing a trailing dot from name if domain is NULL.
300 */ 325 */
326int
301res_querydomain(name, domain, class, type, answer, anslen) 327res_querydomain(name, domain, class, type, answer, anslen)
302 char *name, *domain; 328 const char *name, *domain;
303 int class, type; /* class and type of query */ 329 int class, type; /* class and type of query */
304 u_char *answer; /* buffer to put answer */ 330 u_char *answer; /* buffer to put answer */
305 int anslen; /* size of answer */ 331 int anslen; /* size of answer */
306{ 332{
307 char nbuf[2*MAXDNAME+2]; 333 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
308 char *longname = nbuf; 334 char nbuf[MAXDNAME*2+1+1];
335 const char *longname = nbuf;
309 int n; 336 int n;
310 337
338 if ((_resp->options & RES_INIT) == 0 && res_init() == -1) {
339 h_errno = NETDB_INTERNAL;
340 return (-1);
341 }
311#ifdef DEBUG 342#ifdef DEBUG
312 if (_res.options & RES_DEBUG) 343 if (_resp->options & RES_DEBUG)
313 printf(";; res_querydomain(%s, %s, %d, %d)\n", 344 printf(";; res_querydomain(%s, %s, %d, %d)\n",
314 name, domain, class, type); 345 name, domain?domain:"<Nil>", class, type);
315#endif 346#endif
316 if (domain == NULL) { 347 if (domain == NULL) {
317 /* 348 /*
@@ -325,38 +356,52 @@ res_querydomain(name, domain, class, type, answer, anslen)
325 } else 356 } else
326 longname = name; 357 longname = name;
327 } else 358 } else
328 (void)sprintf(nbuf, "%.*s.%.*s", 359 snprintf(nbuf, sizeof nbuf, "%.*s.%.*s",
329 MAXDNAME, name, MAXDNAME, domain); 360 MAXDNAME, name, MAXDNAME, domain);
330 361
331 return (res_query(longname, class, type, answer, anslen)); 362 return (res_query(longname, class, type, answer, anslen));
332} 363}
333 364
334char * 365const char *
335__hostalias(name) 366hostalias(name)
336 register const char *name; 367 register const char *name;
337{ 368{
369 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
338 register char *cp1, *cp2; 370 register char *cp1, *cp2;
339 FILE *fp; 371 FILE *fp;
340 char *file, *getenv(), *strcpy(), *strncpy(); 372 char *file;
341 char buf[BUFSIZ]; 373 char buf[BUFSIZ];
342 static char abuf[MAXDNAME]; 374 static char abuf[MAXDNAME];
375 size_t len;
343 376
377 if (_resp->options & RES_NOALIASES)
378 return (NULL);
344 file = getenv("HOSTALIASES"); 379 file = getenv("HOSTALIASES");
345 if (file == NULL || (fp = fopen(file, "r")) == NULL) 380 if (issetugid() != 0 || file == NULL || (fp = fopen(file, "r")) == NULL)
346 return (NULL); 381 return (NULL);
347 buf[sizeof(buf) - 1] = '\0'; 382 setbuf(fp, NULL);
348 while (fgets(buf, sizeof(buf), fp)) { 383 while ((cp1 = fgetln(fp, &len)) != NULL) {
349 for (cp1 = buf; *cp1 && !isspace(*cp1); ++cp1); 384 if (cp1[len-1] == '\n')
385 len--;
386 if (len >= sizeof(buf) || len == 0)
387 continue;
388 (void)memcpy(buf, cp1, len);
389 buf[len] = '\0';
390
391 for (cp1 = buf; *cp1 && !isspace(*cp1); ++cp1)
392 ;
350 if (!*cp1) 393 if (!*cp1)
351 break; 394 break;
352 *cp1 = '\0'; 395 *cp1 = '\0';
353 if (!strcasecmp(buf, name)) { 396 if (!strcasecmp(buf, name)) {
354 while (isspace(*++cp1)); 397 while (isspace(*++cp1))
398 ;
355 if (!*cp1) 399 if (!*cp1)
356 break; 400 break;
357 for (cp2 = cp1 + 1; *cp2 && !isspace(*cp2); ++cp2); 401 for (cp2 = cp1 + 1; *cp2 && !isspace(*cp2); ++cp2)
358 abuf[sizeof(abuf) - 1] = *cp2 = '\0'; 402 ;
359 (void)strncpy(abuf, cp1, sizeof(abuf) - 1); 403 *cp2 = '\0';
404 strlcpy(abuf, cp1, sizeof(abuf));
360 fclose(fp); 405 fclose(fp);
361 return (abuf); 406 return (abuf);
362 } 407 }
diff --git a/src/lib/libc/net/res_random.c b/src/lib/libc/net/res_random.c
new file mode 100644
index 0000000000..c739e4a952
--- /dev/null
+++ b/src/lib/libc/net/res_random.c
@@ -0,0 +1,229 @@
1/* $OpenBSD: res_random.c,v 1.12 2002/06/27 10:14:02 itojun Exp $ */
2
3/*
4 * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>
5 * All rights reserved.
6 *
7 * Theo de Raadt <deraadt@openbsd.org> came up with the idea of using
8 * such a mathematical system to generate more random (yet non-repeating)
9 * ids to solve the resolver/named problem. But Niels designed the
10 * actual system based on the constraints.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. All advertising materials mentioning features or use of this software
21 * must display the following acknowledgement:
22 * This product includes software developed by Niels Provos.
23 * 4. The name of the author may not be used to endorse or promote products
24 * derived from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
27 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
28 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
29 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
30 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
31 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
35 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 */
37
38/*
39 * seed = random 15bit
40 * n = prime, g0 = generator to n,
41 * j = random so that gcd(j,n-1) == 1
42 * g = g0^j mod n will be a generator again.
43 *
44 * X[0] = random seed.
45 * X[n] = a*X[n-1]+b mod m is a Linear Congruential Generator
46 * with a = 7^(even random) mod m,
47 * b = random with gcd(b,m) == 1
48 * m = 31104 and a maximal period of m-1.
49 *
50 * The transaction id is determined by:
51 * id[n] = seed xor (g^X[n] mod n)
52 *
53 * Effectivly the id is restricted to the lower 15 bits, thus
54 * yielding two different cycles by toggling the msb on and off.
55 * This avoids reuse issues caused by reseeding.
56 *
57 * The 16 bit space is very small and brute force attempts are
58 * entirly feasible, we skip a random number of transaction ids
59 * so that an attacker will not get sequential ids.
60 */
61
62#include <sys/types.h>
63#include <netinet/in.h>
64#include <sys/time.h>
65#include <resolv.h>
66
67#include <unistd.h>
68#include <stdlib.h>
69#include <string.h>
70
71#define RU_OUT 180 /* Time after wich will be reseeded */
72#define RU_MAX 30000 /* Uniq cycle, avoid blackjack prediction */
73#define RU_GEN 2 /* Starting generator */
74#define RU_N 32749 /* RU_N-1 = 2*2*3*2729 */
75#define RU_AGEN 7 /* determine ru_a as RU_AGEN^(2*rand) */
76#define RU_M 31104 /* RU_M = 2^7*3^5 - don't change */
77
78#define PFAC_N 3
79const static u_int16_t pfacts[PFAC_N] = {
80 2,
81 3,
82 2729
83};
84
85static u_int16_t ru_x;
86static u_int16_t ru_seed, ru_seed2;
87static u_int16_t ru_a, ru_b;
88static u_int16_t ru_g;
89static u_int16_t ru_counter = 0;
90static u_int16_t ru_msb = 0;
91static long ru_reseed;
92static u_int32_t tmp; /* Storage for unused random */
93static struct timeval tv;
94
95static u_int16_t pmod(u_int16_t, u_int16_t, u_int16_t);
96static void res_initid(void);
97
98/*
99 * Do a fast modular exponation, returned value will be in the range
100 * of 0 - (mod-1)
101 */
102
103static u_int16_t
104pmod(u_int16_t gen, u_int16_t exp, u_int16_t mod)
105{
106 u_int16_t s, t, u;
107
108 s = 1;
109 t = gen;
110 u = exp;
111
112 while (u) {
113 if (u & 1)
114 s = (s*t) % mod;
115 u >>= 1;
116 t = (t*t) % mod;
117 }
118 return (s);
119}
120
121/*
122 * Initializes the seed and chooses a suitable generator. Also toggles
123 * the msb flag. The msb flag is used to generate two distinct
124 * cycles of random numbers and thus avoiding reuse of ids.
125 *
126 * This function is called from res_randomid() when needed, an
127 * application does not have to worry about it.
128 */
129static void
130res_initid()
131{
132 u_int16_t j, i;
133 int noprime = 1;
134
135 tmp = arc4random();
136 ru_x = (tmp & 0xFFFF) % RU_M;
137
138 /* 15 bits of random seed */
139 ru_seed = (tmp >> 16) & 0x7FFF;
140 tmp = arc4random();
141 ru_seed2 = tmp & 0x7FFF;
142
143 tmp = arc4random();
144
145 /* Determine the LCG we use */
146 ru_b = (tmp & 0xfffe) | 1;
147 ru_a = pmod(RU_AGEN, (tmp >> 16) & 0xfffe, RU_M);
148 while (ru_b % 3 == 0)
149 ru_b += 2;
150
151 tmp = arc4random();
152 j = tmp % RU_N;
153 tmp = tmp >> 16;
154
155 /*
156 * Do a fast gcd(j,RU_N-1), so we can find a j with
157 * gcd(j, RU_N-1) == 1, giving a new generator for
158 * RU_GEN^j mod RU_N
159 */
160
161 while (noprime) {
162 for (i=0; i<PFAC_N; i++)
163 if (j%pfacts[i] == 0)
164 break;
165
166 if (i>=PFAC_N)
167 noprime = 0;
168 else
169 j = (j+1) % RU_N;
170 }
171
172 ru_g = pmod(RU_GEN,j,RU_N);
173 ru_counter = 0;
174
175 gettimeofday(&tv, NULL);
176 ru_reseed = tv.tv_sec + RU_OUT;
177 ru_msb = ru_msb == 0x8000 ? 0 : 0x8000;
178}
179
180u_int
181res_randomid()
182{
183 int i, n;
184
185 gettimeofday(&tv, NULL);
186 if (ru_counter >= RU_MAX || tv.tv_sec > ru_reseed)
187 res_initid();
188
189 if (!tmp)
190 tmp = arc4random();
191
192 /* Skip a random number of ids */
193 n = tmp & 0x7; tmp = tmp >> 3;
194 if (ru_counter + n >= RU_MAX)
195 res_initid();
196
197 for (i=0; i<=n; i++)
198 /* Linear Congruential Generator */
199 ru_x = (ru_a*ru_x + ru_b) % RU_M;
200
201 ru_counter += i;
202
203 return (ru_seed ^ pmod(ru_g,ru_seed2 ^ ru_x,RU_N)) | ru_msb;
204}
205
206#if 0
207void
208main(int argc, char **argv)
209{
210 int i, n;
211 u_int16_t wert;
212
213 res_initid();
214
215 printf("Generator: %u\n", ru_g);
216 printf("Seed: %u\n", ru_seed);
217 printf("Reseed at %ld\n", ru_reseed);
218 printf("Ru_X: %u\n", ru_x);
219 printf("Ru_A: %u\n", ru_a);
220 printf("Ru_B: %u\n", ru_b);
221
222 n = atoi(argv[1]);
223 for (i=0;i<n;i++) {
224 wert = res_randomid();
225 printf("%06d\n", wert);
226 }
227}
228#endif
229
diff --git a/src/lib/libc/net/res_send.c b/src/lib/libc/net/res_send.c
index e608358180..9e2c2e7169 100644
--- a/src/lib/libc/net/res_send.c
+++ b/src/lib/libc/net/res_send.c
@@ -1,9 +1,11 @@
1/* $NetBSD: res_send.c,v 1.4 1995/02/25 06:21:01 cgd Exp $ */ 1/* $OpenBSD: res_send.c,v 1.14 2003/03/04 00:19:24 itojun Exp $ */
2 2
3/*- 3/*
4 * ++Copyright++ 1985, 1989, 1993
5 * -
4 * Copyright (c) 1985, 1989, 1993 6 * Copyright (c) 1985, 1989, 1993
5 * The Regents of the University of California. All rights reserved. 7 * The Regents of the University of California. All rights reserved.
6 * 8 *
7 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
9 * are met: 11 * are met:
@@ -14,12 +16,12 @@
14 * documentation and/or other materials provided with the distribution. 16 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software 17 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement: 18 * must display the following acknowledgement:
17 * This product includes software developed by the University of 19 * This product includes software developed by the University of
18 * California, Berkeley and its contributors. 20 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors 21 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software 22 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission. 23 * without specific prior written permission.
22 * 24 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -53,19 +55,31 @@
53 * --Copyright-- 55 * --Copyright--
54 */ 56 */
55 57
58#ifndef INET6
59#define INET6
60#endif
61
56#if defined(LIBC_SCCS) && !defined(lint) 62#if defined(LIBC_SCCS) && !defined(lint)
57#if 0 63#if 0
58static char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93"; 64static char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93";
59static char rcsid[] = "$Id: res_send.c,v 4.9.1.1 1993/05/02 22:43:03 vixie Rel "; 65static char rcsid[] = "$From: res_send.c,v 8.12 1996/10/08 04:51:06 vixie Exp $";
60#else 66#else
61static char rcsid[] = "$NetBSD: res_send.c,v 1.4 1995/02/25 06:21:01 cgd Exp $"; 67static char rcsid[] = "$OpenBSD: res_send.c,v 1.14 2003/03/04 00:19:24 itojun Exp $";
62#endif 68#endif
63#endif /* LIBC_SCCS and not lint */ 69#endif /* LIBC_SCCS and not lint */
64 70
71 /* change this to "0"
72 * if you talk to a lot
73 * of multi-homed SunOS
74 * ("broken") name servers.
75 */
76#define CHECK_SRVR_ADDR 1 /* XXX - should be in options.h */
77
65/* 78/*
66 * Send query to name server and wait for reply. 79 * Send query to name server and wait for reply.
67 */ 80 */
68 81
82#include <sys/types.h>
69#include <sys/param.h> 83#include <sys/param.h>
70#include <sys/time.h> 84#include <sys/time.h>
71#include <sys/socket.h> 85#include <sys/socket.h>
@@ -73,16 +87,24 @@ static char rcsid[] = "$NetBSD: res_send.c,v 1.4 1995/02/25 06:21:01 cgd Exp $";
73#include <netinet/in.h> 87#include <netinet/in.h>
74#include <arpa/nameser.h> 88#include <arpa/nameser.h>
75#include <arpa/inet.h> 89#include <arpa/inet.h>
90
76#include <stdio.h> 91#include <stdio.h>
92#include <netdb.h>
77#include <errno.h> 93#include <errno.h>
78#include <resolv.h> 94#include <resolv.h>
79#include <unistd.h> 95#include <stdlib.h>
80#include <string.h> 96#include <string.h>
97#include <unistd.h>
98
99#include "thread_private.h"
81 100
82static int s = -1; /* socket used for communications */ 101static int s = -1; /* socket used for communications */
83static struct sockaddr no_addr; 102static int connected = 0; /* is the socket connected */
103static int vc = 0; /* is the socket a virtual ciruit? */
104static int af = 0; /* address family of socket */
84 105
85#ifndef FD_SET 106#ifndef FD_SET
107/* XXX - should be in portability.h */
86#define NFDBITS 32 108#define NFDBITS 32
87#define FD_SETSIZE 32 109#define FD_SETSIZE 32
88#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS))) 110#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
@@ -91,121 +113,403 @@ static struct sockaddr no_addr;
91#define FD_ZERO(p) bzero((char *)(p), sizeof(*(p))) 113#define FD_ZERO(p) bzero((char *)(p), sizeof(*(p)))
92#endif 114#endif
93 115
94res_send(buf, buflen, answer, anslen) 116#define CAN_RECONNECT 1
95 const char *buf; 117
96 int buflen; 118#ifndef DEBUG
97 char *answer; 119# define Dprint(cond, args) /*empty*/
98 int anslen; 120# define DprintQ(cond, args, query, size) /*empty*/
121# define Aerror(file, string, error, address) /*empty*/
122# define Perror(file, string, error) /*empty*/
123#else
124# define Dprint(cond, args) if (cond) {fprintf args;} else {}
125# define DprintQ(cond, args, query, size) if (cond) {\
126 fprintf args;\
127 __fp_nquery(query, size, stdout);\
128 } else {}
129static char abuf[NI_MAXHOST];
130static char pbuf[NI_MAXSERV];
131static void Aerror(FILE *, char *, int, struct sockaddr *);
132static void Perror(FILE *, char *, int);
133
134 static void
135 Aerror(file, string, error, address)
136 FILE *file;
137 char *string;
138 int error;
139 struct sockaddr *address;
140 {
141 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
142 int save = errno;
143
144 if (_resp->options & RES_DEBUG) {
145 if (getnameinfo(address, address->sa_len, abuf, sizeof(abuf),
146 pbuf, sizeof(pbuf),
147 NI_NUMERICHOST|NI_NUMERICSERV|NI_WITHSCOPEID) != 0) {
148 strlcpy(abuf, "?", sizeof(abuf));
149 strlcpy(pbuf, "?", sizeof(pbuf));
150 }
151 fprintf(file, "res_send: %s ([%s].%s): %s\n",
152 string, abuf, pbuf, strerror(error));
153 }
154 errno = save;
155 }
156 static void
157 Perror(file, string, error)
158 FILE *file;
159 char *string;
160 int error;
161 {
162 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
163 int save = errno;
164
165 if (_resp->options & RES_DEBUG) {
166 fprintf(file, "res_send: %s: %s\n",
167 string, strerror(error));
168 }
169 errno = save;
170 }
171#endif
172
173static res_send_qhook Qhook = NULL;
174static res_send_rhook Rhook = NULL;
175
176void
177res_send_setqhook(hook)
178 res_send_qhook hook;
99{ 179{
100 register int n; 180
101 int try, v_circuit, resplen, ns; 181 Qhook = hook;
102 int gotsomewhere = 0, connected = 0; 182}
103 int connreset = 0; 183
104 u_short id, len; 184void
105 char *cp; 185res_send_setrhook(hook)
106 fd_set dsmask; 186 res_send_rhook hook;
107 struct timeval timeout; 187{
108 HEADER *hp = (HEADER *) buf; 188
109 HEADER *anhp = (HEADER *) answer; 189 Rhook = hook;
110 u_int badns; /* XXX NSMAX can't exceed #/bits per this */ 190}
111 struct iovec iov[2]; 191
112 int terrno = ETIMEDOUT; 192#ifdef INET6
113 char junk[512]; 193static struct sockaddr * get_nsaddr(size_t);
114 194
115#ifdef DEBUG 195/*
116 if ((_res.options & RES_DEBUG) || (_res.pfcode & RES_PRF_QUERY)) { 196 * pick appropriate nsaddr_list for use. see res_init() for initialization.
117 printf(";; res_send()\n"); 197 */
118 __p_query(buf); 198static struct sockaddr *
199get_nsaddr(n)
200 size_t n;
201{
202 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
203 struct __res_state_ext *_res_extp = _THREAD_PRIVATE(_res_ext, _res_ext,
204 &_res_ext);
205
206 if (!_resp->nsaddr_list[n].sin_family) {
207 /*
208 * - _res_extp->nsaddr_list[n] holds an address that is larger
209 * than struct sockaddr, and
210 * - user code did not update _resp->nsaddr_list[n].
211 */
212 return (struct sockaddr *)&_res_extp->nsaddr_list[n];
213 } else {
214 /*
215 * - user code updated _res.nsaddr_list[n], or
216 * - _resp->nsaddr_list[n] has the same content as
217 * _res_extp->nsaddr_list[n].
218 */
219 return (struct sockaddr *)&_resp->nsaddr_list[n];
119 } 220 }
221}
222#else
223#define get_nsaddr(n) ((struct sockaddr *)&_resp->nsaddr_list[(n)])
120#endif 224#endif
121 if (!(_res.options & RES_INIT)) 225
122 if (res_init() == -1) { 226/* int
123 return(-1); 227 * res_isourserver(ina)
228 * looks up "ina" in _resp->ns_addr_list[]
229 * returns:
230 * 0 : not found
231 * >0 : found
232 * author:
233 * paul vixie, 29may94
234 */
235int
236res_isourserver(inp)
237 const struct sockaddr_in *inp;
238{
239 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
240#ifdef INET6
241 const struct sockaddr_in6 *in6p = (const struct sockaddr_in6 *)inp;
242 const struct sockaddr_in6 *srv6;
243#endif
244 const struct sockaddr_in *srv;
245 int ns, ret;
246
247 ret = 0;
248 switch (inp->sin_family) {
249#ifdef INET6
250 case AF_INET6:
251 for (ns = 0; ns < _resp->nscount; ns++) {
252 srv6 = (struct sockaddr_in6 *)get_nsaddr(ns);
253 if (srv6->sin6_family == in6p->sin6_family &&
254 srv6->sin6_port == in6p->sin6_port &&
255 srv6->sin6_scope_id == in6p->sin6_scope_id &&
256 (IN6_IS_ADDR_UNSPECIFIED(&srv6->sin6_addr) ||
257 IN6_ARE_ADDR_EQUAL(&srv6->sin6_addr,
258 &in6p->sin6_addr))) {
259 ret++;
260 break;
261 }
124 } 262 }
125 v_circuit = (_res.options & RES_USEVC) || buflen > PACKETSZ; 263 break;
126 id = hp->id; 264#endif
265 case AF_INET:
266 for (ns = 0; ns < _resp->nscount; ns++) {
267 srv = (struct sockaddr_in *)get_nsaddr(ns);
268 if (srv->sin_family == inp->sin_family &&
269 srv->sin_port == inp->sin_port &&
270 (srv->sin_addr.s_addr == INADDR_ANY ||
271 srv->sin_addr.s_addr == inp->sin_addr.s_addr)) {
272 ret++;
273 break;
274 }
275 }
276 break;
277 }
278 return (ret);
279}
280
281/* int
282 * res_nameinquery(name, type, class, buf, eom)
283 * look for (name,type,class) in the query section of packet (buf,eom)
284 * returns:
285 * -1 : format error
286 * 0 : not found
287 * >0 : found
288 * author:
289 * paul vixie, 29may94
290 */
291int
292res_nameinquery(name, type, class, buf, eom)
293 const char *name;
294 register int type, class;
295 const u_char *buf, *eom;
296{
297 register const u_char *cp = buf + HFIXEDSZ;
298 int qdcount = ntohs(((HEADER*)buf)->qdcount);
299
300 while (qdcount-- > 0) {
301 char tname[MAXDNAME+1];
302 register int n, ttype, tclass;
303
304 n = dn_expand(buf, eom, cp, tname, sizeof tname);
305 if (n < 0)
306 return (-1);
307 cp += n;
308 ttype = _getshort(cp); cp += INT16SZ;
309 tclass = _getshort(cp); cp += INT16SZ;
310 if (ttype == type &&
311 tclass == class &&
312 strcasecmp(tname, name) == 0)
313 return (1);
314 }
315 return (0);
316}
317
318/* int
319 * res_queriesmatch(buf1, eom1, buf2, eom2)
320 * is there a 1:1 mapping of (name,type,class)
321 * in (buf1,eom1) and (buf2,eom2)?
322 * returns:
323 * -1 : format error
324 * 0 : not a 1:1 mapping
325 * >0 : is a 1:1 mapping
326 * author:
327 * paul vixie, 29may94
328 */
329int
330res_queriesmatch(buf1, eom1, buf2, eom2)
331 const u_char *buf1, *eom1;
332 const u_char *buf2, *eom2;
333{
334 register const u_char *cp = buf1 + HFIXEDSZ;
335 int qdcount = ntohs(((HEADER*)buf1)->qdcount);
336
337 if (qdcount != ntohs(((HEADER*)buf2)->qdcount))
338 return (0);
339 while (qdcount-- > 0) {
340 char tname[MAXDNAME+1];
341 register int n, ttype, tclass;
342
343 n = dn_expand(buf1, eom1, cp, tname, sizeof tname);
344 if (n < 0)
345 return (-1);
346 cp += n;
347 ttype = _getshort(cp); cp += INT16SZ;
348 tclass = _getshort(cp); cp += INT16SZ;
349 if (!res_nameinquery(tname, ttype, tclass, buf2, eom2))
350 return (0);
351 }
352 return (1);
353}
354
355int
356res_send(buf, buflen, ans, anssiz)
357 const u_char *buf;
358 int buflen;
359 u_char *ans;
360 int anssiz;
361{
362 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
363 HEADER *hp = (HEADER *) buf;
364 HEADER *anhp = (HEADER *) ans;
365 int gotsomewhere, connreset, terrno, try, v_circuit, resplen, ns;
366 register int n;
367 u_int badns; /* XXX NSMAX can't exceed #/bits in this var */
368
369 if ((_resp->options & RES_INIT) == 0 && res_init() == -1) {
370 /* errno should have been set by res_init() in this case. */
371 return (-1);
372 }
373 DprintQ((_resp->options & RES_DEBUG) || (_resp->pfcode & RES_PRF_QUERY),
374 (stdout, ";; res_send()\n"), buf, buflen);
375 v_circuit = (_resp->options & RES_USEVC) || buflen > PACKETSZ;
376 gotsomewhere = 0;
377 connreset = 0;
378 terrno = ETIMEDOUT;
127 badns = 0; 379 badns = 0;
380
128 /* 381 /*
129 * Send request, RETRY times, or until successful 382 * Send request, RETRY times, or until successful
130 */ 383 */
131 for (try = 0; try < _res.retry; try++) { 384 for (try = 0; try < _resp->retry; try++) {
132 for (ns = 0; ns < _res.nscount; ns++) { 385 for (ns = 0; ns < _resp->nscount; ns++) {
133 if (badns & (1<<ns)) 386 struct sockaddr *nsap = get_nsaddr(ns);
134 continue; 387 socklen_t salen;
135#ifdef DEBUG 388
136 if (_res.options & RES_DEBUG) 389 if (nsap->sa_len)
137 printf(";; Querying server (# %d) address = %s\n", 390 salen = nsap->sa_len;
138 ns+1, 391#ifdef INET6
139 inet_ntoa(_res.nsaddr_list[ns].sin_addr)); 392 else if (nsap->sa_family == AF_INET6)
393 salen = sizeof(struct sockaddr_in6);
140#endif 394#endif
141 usevc: 395 else if (nsap->sa_family == AF_INET)
396 salen = sizeof(struct sockaddr_in);
397 else
398 salen = 0; /*unknown, die on connect*/
399
400 same_ns:
401 if (badns & (1 << ns)) {
402 res_close();
403 goto next_ns;
404 }
405
406 if (Qhook) {
407 int done = 0, loops = 0;
408
409 do {
410 res_sendhookact act;
411
412 act = (*Qhook)((struct sockaddr_in **)&nsap,
413 &buf, &buflen,
414 ans, anssiz, &resplen);
415 switch (act) {
416 case res_goahead:
417 done = 1;
418 break;
419 case res_nextns:
420 res_close();
421 goto next_ns;
422 case res_done:
423 return (resplen);
424 case res_modified:
425 /* give the hook another try */
426 if (++loops < 42) /*doug adams*/
427 break;
428 /*FALLTHROUGH*/
429 case res_error:
430 /*FALLTHROUGH*/
431 default:
432 return (-1);
433 }
434 } while (!done);
435 }
436
437 Dprint((_resp->options & RES_DEBUG) &&
438 getnameinfo(nsap, salen, abuf, sizeof(abuf),
439 NULL, 0, NI_NUMERICHOST | NI_WITHSCOPEID) == 0,
440 (stdout, ";; Querying server (# %d) address = %s\n",
441 ns + 1, abuf));
442
142 if (v_circuit) { 443 if (v_circuit) {
143 int truncated = 0; 444 int truncated;
445 struct iovec iov[2];
446 u_short len;
447 u_char *cp;
144 448
145 /* 449 /*
146 * Use virtual circuit; 450 * Use virtual circuit;
147 * at most one attempt per server. 451 * at most one attempt per server.
148 */ 452 */
149 try = _res.retry; 453 try = _resp->retry;
150 if (s < 0) { 454 truncated = 0;
151 s = socket(AF_INET, SOCK_STREAM, 0); 455 if ((s < 0) || (!vc) || (af != nsap->sa_family)) {
456 if (s >= 0)
457 res_close();
458
459 af = nsap->sa_family;
460 s = socket(af, SOCK_STREAM, 0);
152 if (s < 0) { 461 if (s < 0) {
153 terrno = errno; 462 terrno = errno;
154#ifdef DEBUG 463 Perror(stderr, "socket(vc)", errno);
155 if (_res.options & RES_DEBUG) 464#if 0
156 perror("socket (vc) failed"); 465 return (-1);
466#else
467 badns |= (1 << ns);
468 res_close();
469 goto next_ns;
157#endif 470#endif
158 continue;
159 } 471 }
160 if (connect(s, 472 errno = 0;
161 (struct sockaddr *)&(_res.nsaddr_list[ns]), 473 if (connect(s, nsap, salen) < 0) {
162 sizeof(struct sockaddr)) < 0) {
163 terrno = errno; 474 terrno = errno;
164#ifdef DEBUG 475 Aerror(stderr, "connect/vc",
165 if (_res.options & RES_DEBUG) 476 errno, nsap);
166 perror("connect failed"); 477 badns |= (1 << ns);
167#endif 478 res_close();
168 (void) close(s); 479 goto next_ns;
169 s = -1;
170 continue;
171 } 480 }
481 vc = 1;
172 } 482 }
173 /* 483 /*
174 * Send length & message 484 * Send length & message
175 */ 485 */
176 len = htons((u_short)buflen); 486 putshort((u_short)buflen, (u_char*)&len);
177 iov[0].iov_base = (caddr_t)&len; 487 iov[0].iov_base = (caddr_t)&len;
178 iov[0].iov_len = sizeof(len); 488 iov[0].iov_len = INT16SZ;
179 iov[1].iov_base = (char *)buf; 489 iov[1].iov_base = (caddr_t)buf;
180 iov[1].iov_len = buflen; 490 iov[1].iov_len = buflen;
181 if (writev(s, iov, 2) != sizeof(len) + buflen) { 491 if (writev(s, iov, 2) != (INT16SZ + buflen)) {
182 terrno = errno; 492 terrno = errno;
183#ifdef DEBUG 493 Perror(stderr, "write failed", errno);
184 if (_res.options & RES_DEBUG) 494 badns |= (1 << ns);
185 perror("write failed"); 495 res_close();
186#endif 496 goto next_ns;
187 (void) close(s);
188 s = -1;
189 continue;
190 } 497 }
191 /* 498 /*
192 * Receive length & response 499 * Receive length & response
193 */ 500 */
194 cp = answer; 501read_len:
195 len = sizeof(short); 502 cp = ans;
196 while (len != 0 && 503 len = INT16SZ;
197 (n = read(s, (char *)cp, (int)len)) > 0) { 504 while ((n = read(s, (char *)cp, (int)len)) > 0) {
198 cp += n; 505 cp += n;
199 len -= n; 506 if ((len -= n) <= 0)
507 break;
200 } 508 }
201 if (n <= 0) { 509 if (n <= 0) {
202 terrno = errno; 510 terrno = errno;
203#ifdef DEBUG 511 Perror(stderr, "read failed", errno);
204 if (_res.options & RES_DEBUG) 512 res_close();
205 perror("read failed");
206#endif
207 (void) close(s);
208 s = -1;
209 /* 513 /*
210 * A long running process might get its TCP 514 * A long running process might get its TCP
211 * connection reset if the remote server was 515 * connection reset if the remote server was
@@ -217,35 +521,32 @@ res_send(buf, buflen, answer, anslen)
217 */ 521 */
218 if (terrno == ECONNRESET && !connreset) { 522 if (terrno == ECONNRESET && !connreset) {
219 connreset = 1; 523 connreset = 1;
220 ns--; 524 res_close();
525 goto same_ns;
221 } 526 }
222 continue; 527 res_close();
528 goto next_ns;
223 } 529 }
224 cp = answer; 530 resplen = _getshort(ans);
225 if ((resplen = ntohs(*(u_short *)cp)) > anslen) { 531 if (resplen > anssiz) {
226#ifdef DEBUG 532 Dprint(_resp->options & RES_DEBUG,
227 if (_res.options & RES_DEBUG) 533 (stdout, ";; response truncated\n")
228 fprintf(stderr, 534 );
229 ";; response truncated\n");
230#endif
231 len = anslen;
232 truncated = 1; 535 truncated = 1;
536 len = anssiz;
233 } else 537 } else
234 len = resplen; 538 len = resplen;
539 cp = ans;
235 while (len != 0 && 540 while (len != 0 &&
236 (n = read(s, (char *)cp, (int)len)) > 0) { 541 (n = read(s, (char *)cp, (int)len)) > 0) {
237 cp += n; 542 cp += n;
238 len -= n; 543 len -= n;
239 } 544 }
240 if (n <= 0) { 545 if (n <= 0) {
241 terrno = errno; 546 terrno = errno;
242#ifdef DEBUG 547 Perror(stderr, "read(vc)", errno);
243 if (_res.options & RES_DEBUG) 548 res_close();
244 perror("read failed"); 549 goto next_ns;
245#endif
246 (void) close(s);
247 s = -1;
248 continue;
249 } 550 }
250 if (truncated) { 551 if (truncated) {
251 /* 552 /*
@@ -253,33 +554,72 @@ res_send(buf, buflen, answer, anslen)
253 * so connection stays in synch. 554 * so connection stays in synch.
254 */ 555 */
255 anhp->tc = 1; 556 anhp->tc = 1;
256 len = resplen - anslen; 557 len = resplen - anssiz;
257 while (len != 0) { 558 while (len != 0) {
258 n = (len > sizeof(junk) ? 559 char junk[PACKETSZ];
259 sizeof(junk) : len); 560
561 n = (len > sizeof(junk)
562 ? sizeof(junk)
563 : len);
260 if ((n = read(s, junk, n)) > 0) 564 if ((n = read(s, junk, n)) > 0)
261 len -= n; 565 len -= n;
262 else 566 else
263 break; 567 break;
264 } 568 }
265 } 569 }
570 /*
571 * The calling applicating has bailed out of
572 * a previous call and failed to arrange to have
573 * the circuit closed or the server has got
574 * itself confused. Anyway drop the packet and
575 * wait for the correct one.
576 */
577 if (hp->id != anhp->id) {
578 DprintQ((_resp->options & RES_DEBUG) ||
579 (_resp->pfcode & RES_PRF_REPLY),
580 (stdout, ";; old answer (unexpected):\n"),
581 ans, (resplen>anssiz)?anssiz:resplen);
582 goto read_len;
583 }
266 } else { 584 } else {
267 /* 585 /*
268 * Use datagrams. 586 * Use datagrams.
269 */ 587 */
270 if (s < 0) { 588 struct timeval timeout;
271 s = socket(AF_INET, SOCK_DGRAM, 0); 589 fd_set *dsmaskp;
590 struct sockaddr_storage from;
591 socklen_t fromlen;
592
593 if ((s < 0) || vc || (af != nsap->sa_family)) {
594 if (vc)
595 res_close();
596 af = nsap->sa_family;
597 s = socket(af, SOCK_DGRAM, 0);
272 if (s < 0) { 598 if (s < 0) {
599#if !CAN_RECONNECT
600 bad_dg_sock:
601#endif
273 terrno = errno; 602 terrno = errno;
274#ifdef DEBUG 603 Perror(stderr, "socket(dg)", errno);
275 if (_res.options & RES_DEBUG) 604#if 0
276 perror("socket (dg) failed"); 605 return (-1);
606#else
607 badns |= (1 << ns);
608 res_close();
609 goto next_ns;
277#endif 610#endif
278 continue;
279 } 611 }
612#ifdef IPV6_MINMTU
613 if (af == AF_INET6) {
614 const int yes = 1;
615 (void)setsockopt(s, IPPROTO_IPV6,
616 IPV6_USE_MIN_MTU, &yes,
617 sizeof(yes));
618 }
619#endif
620 connected = 0;
280 } 621 }
281 /* 622 /*
282 * I'm tired of answering this question, so:
283 * On a 4.3BSD+ machine (client and server, 623 * On a 4.3BSD+ machine (client and server,
284 * actually), sending to a nameserver datagram 624 * actually), sending to a nameserver datagram
285 * port with no nameserver will cause an 625 * port with no nameserver will cause an
@@ -294,31 +634,28 @@ res_send(buf, buflen, answer, anslen)
294 * as we wish to receive answers from the first 634 * as we wish to receive answers from the first
295 * server to respond. 635 * server to respond.
296 */ 636 */
297 if (_res.nscount == 1 || (try == 0 && ns == 0)) { 637 if (!(_resp->options & RES_INSECURE1) &&
638 (_resp->nscount == 1 || (try == 0 && ns == 0))) {
298 /* 639 /*
299 * Don't use connect if we might 640 * Connect only if we are sure we won't
300 * still receive a response 641 * receive a response from another server.
301 * from another server.
302 */ 642 */
303 if (connected == 0) { 643 if (!connected) {
304 if (connect(s, 644 if (connect(s, nsap, salen) < 0) {
305 (struct sockaddr *) 645 Aerror(stderr,
306 &_res.nsaddr_list[ns], 646 "connect(dg)",
307 sizeof(struct sockaddr)) < 0) { 647 errno, nsap);
308#ifdef DEBUG 648 badns |= (1 << ns);
309 if (_res.options & RES_DEBUG) 649 res_close();
310 perror("connect"); 650 goto next_ns;
311#endif
312 continue;
313 } 651 }
314 connected = 1; 652 connected = 1;
315 } 653 }
316 if (send(s, buf, buflen, 0) != buflen) { 654 if (send(s, (char*)buf, buflen, 0) != buflen) {
317#ifdef DEBUG 655 Perror(stderr, "send", errno);
318 if (_res.options & RES_DEBUG) 656 badns |= (1 << ns);
319 perror("send"); 657 res_close();
320#endif 658 goto next_ns;
321 continue;
322 } 659 }
323 } else { 660 } else {
324 /* 661 /*
@@ -326,134 +663,221 @@ res_send(buf, buflen, answer, anslen)
326 * for responses from more than one server. 663 * for responses from more than one server.
327 */ 664 */
328 if (connected) { 665 if (connected) {
329 (void) connect(s, &no_addr, 666#if CAN_RECONNECT
330 sizeof(no_addr)); 667#ifdef INET6
668 /* XXX: any errornous address */
669#endif /* INET6 */
670 struct sockaddr_in no_addr;
671
672 no_addr.sin_family = AF_INET;
673 no_addr.sin_addr.s_addr = INADDR_ANY;
674 no_addr.sin_port = 0;
675 (void) connect(s,
676 (struct sockaddr *)
677 &no_addr,
678 sizeof(no_addr));
679#else
680 int s1 = socket(af, SOCK_DGRAM,0);
681 if (s1 < 0)
682 goto bad_dg_sock;
683 (void) dup2(s1, s);
684 (void) close(s1);
685 Dprint(_resp->options & RES_DEBUG,
686 (stdout, ";; new DG socket\n"))
687#endif
688#ifdef IPV6_MINMTU
689 if (af == AF_INET6) {
690 const int yes = 1;
691 (void)setsockopt(s, IPPROTO_IPV6,
692 IPV6_USE_MIN_MTU, &yes,
693 sizeof(yes));
694 }
695#endif
331 connected = 0; 696 connected = 0;
697 errno = 0;
332 } 698 }
333 if (sendto(s, buf, buflen, 0, 699 if (sendto(s, (char*)buf, buflen, 0,
334 (struct sockaddr *)&_res.nsaddr_list[ns], 700 nsap, salen) != buflen) {
335 sizeof(struct sockaddr)) != buflen) { 701 Aerror(stderr, "sendto", errno, nsap);
336#ifdef DEBUG 702 badns |= (1 << ns);
337 if (_res.options & RES_DEBUG) 703 res_close();
338 perror("sendto"); 704 goto next_ns;
339#endif
340 continue;
341 } 705 }
342 } 706 }
343 707
344 /* 708 /*
345 * Wait for reply 709 * Wait for reply
346 */ 710 */
347 timeout.tv_sec = (_res.retrans << try); 711 timeout.tv_sec = (_resp->retrans << try);
348 if (try > 0) 712 if (try > 0)
349 timeout.tv_sec /= _res.nscount; 713 timeout.tv_sec /= _resp->nscount;
350 if ((long) timeout.tv_sec <= 0) 714 if ((long) timeout.tv_sec <= 0)
351 timeout.tv_sec = 1; 715 timeout.tv_sec = 1;
352 timeout.tv_usec = 0; 716 timeout.tv_usec = 0;
353wait: 717 wait:
354 FD_ZERO(&dsmask); 718 dsmaskp = (fd_set *)calloc(howmany(s+1, NFDBITS),
355 FD_SET(s, &dsmask); 719 sizeof(fd_mask));
356 n = select(s+1, &dsmask, (fd_set *)NULL, 720 if (dsmaskp == NULL) {
357 (fd_set *)NULL, &timeout); 721 res_close();
722 goto next_ns;
723 }
724 FD_SET(s, dsmaskp);
725 n = select(s+1, dsmaskp, (fd_set *)NULL,
726 (fd_set *)NULL, &timeout);
727 free(dsmaskp);
358 if (n < 0) { 728 if (n < 0) {
359#ifdef DEBUG 729 if (errno == EINTR)
360 if (_res.options & RES_DEBUG) 730 goto wait;
361 perror("select"); 731 Perror(stderr, "select", errno);
362#endif 732 res_close();
363 continue; 733 goto next_ns;
364 } 734 }
365 if (n == 0) { 735 if (n == 0) {
366 /* 736 /*
367 * timeout 737 * timeout
368 */ 738 */
369#ifdef DEBUG 739 Dprint(_resp->options & RES_DEBUG,
370 if (_res.options & RES_DEBUG) 740 (stdout, ";; timeout\n"));
371 printf(";; timeout\n");
372#endif
373 gotsomewhere = 1; 741 gotsomewhere = 1;
374 continue; 742 res_close();
743 goto next_ns;
375 } 744 }
376 if ((resplen = recv(s, answer, anslen, 0)) <= 0) { 745 errno = 0;
377#ifdef DEBUG 746 fromlen = sizeof(from);
378 if (_res.options & RES_DEBUG) 747 resplen = recvfrom(s, (char*)ans, anssiz, 0,
379 perror("recvfrom"); 748 (struct sockaddr *)&from, &fromlen);
380#endif 749 if (resplen <= 0) {
381 continue; 750 Perror(stderr, "recvfrom", errno);
751 res_close();
752 goto next_ns;
382 } 753 }
383 gotsomewhere = 1; 754 gotsomewhere = 1;
384 if (id != anhp->id) { 755 if (hp->id != anhp->id) {
385 /* 756 /*
386 * response from old query, ignore it 757 * response from old query, ignore it.
758 * XXX - potential security hazard could
759 * be detected here.
387 */ 760 */
388#ifdef DEBUG 761 DprintQ((_resp->options & RES_DEBUG) ||
389 if ((_res.options & RES_DEBUG) || 762 (_resp->pfcode & RES_PRF_REPLY),
390 (_res.pfcode & RES_PRF_REPLY)) { 763 (stdout, ";; old answer:\n"),
391 printf(";; old answer:\n"); 764 ans, (resplen>anssiz)?anssiz:resplen);
392 __p_query(answer); 765 goto wait;
393 } 766 }
767#if CHECK_SRVR_ADDR
768 if (!(_resp->options & RES_INSECURE1) &&
769 !res_isourserver((struct sockaddr_in *)&from)) {
770 /*
771 * response from wrong server? ignore it.
772 * XXX - potential security hazard could
773 * be detected here.
774 */
775 DprintQ((_resp->options & RES_DEBUG) ||
776 (_resp->pfcode & RES_PRF_REPLY),
777 (stdout, ";; not our server:\n"),
778 ans, (resplen>anssiz)?anssiz:resplen);
779 goto wait;
780 }
394#endif 781#endif
782 if (!(_resp->options & RES_INSECURE2) &&
783 !res_queriesmatch(buf, buf + buflen,
784 ans, ans + anssiz)) {
785 /*
786 * response contains wrong query? ignore it.
787 * XXX - potential security hazard could
788 * be detected here.
789 */
790 DprintQ((_resp->options & RES_DEBUG) ||
791 (_resp->pfcode & RES_PRF_REPLY),
792 (stdout, ";; wrong query name:\n"),
793 ans, (resplen>anssiz)?anssiz:resplen);
395 goto wait; 794 goto wait;
396 } 795 }
397 if (anhp->rcode == SERVFAIL || anhp->rcode == NOTIMP || 796 if (anhp->rcode == SERVFAIL ||
797 anhp->rcode == NOTIMP ||
398 anhp->rcode == REFUSED) { 798 anhp->rcode == REFUSED) {
399#ifdef DEBUG 799 DprintQ(_resp->options & RES_DEBUG,
400 if (_res.options & RES_DEBUG) { 800 (stdout, "server rejected query:\n"),
401 printf("server rejected query:\n"); 801 ans, (resplen>anssiz)?anssiz:resplen);
402 __p_query(answer); 802 badns |= (1 << ns);
403 } 803 res_close();
404#endif 804 /* don't retry if called from dig */
405 badns |= (1<<ns); 805 if (!_resp->pfcode)
406 continue; 806 goto next_ns;
407 } 807 }
408 if (!(_res.options & RES_IGNTC) && anhp->tc) { 808 if (!(_resp->options & RES_IGNTC) && anhp->tc) {
409 /* 809 /*
410 * get rest of answer; 810 * get rest of answer;
411 * use TCP with same server. 811 * use TCP with same server.
412 */ 812 */
413#ifdef DEBUG 813 Dprint(_resp->options & RES_DEBUG,
414 if (_res.options & RES_DEBUG) 814 (stdout, ";; truncated answer\n"));
415 printf(";; truncated answer\n");
416#endif
417 (void) close(s);
418 s = -1;
419 v_circuit = 1; 815 v_circuit = 1;
420 goto usevc; 816 res_close();
817 goto same_ns;
421 } 818 }
422 } 819 } /*if vc/dg*/
423#ifdef DEBUG 820 Dprint((_resp->options & RES_DEBUG) ||
424 if (_res.options & RES_DEBUG) 821 ((_resp->pfcode & RES_PRF_REPLY) &&
425 printf(";; got answer:\n"); 822 (_resp->pfcode & RES_PRF_HEAD1)),
426 if ((_res.options & RES_DEBUG) || 823 (stdout, ";; got answer:\n"));
427 (_res.pfcode & RES_PRF_REPLY)) 824 DprintQ((_resp->options & RES_DEBUG) ||
428 __p_query(answer); 825 (_resp->pfcode & RES_PRF_REPLY),
429#endif 826 (stdout, "%s", ""),
827 ans, (resplen>anssiz)?anssiz:resplen);
430 /* 828 /*
431 * If using virtual circuits, we assume that the first server 829 * If using virtual circuits, we assume that the first server
432 * is preferred * over the rest (i.e. it is on the local 830 * is preferred over the rest (i.e. it is on the local
433 * machine) and only keep that one open. 831 * machine) and only keep that one open.
434 * If we have temporarily opened a virtual circuit, 832 * If we have temporarily opened a virtual circuit,
435 * or if we haven't been asked to keep a socket open, 833 * or if we haven't been asked to keep a socket open,
436 * close the socket. 834 * close the socket.
437 */ 835 */
438 if ((v_circuit && 836 if ((v_circuit && (!(_resp->options & RES_USEVC) || ns != 0)) ||
439 ((_res.options & RES_USEVC) == 0 || ns != 0)) || 837 !(_resp->options & RES_STAYOPEN)) {
440 (_res.options & RES_STAYOPEN) == 0) { 838 res_close();
441 (void) close(s); 839 }
442 s = -1; 840 if (Rhook) {
841 int done = 0, loops = 0;
842
843 do {
844 res_sendhookact act;
845
846 act = (*Rhook)((struct sockaddr_in *)nsap,
847 buf, buflen,
848 ans, anssiz, &resplen);
849 switch (act) {
850 case res_goahead:
851 case res_done:
852 done = 1;
853 break;
854 case res_nextns:
855 res_close();
856 goto next_ns;
857 case res_modified:
858 /* give the hook another try */
859 if (++loops < 42) /*doug adams*/
860 break;
861 /*FALLTHROUGH*/
862 case res_error:
863 /*FALLTHROUGH*/
864 default:
865 return (-1);
866 }
867 } while (!done);
868
443 } 869 }
444 return (resplen); 870 return (resplen);
445 } 871 next_ns: ;
446 } 872 } /*foreach ns*/
447 if (s >= 0) { 873 } /*foreach retry*/
448 (void) close(s); 874 res_close();
449 s = -1; 875 if (!v_circuit) {
450 } 876 if (!gotsomewhere)
451 if (v_circuit == 0)
452 if (gotsomewhere == 0)
453 errno = ECONNREFUSED; /* no nameservers found */ 877 errno = ECONNREFUSED; /* no nameservers found */
454 else 878 else
455 errno = ETIMEDOUT; /* no answer obtained */ 879 errno = ETIMEDOUT; /* no answer obtained */
456 else 880 } else
457 errno = terrno; 881 errno = terrno;
458 return (-1); 882 return (-1);
459} 883}
@@ -465,10 +889,14 @@ wait:
465 * 889 *
466 * This routine is not expected to be user visible. 890 * This routine is not expected to be user visible.
467 */ 891 */
468_res_close() 892void
893res_close()
469{ 894{
470 if (s != -1) { 895 if (s >= 0) {
471 (void) close(s); 896 (void) close(s);
472 s = -1; 897 s = -1;
898 connected = 0;
899 vc = 0;
900 af = 0;
473 } 901 }
474} 902}
diff --git a/src/lib/libc/net/resolver.3 b/src/lib/libc/net/resolver.3
index 99abe17f03..4d5402ed2d 100644
--- a/src/lib/libc/net/resolver.3
+++ b/src/lib/libc/net/resolver.3
@@ -1,4 +1,4 @@
1.\" $NetBSD: resolver.3,v 1.5 1995/02/25 06:21:02 cgd Exp $ 1.\" $OpenBSD: resolver.3,v 1.15 2001/04/03 20:09:08 aaron Exp $
2.\" 2.\"
3.\" Copyright (c) 1985, 1991, 1993 3.\" Copyright (c) 1985, 1991, 1993
4.\" The Regents of the University of California. All rights reserved. 4.\" The Regents of the University of California. All rights reserved.
@@ -31,11 +31,9 @@
31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32.\" SUCH DAMAGE. 32.\" SUCH DAMAGE.
33.\" 33.\"
34.\" @(#)resolver.3 8.1 (Berkeley) 6/4/93
35.\"
36.Dd June 4, 1993 34.Dd June 4, 1993
37.Dt RESOLVER 3 35.Dt RESOLVER 3
38.Os BSD 4.3 36.Os
39.Sh NAME 37.Sh NAME
40.Nm res_query , 38.Nm res_query ,
41.Nm res_search , 39.Nm res_search ,
@@ -50,6 +48,7 @@
50.Fd #include <netinet/in.h> 48.Fd #include <netinet/in.h>
51.Fd #include <arpa/nameser.h> 49.Fd #include <arpa/nameser.h>
52.Fd #include <resolv.h> 50.Fd #include <resolv.h>
51.Ft int
53.Fo res_query 52.Fo res_query
54.Fa "char *dname" 53.Fa "char *dname"
55.Fa "int class" 54.Fa "int class"
@@ -57,6 +56,7 @@
57.Fa "u_char *answer" 56.Fa "u_char *answer"
58.Fa "int anslen" 57.Fa "int anslen"
59.Fc 58.Fc
59.Ft int
60.Fo res_search 60.Fo res_search
61.Fa "char *dname" 61.Fa "char *dname"
62.Fa "int class" 62.Fa "int class"
@@ -64,6 +64,7 @@
64.Fa "u_char *answer" 64.Fa "u_char *answer"
65.Fa "int anslen" 65.Fa "int anslen"
66.Fc 66.Fc
67.Ft int
67.Fo res_mkquery 68.Fo res_mkquery
68.Fa "int op" 69.Fa "int op"
69.Fa "char *dname" 70.Fa "char *dname"
@@ -75,13 +76,16 @@
75.Fa "char *buf" 76.Fa "char *buf"
76.Fa "int buflen" 77.Fa "int buflen"
77.Fc 78.Fc
79.Ft int
78.Fo res_send 80.Fo res_send
79.Fa "char *msg" 81.Fa "char *msg"
80.Fa "int msglen" 82.Fa "int msglen"
81.Fa "char *answer" 83.Fa "char *answer"
82.Fa "int anslen" 84.Fa "int anslen"
83.Fc 85.Fc
84.Fn res_init 86.Ft int
87.Fn res_init "void"
88.Ft int
85.Fo dn_comp 89.Fo dn_comp
86.Fa "char *exp_dn" 90.Fa "char *exp_dn"
87.Fa "char *comp_dn" 91.Fa "char *comp_dn"
@@ -89,6 +93,7 @@
89.Fa "char **dnptrs" 93.Fa "char **dnptrs"
90.Fa "char **lastdnptr" 94.Fa "char **lastdnptr"
91.Fc 95.Fc
96.Ft int
92.Fo dn_expand 97.Fo dn_expand
93.Fa "u_char *msg" 98.Fa "u_char *msg"
94.Fa "u_char *eomorig" 99.Fa "u_char *eomorig"
@@ -97,22 +102,22 @@
97.Fa "int length" 102.Fa "int length"
98.Fc 103.Fc
99.Sh DESCRIPTION 104.Sh DESCRIPTION
100These routines are used for making, sending and interpreting 105These routines are used for making, sending, and interpreting
101query and reply messages with Internet domain name servers. 106query and reply messages with Internet domain name servers.
102.Pp 107.Pp
103Global configuration and state information that is used by the 108Global configuration and state information that is used by the
104resolver routines is kept in the structure 109resolver routines is kept in the structure
105.Em _res . 110.Li _res .
106Most of the values have reasonable defaults and can be ignored. 111Most of the values have reasonable defaults and can be ignored.
107Options 112Options stored in
108stored in 113.Li _res.options
109.Em _res.options
110are defined in 114are defined in
111.Pa resolv.h 115.Aq Pa resolv.h
112and are as follows. 116and are as follows.
113Options are stored as a simple bit mask containing the bitwise ``or'' 117Options are stored as a simple bit mask containing the bitwise
118.Tn OR
114of the options enabled. 119of the options enabled.
115.Bl -tag -width RES_DEFNAMES 120.Bl -tag -width RES_USE_INET6
116.It Dv RES_INIT 121.It Dv RES_INIT
117True if the initial name server address and default domain name are 122True if the initial name server address and default domain name are
118initialized (i.e., 123initialized (i.e.,
@@ -137,8 +142,7 @@ Used with
137.Dv RES_USEVC 142.Dv RES_USEVC
138to keep the 143to keep the
139.Tn TCP 144.Tn TCP
140connection open between 145connection open between queries.
141queries.
142This is useful only in programs that regularly do many queries. 146This is useful only in programs that regularly do many queries.
143.Tn UDP 147.Tn UDP
144should be the normal mode used. 148should be the normal mode used.
@@ -165,16 +169,20 @@ will search for host names in the current domain and in parent domains; see
165This is used by the standard host lookup routine 169This is used by the standard host lookup routine
166.Xr gethostbyname 3 . 170.Xr gethostbyname 3 .
167This option is enabled by default. 171This option is enabled by default.
172.It Dv RES_USE_INET6
173Enables support for IPv6-only applications.
174This causes IPv4 addresses to be returned as an IPv4 mapped address.
175For example, 10.1.1.1 will be returned as ::ffff:10.1.1.1.
176The option is not meaningful on
177.Ox .
168.El 178.El
169.Pp 179.Pp
170The 180The
171.Fn res_init 181.Fn res_init
172routine 182routine reads the configuration file (if any; see
173reads the configuration file (if any; see
174.Xr resolv.conf 5 ) 183.Xr resolv.conf 5 )
175to get the default domain name, 184to get the default domain name, search list, and the Internet address
176search list and 185of the local name server(s).
177the Internet address of the local name server(s).
178If no server is configured, the host running 186If no server is configured, the host running
179the resolver is tried. 187the resolver is tried.
180The current domain name is defined by the hostname 188The current domain name is defined by the hostname
@@ -212,7 +220,7 @@ The query requests information of the specified
212.Fa type 220.Fa type
213and 221and
214.Fa class 222.Fa class
215for the specified fully-qualified domain name 223for the specified fully qualified domain name
216.Fa dname . 224.Fa dname .
217The reply message is left in the 225The reply message is left in the
218.Fa answer 226.Fa answer
@@ -224,8 +232,7 @@ The
224.Fn res_search 232.Fn res_search
225routine makes a query and awaits a response like 233routine makes a query and awaits a response like
226.Fn res_query , 234.Fn res_query ,
227but in addition, it implements the default and search rules 235but in addition, it implements the default and search rules controlled by the
228controlled by the
229.Dv RES_DEFNAMES 236.Dv RES_DEFNAMES
230and 237and
231.Dv RES_DNSRCH 238.Dv RES_DNSRCH
@@ -236,11 +243,9 @@ The remaining routines are lower-level routines used by
236.Fn res_query . 243.Fn res_query .
237The 244The
238.Fn res_mkquery 245.Fn res_mkquery
239function 246function constructs a standard query message and places it in
240constructs a standard query message and places it in
241.Fa buf . 247.Fa buf .
242It returns the size of the query, or \-1 if the query is 248It returns the size of the query, or \-1 if the query is larger than
243larger than
244.Fa buflen . 249.Fa buflen .
245The query type 250The query type
246.Fa op 251.Fa op
@@ -250,26 +255,23 @@ but can be any of the query types defined in
250.Aq Pa arpa/nameser.h . 255.Aq Pa arpa/nameser.h .
251The domain name for the query is given by 256The domain name for the query is given by
252.Fa dname . 257.Fa dname .
253.Fa Newrr 258.Fa newrr
254is currently unused but is intended for making update messages. 259is currently unused but is intended for making update messages.
255.Pp 260.Pp
256The 261The
257.Fn res_send 262.Fn res_send
258routine 263routine sends a pre-formatted query and returns an answer.
259sends a pre-formatted query and returns an answer.
260It will call 264It will call
261.Fn res_init 265.Fn res_init
262if 266if
263.Dv RES_INIT 267.Dv RES_INIT
264is not set, send the query to the local name server, and 268is not set, send the query to the local name server, and
265handle timeouts and retries. 269handle timeouts and retries.
266The length of the reply message is returned, or 270The length of the reply message is returned, or \-1 if there were errors.
267\-1 if there were errors.
268.Pp 271.Pp
269The 272The
270.Fn dn_comp 273.Fn dn_comp
271function 274function compresses the domain name
272compresses the domain name
273.Fa exp_dn 275.Fa exp_dn
274and stores it in 276and stores it in
275.Fa comp_dn . 277.Fa comp_dn .
@@ -278,24 +280,23 @@ The size of the array pointed to by
278.Fa comp_dn 280.Fa comp_dn
279is given by 281is given by
280.Fa length . 282.Fa length .
281The compression uses 283The compression uses an array of pointers
282an array of pointers
283.Fa dnptrs 284.Fa dnptrs
284to previously-compressed names in the current message. 285to previously compressed names in the current message.
285The first pointer points to 286The first pointer points
286to the beginning of the message and the list ends with 287to the beginning of the message and the list ends with
287.Dv NULL . 288.Dv NULL .
288The limit to the array is specified by 289The limit to the array is specified by
289.Fa lastdnptr . 290.Fa lastdnptr .
290A side effect of 291A side effect of
291.Fn dn_comp 292.Fn dn_comp
292is to update the list of pointers for 293is to update the list of pointers for labels inserted into the message
293labels inserted into the message
294as the name is compressed. 294as the name is compressed.
295If 295If
296.Em dnptr 296.Em dnptr
297is 297is
298.Dv NULL, names are not compressed. 298.Dv NULL ,
299names are not compressed.
299If 300If
300.Fa lastdnptr 301.Fa lastdnptr
301is 302is
@@ -304,8 +305,7 @@ the list of labels is not updated.
304.Pp 305.Pp
305The 306The
306.Fn dn_expand 307.Fn dn_expand
307entry 308entry expands the compressed domain name
308expands the compressed domain name
309.Fa comp_dn 309.Fa comp_dn
310to a full domain name 310to a full domain name
311The compressed name is contained in a query or reply message; 311The compressed name is contained in a query or reply message;
@@ -319,20 +319,21 @@ The size of compressed name is returned or \-1 if there was an error.
319.Sh FILES 319.Sh FILES
320.Bl -tag -width Pa 320.Bl -tag -width Pa
321/etc/resolv.conf 321/etc/resolv.conf
322The configuration file 322configuration file
323see 323see
324.Xr resolv.conf 5 . 324.Xr resolv.conf 5 .
325.El 325.El
326.Sh SEE ALSO 326.Sh SEE ALSO
327.Xr gethostbyname 3 , 327.Xr gethostbyname 3 ,
328.Xr named 8 ,
329.Xr resolv.conf 5 , 328.Xr resolv.conf 5 ,
330.Xr hostname 7 , 329.Xr hostname 7 ,
330.Xr named 8
331.Pp 331.Pp
332.%T RFC1032 , 332.%T RFC1032 ,
333.%T RFC1033 , 333.%T RFC1033 ,
334.%T RFC1034 , 334.%T RFC1034 ,
335.%T RFC1035 , 335.%T RFC1035 ,
336.%T RFC1535 ,
336.%T RFC974 337.%T RFC974
337.Rs 338.Rs
338.%T "Name Server Operations Guide for BIND" 339.%T "Name Server Operations Guide for BIND"
@@ -340,5 +341,5 @@ see
340.Sh HISTORY 341.Sh HISTORY
341The 342The
342.Nm 343.Nm
343function appeared in 344function appeared in
344.Bx 4.3 . 345.Bx 4.3 .
diff --git a/src/lib/libc/net/rresvport.c b/src/lib/libc/net/rresvport.c
new file mode 100644
index 0000000000..c807adfb83
--- /dev/null
+++ b/src/lib/libc/net/rresvport.c
@@ -0,0 +1,118 @@
1/*
2 * Copyright (c) 1995, 1996, 1998 Theo de Raadt. All rights reserved.
3 * Copyright (c) 1983, 1993, 1994
4 * The Regents of the University of California. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by the University of
17 * California, Berkeley and its contributors.
18 * This product includes software developed by Theo de Raadt.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36#if defined(LIBC_SCCS) && !defined(lint)
37static char *rcsid = "$OpenBSD: rresvport.c,v 1.5 2000/01/26 03:43:20 deraadt Exp $";
38#endif /* LIBC_SCCS and not lint */
39
40#include <sys/param.h>
41#include <sys/socket.h>
42#include <sys/stat.h>
43
44#include <netinet/in.h>
45#include <arpa/inet.h>
46
47#include <signal.h>
48#include <fcntl.h>
49#include <netdb.h>
50#include <unistd.h>
51#include <pwd.h>
52#include <errno.h>
53#include <stdio.h>
54#include <ctype.h>
55#include <string.h>
56#include <syslog.h>
57#include <stdlib.h>
58#include <netgroup.h>
59
60int
61rresvport(alport)
62 int *alport;
63{
64 return rresvport_af(alport, AF_INET);
65}
66
67
68int
69rresvport_af(alport, af)
70 int *alport;
71 int af;
72{
73 struct sockaddr_storage ss;
74 struct sockaddr *sa;
75 u_int16_t *portp;
76 int s;
77
78 bzero(&ss, sizeof ss);
79 sa = (struct sockaddr *)&ss;
80
81 switch (af) {
82 case AF_INET:
83 sa->sa_len = sizeof(struct sockaddr_in);
84 portp = &((struct sockaddr_in *)sa)->sin_port;
85 break;
86 case AF_INET6:
87 sa->sa_len = sizeof(struct sockaddr_in6);
88 portp = &((struct sockaddr_in6 *)sa)->sin6_port;
89 break;
90 default:
91 errno = EPFNOSUPPORT;
92 return (-1);
93 }
94 sa->sa_family = af;
95
96 s = socket(af, SOCK_STREAM, 0);
97 if (s < 0)
98 return (-1);
99
100 *portp = htons(*alport);
101 if (*alport < IPPORT_RESERVED - 1) {
102 if (bind(s, sa, sa->sa_len) >= 0)
103 return (s);
104 if (errno != EADDRINUSE) {
105 (void)close(s);
106 return (-1);
107 }
108 }
109
110 *portp = 0;
111 sa->sa_family = af;
112 if (bindresvport_sa(s, sa) == -1) {
113 (void)close(s);
114 return (-1);
115 }
116 *alport = ntohs(*portp);
117 return (s);
118}
diff --git a/src/lib/libc/net/rthdr.c b/src/lib/libc/net/rthdr.c
new file mode 100644
index 0000000000..7a87b322d1
--- /dev/null
+++ b/src/lib/libc/net/rthdr.c
@@ -0,0 +1,310 @@
1/* $OpenBSD: rthdr.c,v 1.3 2002/06/27 10:14:02 itojun Exp $ */
2
3/*
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#include <sys/param.h>
33#include <sys/types.h>
34#include <sys/socket.h>
35
36#include <netinet/in.h>
37#include <netinet/ip6.h>
38
39#include <string.h>
40#include <stdio.h>
41
42size_t
43inet6_rthdr_space(type, seg)
44 int type, seg;
45{
46 switch(type) {
47 case IPV6_RTHDR_TYPE_0:
48 if (seg < 1 || seg > 23)
49 return(0);
50 return(CMSG_SPACE(sizeof(struct in6_addr) * (seg - 1)
51 + sizeof(struct ip6_rthdr0)));
52 default:
53#ifdef DEBUG
54 fprintf(stderr, "inet6_rthdr_space: unknown type(%d)\n", type);
55#endif
56 return(0);
57 }
58}
59
60struct cmsghdr *
61inet6_rthdr_init(bp, type)
62 void *bp;
63 int type;
64{
65 register struct cmsghdr *ch = (struct cmsghdr *)bp;
66 register struct ip6_rthdr *rthdr;
67
68 rthdr = (struct ip6_rthdr *)CMSG_DATA(ch);
69
70 ch->cmsg_level = IPPROTO_IPV6;
71 ch->cmsg_type = IPV6_RTHDR;
72
73 switch(type) {
74 case IPV6_RTHDR_TYPE_0:
75 ch->cmsg_len = CMSG_LEN(sizeof(struct ip6_rthdr0) - sizeof(struct in6_addr));
76 bzero(rthdr, sizeof(struct ip6_rthdr0));
77 rthdr->ip6r_type = IPV6_RTHDR_TYPE_0;
78 return(ch);
79 default:
80#ifdef DEBUG
81 fprintf(stderr, "inet6_rthdr_init: unknown type(%d)\n", type);
82#endif
83 return(NULL);
84 }
85}
86
87int
88inet6_rthdr_add(cmsg, addr, flags)
89 struct cmsghdr *cmsg;
90 const struct in6_addr *addr;
91 u_int flags;
92{
93 register struct ip6_rthdr *rthdr;
94
95 rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg);
96
97 switch(rthdr->ip6r_type) {
98 case IPV6_RTHDR_TYPE_0:
99 {
100 struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
101 if (flags != IPV6_RTHDR_LOOSE && flags != IPV6_RTHDR_STRICT) {
102#ifdef DEBUG
103 fprintf(stderr, "inet6_rthdr_add: unsupported flag(%u)\n", flags);
104#endif
105 return(-1);
106 }
107 if (rt0->ip6r0_segleft == 23) {
108#ifdef DEBUG
109 fprintf(stderr, "inet6_rthdr_add: segment overflow\n");
110#endif
111 return(-1);
112 }
113 if (flags == IPV6_RTHDR_STRICT) {
114 int c, b;
115 c = rt0->ip6r0_segleft / 8;
116 b = rt0->ip6r0_segleft % 8;
117 rt0->ip6r0_slmap[c] |= (1 << (7 - b));
118 }
119 rt0->ip6r0_segleft++;
120 bcopy(addr, (caddr_t)rt0 + ((rt0->ip6r0_len + 1) << 3),
121 sizeof(struct in6_addr));
122 rt0->ip6r0_len += sizeof(struct in6_addr) >> 3;
123 cmsg->cmsg_len = CMSG_LEN((rt0->ip6r0_len + 1) << 3);
124 break;
125 }
126 default:
127#ifdef DEBUG
128 fprintf(stderr, "inet6_rthdr_add: unknown type(%u)\n",
129 rthdr->ip6r_type);
130#endif
131 return(-1);
132 }
133
134 return(0);
135}
136
137int
138inet6_rthdr_lasthop(cmsg, flags)
139 struct cmsghdr *cmsg;
140 unsigned int flags;
141{
142 register struct ip6_rthdr *rthdr;
143
144 rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg);
145
146 switch(rthdr->ip6r_type) {
147 case IPV6_RTHDR_TYPE_0:
148 {
149 struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
150 if (flags != IPV6_RTHDR_LOOSE && flags != IPV6_RTHDR_STRICT) {
151#ifdef DEBUG
152 fprintf(stderr, "inet6_rthdr_lasthop: unsupported flag(%u)\n", flags);
153#endif
154 return(-1);
155 }
156 if (rt0->ip6r0_segleft > 23) {
157#ifdef DEBUG
158 fprintf(stderr, "inet6_rthdr_add: segment overflow\n");
159#endif
160 return(-1);
161 }
162 if (flags == IPV6_RTHDR_STRICT) {
163 int c, b;
164 c = rt0->ip6r0_segleft / 8;
165 b = rt0->ip6r0_segleft % 8;
166 rt0->ip6r0_slmap[c] |= (1 << (7 - b));
167 }
168 break;
169 }
170 default:
171#ifdef DEBUG
172 fprintf(stderr, "inet6_rthdr_lasthop: unknown type(%u)\n",
173 rthdr->ip6r_type);
174#endif
175 return(-1);
176 }
177
178 return(0);
179}
180
181#if 0
182int
183inet6_rthdr_reverse(in, out)
184 const struct cmsghdr *in;
185 struct cmsghdr *out;
186{
187#ifdef DEBUG
188 fprintf(stderr, "inet6_rthdr_reverse: not implemented yet\n");
189#endif
190 return -1;
191}
192#endif
193
194int
195inet6_rthdr_segments(cmsg)
196 const struct cmsghdr *cmsg;
197{
198 register struct ip6_rthdr *rthdr;
199
200 rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg);
201
202 switch(rthdr->ip6r_type) {
203 case IPV6_RTHDR_TYPE_0:
204 {
205 struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
206
207 if (rt0->ip6r0_len % 2 || 46 < rt0->ip6r0_len) {
208#ifdef DEBUG
209 fprintf(stderr, "inet6_rthdr_segments: invalid size(%u)\n",
210 rt0->ip6r0_len);
211#endif
212 return -1;
213 }
214
215 return (rt0->ip6r0_len * 8) / sizeof(struct in6_addr);
216 }
217
218 default:
219#ifdef DEBUG
220 fprintf(stderr, "inet6_rthdr_segments: unknown type(%u)\n",
221 rthdr->ip6r_type);
222#endif
223 return -1;
224 }
225}
226
227struct in6_addr *
228inet6_rthdr_getaddr(cmsg, index)
229 struct cmsghdr *cmsg;
230 int index;
231{
232 register struct ip6_rthdr *rthdr;
233
234 rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg);
235
236 switch(rthdr->ip6r_type) {
237 case IPV6_RTHDR_TYPE_0:
238 {
239 struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
240 int naddr;
241
242 if (rt0->ip6r0_len % 2 || 46 < rt0->ip6r0_len) {
243#ifdef DEBUG
244 fprintf(stderr, "inet6_rthdr_getaddr: invalid size(%u)\n",
245 rt0->ip6r0_len);
246#endif
247 return NULL;
248 }
249 naddr = (rt0->ip6r0_len * 8) / sizeof(struct in6_addr);
250 if (index <= 0 || naddr < index) {
251#ifdef DEBUG
252 fprintf(stderr, "inet6_rthdr_getaddr: invalid index(%d)\n", index);
253#endif
254 return NULL;
255 }
256 return &rt0->ip6r0_addr[index - 1];
257 }
258
259 default:
260#ifdef DEBUG
261 fprintf(stderr, "inet6_rthdr_getaddr: unknown type(%u)\n",
262 rthdr->ip6r_type);
263#endif
264 return NULL;
265 }
266}
267
268int
269inet6_rthdr_getflags(cmsg, index)
270 const struct cmsghdr *cmsg;
271 int index;
272{
273 register struct ip6_rthdr *rthdr;
274
275 rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg);
276
277 switch(rthdr->ip6r_type) {
278 case IPV6_RTHDR_TYPE_0:
279 {
280 struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
281 int naddr;
282
283 if (rt0->ip6r0_len % 2 || 46 < rt0->ip6r0_len) {
284#ifdef DEBUG
285 fprintf(stderr, "inet6_rthdr_getflags: invalid size(%u)\n",
286 rt0->ip6r0_len);
287#endif
288 return -1;
289 }
290 naddr = (rt0->ip6r0_len * 8) / sizeof(struct in6_addr);
291 if (index < 0 || naddr < index) {
292#ifdef DEBUG
293 fprintf(stderr, "inet6_rthdr_getflags: invalid index(%d)\n", index);
294#endif
295 return -1;
296 }
297 if (rt0->ip6r0_slmap[index / 8] & (0x80 >> (index % 8)))
298 return IPV6_RTHDR_STRICT;
299 else
300 return IPV6_RTHDR_LOOSE;
301 }
302
303 default:
304#ifdef DEBUG
305 fprintf(stderr, "inet6_rthdr_getflags: unknown type(%u)\n",
306 rthdr->ip6r_type);
307#endif
308 return -1;
309 }
310}
diff --git a/src/lib/libc/net/send.c b/src/lib/libc/net/send.c
index 88f3550ec6..8495931ca3 100644
--- a/src/lib/libc/net/send.c
+++ b/src/lib/libc/net/send.c
@@ -1,5 +1,3 @@
1/* $NetBSD: send.c,v 1.6 1995/02/25 06:21:02 cgd Exp $ */
2
3/* 1/*
4 * Copyright (c) 1988, 1993 2 * Copyright (c) 1988, 1993
5 * The Regents of the University of California. All rights reserved. 3 * The Regents of the University of California. All rights reserved.
@@ -34,11 +32,7 @@
34 */ 32 */
35 33
36#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
37#if 0 35static char rcsid[] = "$OpenBSD: send.c,v 1.2 1996/08/19 08:29:52 tholo Exp $";
38static char sccsid[] = "@(#)send.c 8.2 (Berkeley) 2/21/94";
39#else
40static char rcsid[] = "$NetBSD: send.c,v 1.6 1995/02/25 06:21:02 cgd Exp $";
41#endif
42#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
43 37
44#include <sys/types.h> 38#include <sys/types.h>
diff --git a/src/lib/libc/net/sethostent.c b/src/lib/libc/net/sethostent.c
index 00f6499695..40a5a80962 100644
--- a/src/lib/libc/net/sethostent.c
+++ b/src/lib/libc/net/sethostent.c
@@ -1,5 +1,3 @@
1/* $NetBSD: sethostent.c,v 1.4 1995/02/25 06:21:03 cgd Exp $ */
2
3/* 1/*
4 * Copyright (c) 1985, 1993 2 * Copyright (c) 1985, 1993
5 * The Regents of the University of California. All rights reserved. 3 * The Regents of the University of California. All rights reserved.
@@ -34,11 +32,7 @@
34 */ 32 */
35 33
36#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
37#if 0 35static char rcsid[] = "$OpenBSD: sethostent.c,v 1.5 2003/01/28 04:58:00 marc Exp $";
38static char sccsid[] = "@(#)sethostent.c 8.1 (Berkeley) 6/4/93";
39#else
40static char rcsid[] = "$NetBSD: sethostent.c,v 1.4 1995/02/25 06:21:03 cgd Exp $";
41#endif
42#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
43 37
44#include <sys/param.h> 38#include <sys/param.h>
@@ -47,16 +41,25 @@ static char rcsid[] = "$NetBSD: sethostent.c,v 1.4 1995/02/25 06:21:03 cgd Exp $
47#include <netdb.h> 41#include <netdb.h>
48#include <resolv.h> 42#include <resolv.h>
49 43
44#include "thread_private.h"
45
50void 46void
51sethostent(stayopen) 47sethostent(stayopen)
48 int stayopen;
52{ 49{
50 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
51
52 if ((_resp->options & RES_INIT) == 0 && res_init() == -1)
53 return;
53 if (stayopen) 54 if (stayopen)
54 _res.options |= RES_STAYOPEN | RES_USEVC; 55 _resp->options |= RES_STAYOPEN | RES_USEVC;
55} 56}
56 57
57void 58void
58endhostent() 59endhostent()
59{ 60{
60 _res.options &= ~(RES_STAYOPEN | RES_USEVC); 61 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
61 _res_close(); 62
63 _resp->options &= ~(RES_STAYOPEN | RES_USEVC);
64 res_close();
62} 65}
diff --git a/src/lib/libc/net/vars6.c b/src/lib/libc/net/vars6.c
new file mode 100644
index 0000000000..a22d49d047
--- /dev/null
+++ b/src/lib/libc/net/vars6.c
@@ -0,0 +1,42 @@
1/* $OpenBSD: vars6.c,v 1.2 2003/05/10 10:56:47 jmc Exp $ */
2
3/*
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#include <sys/types.h>
33#include <netinet/in.h>
34
35/*
36 * Definitions of some constant IPv6 addresses.
37 */
38const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
39const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
40const struct in6_addr in6addr_nodelocal_allnodes = IN6ADDR_NODELOCAL_ALLNODES_INIT;
41const struct in6_addr in6addr_linklocal_allnodes = IN6ADDR_LINKLOCAL_ALLNODES_INIT;
42
diff --git a/src/lib/libc/stdlib/Makefile.inc b/src/lib/libc/stdlib/Makefile.inc
index 782a4ab022..bfbbdcb7f4 100644
--- a/src/lib/libc/stdlib/Makefile.inc
+++ b/src/lib/libc/stdlib/Makefile.inc
@@ -1,24 +1,28 @@
1# from: @(#)Makefile.inc 5.6 (Berkeley) 6/4/91 1# $OpenBDS: Makefile.inc,v 1.6 1996/08/21 03:47:21 tholo Exp $
2# $Id: Makefile.inc,v 1.1.1.1 1995/10/18 08:42:16 deraadt Exp $
3 2
4# stdlib sources 3# stdlib sources
5.PATH: ${.CURDIR}/arch/${MACHINE_ARCH}/stdlib ${.CURDIR}/stdlib 4.PATH: ${LIBCSRCDIR}/arch/${MACHINE_ARCH}/stdlib ${LIBCSRCDIR}/stdlib
6 5
7SRCS+= a64l.c abort.c atexit.c atoi.c atof.c atol.c bsearch.c calloc.c \ 6SRCS+= a64l.c abort.c atexit.c atoi.c atof.c atol.c atoll.c bsearch.c \
8 exit.c getenv.c getopt.c heapsort.c l64a.c malloc.c merge.c \ 7 calloc.c cfree.c exit.c ecvt.c gcvt.c getenv.c getopt.c getopt_long.c \
8 getsubopt.c heapsort.c l64a.c lsearch.c malloc.c merge.c \
9 multibyte.c putenv.c qsort.c radixsort.c rand.c random.c realpath.c \ 9 multibyte.c putenv.c qsort.c radixsort.c rand.c random.c realpath.c \
10 setenv.c strtod.c strtol.c strtoq.c strtoul.c strtouq.c system.c \ 10 setenv.c strtod.c strtol.c strtoll.c strtoul.c strtoull.c system.c \
11 _rand48.c drand48.c erand48.c jrand48.c lcong48.c lrand48.c \ 11 tfind.c tsearch.c _rand48.c drand48.c erand48.c jrand48.c lcong48.c \
12 mrand48.c nrand48.c seed48.c srand48.c qabs.c qdiv.c 12 lrand48.c mrand48.c nrand48.c seed48.c srand48.c qabs.c qdiv.c
13 13
14.if (${MACHINE_ARCH} == "m68k") 14.if (${MACHINE_ARCH} == "m68k")
15SRCS+= abs.S div.c labs.c ldiv.c 15SRCS+= abs.S div.c labs.c ldiv.c
16LSRCS+= abs.c
16.elif (${MACHINE_ARCH} == "i386") 17.elif (${MACHINE_ARCH} == "i386")
17SRCS+= abs.S div.S labs.S ldiv.S 18SRCS+= abs.S div.S labs.S ldiv.S
19LSRCS+= abs.c div.c labs.c ldiv.c
18.elif (${MACHINE_ARCH} == "ns32k") 20.elif (${MACHINE_ARCH} == "ns32k")
19SRCS+= abs.S div.c labs.c ldiv.c 21SRCS+= abs.S div.c labs.c ldiv.c
22LSRCS+= abs.c
20.elif (${MACHINE_ARCH} == "tahoe") 23.elif (${MACHINE_ARCH} == "tahoe")
21SRCS+= abs.S div.c labs.c ldiv.c 24SRCS+= abs.S div.c labs.c ldiv.c
25LSRCS+= abs.c
22.elif (${MACHINE_ARCH} == "vax") 26.elif (${MACHINE_ARCH} == "vax")
23SRCS+= abs.c div.c labs.c ldiv.c 27SRCS+= abs.c div.c labs.c ldiv.c
24.elif (${MACHINE_ARCH} == "alpha") 28.elif (${MACHINE_ARCH} == "alpha")
@@ -28,18 +32,36 @@ SRCS+= abs.c div.c labs.c ldiv.c
28SRCS+= abs.c div.c labs.c ldiv.c 32SRCS+= abs.c div.c labs.c ldiv.c
29.endif 33.endif
30 34
31MAN+= abort.3 abs.3 alloca.3 atexit.3 atof.3 atoi.3 atol.3 bsearch.3 \ 35.if (${MACHINE_ARCH} == "vax") || (${MACHINE_ARCH} == "m68k")
32 calloc.3 div.3 exit.3 free.3 getenv.3 getopt.3 labs.3 ldiv.3 \ 36SRCS+= insque.S remque.S
33 malloc.3 memory.3 qabs.3 qdiv.3 qsort.3 radixsort.3 rand48.3 \ 37.else
34 rand.3 random.3 realloc.3 realpath.3 strtod.3 strtol.3 strtoul.3 \ 38SRCS+= insque.c remque.c
35 system.3 39.endif
40
41MAN+= a64l.3 abort.3 abs.3 alloca.3 atexit.3 atof.3 atoi.3 atol.3 atoll.3 \
42 bsearch.3 div.3 ecvt.3 exit.3 getenv.3 getopt.3 getopt_long.3 \
43 getsubopt.3 insque.3 labs.3 ldiv.3 lsearch.3 malloc.3 memory.3 qabs.3 \
44 qdiv.3 qsort.3 radixsort.3 rand48.3 rand.3 random.3 realpath.3 \
45 strtod.3 strtol.3 strtoul.3 system.3 tsearch.3
36 46
47MLINKS+=ecvt.3 fcvt.3 ecvt.3 gcvt.3
37MLINKS+=getenv.3 setenv.3 getenv.3 unsetenv.3 getenv.3 putenv.3 48MLINKS+=getenv.3 setenv.3 getenv.3 unsetenv.3 getenv.3 putenv.3
49MLINKS+=getopt_long.3 getopt_long_only.3
50MLINKS+=insque.3 remque.3
51MLINKS+=lsearch.3 lfind.3
52MLINKS+=malloc.3 free.3 malloc.3 realloc.3 malloc.3 calloc.3
53MLINKS+=malloc.3 cfree.3 malloc.3 malloc.conf.5
38MLINKS+=qsort.3 heapsort.3 qsort.3 mergesort.3 54MLINKS+=qsort.3 heapsort.3 qsort.3 mergesort.3
39MLINKS+=rand.3 srand.3 55MLINKS+=radixsort.3 sradixsort.3
40MLINKS+=strtol.3 strtoq.3 56MLINKS+=rand.3 srand.3 rand.3 rand_r.3
41MLINKS+=strtoul.3 strtouq.3 57MLINKS+=random.3 initstate.3 random.3 setstate.3
42MLINKS+=random.3 initstate.3 random.3 setstate.3 random.3 srandom.3 58MLINKS+=random.3 srandom.3 random.3 srandomdev.3
43MLINKS+=rand48.3 drand48.3 rand48.3 erand48.3 rand48.3 lrand48.3 59MLINKS+=rand48.3 drand48.3 rand48.3 erand48.3 rand48.3 lrand48.3
44MLINKS+=rand48.3 mrand48.3 rand48.3 nrand48.3 rand48.3 jrand48.3 60MLINKS+=rand48.3 mrand48.3 rand48.3 nrand48.3 rand48.3 jrand48.3
45MLINKS+=rand48.3 srand48.3 rand48.3 seed48.3 rand48.3 lcong48.3 61MLINKS+=rand48.3 srand48.3 rand48.3 seed48.3 rand48.3 lcong48.3
62MLINKS+=strtol.3 strtoll.3 strtol.3 strtoq.3
63MLINKS+=strtoul.3 strtoull.3 strtoul.3 strtouq.3
64MLINKS+=tsearch.3 tfind.3
65MLINKS+=tsearch.3 tdelete.3
66MLINKS+=tsearch.3 twalk.3
67MLINKS+=a64l.3 l64a.3
diff --git a/src/lib/libc/stdlib/_rand48.c b/src/lib/libc/stdlib/_rand48.c
index 83ade4645a..fed7372f68 100644
--- a/src/lib/libc/stdlib/_rand48.c
+++ b/src/lib/libc/stdlib/_rand48.c
@@ -11,6 +11,10 @@
11 * to anyone/anything when using this software. 11 * to anyone/anything when using this software.
12 */ 12 */
13 13
14#if defined(LIBC_SCCS) && !defined(lint)
15static char rcsid[] = "$OpenBSD: _rand48.c,v 1.2 1996/08/19 08:33:19 tholo Exp $";
16#endif /* LIBC_SCCS and not lint */
17
14#include "rand48.h" 18#include "rand48.h"
15 19
16unsigned short __rand48_seed[3] = { 20unsigned short __rand48_seed[3] = {
diff --git a/src/lib/libc/stdlib/a64l.3 b/src/lib/libc/stdlib/a64l.3
new file mode 100644
index 0000000000..6b9fd23154
--- /dev/null
+++ b/src/lib/libc/stdlib/a64l.3
@@ -0,0 +1,144 @@
1.\" Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
2.\" All rights reserved.
3.\"
4.\" Redistribution and use in source and binary forms, with or without
5.\" modification, are permitted provided that the following conditions
6.\" are met:
7.\" 1. Redistributions of source code must retain the above copyright
8.\" notice, this list of conditions and the following disclaimer.
9.\" 2. Redistributions in binary form must reproduce the above copyright
10.\" notice, this list of conditions and the following disclaimer in the
11.\" documentation and/or other materials provided with the distribution.
12.\" 3. The name of the author may not be used to endorse or promote products
13.\" derived from this software without specific prior written permission.
14.\"
15.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
16.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
17.\" AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
18.\" THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19.\" EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20.\" PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21.\" OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22.\" WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
24.\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25.\"
26.\" $OpenBSD: a64l.3,v 1.6 2003/05/10 06:48:30 jmc Exp $
27.\"
28.Dd August 17, 1997
29.Dt A64L 3
30.Os
31.Sh NAME
32.Nm a64l ,
33.Nm l64a
34.Nd convert between 32-bit integer and radix-64 ASCII string
35.Sh SYNOPSIS
36.Fd #include <stdlib.h>
37.Ft long
38.Fn a64l "const char *s"
39.Ft char *
40.Fn l64a "long l"
41.Sh DESCRIPTION
42The
43.Fn a64l
44and
45.Fn l64a
46functions are used to maintain numbers stored in radix-64
47.Tn ASCII
48characters.
49This is a notation by which 32-bit integers
50can be represented by up to six characters; each character represents a
51.Dq digit
52in a radix-64 notation.
53.Pp
54The characters used to represent digits are
55.Ql \&.
56for 0,
57.Ql /
58for 1,
59.Ql 0
60through
61.Ql 9
62for 2-11,
63.Ql A
64through
65.Ql Z
66for 12-37, and
67.Ql a
68through
69.Ql z
70for 38-63.
71.Pp
72The
73.Fn a64l
74function takes a pointer to a null-terminated radix-64 representation
75and returns a corresponding 32-bit value.
76If the string pointed to by
77.Fa s
78contains more than six characters,
79.Fn a64l
80will use the first six.
81.Fn a64l
82scans the character string from left to right, decoding
83each character as a 6-bit radix-64 number.
84If a long integer is
85larger than 32 bits, the return value will be sign-extended.
86.Pp
87.Fn l64a
88takes a long integer argument
89.Fa l
90and returns a pointer to the corresponding radix-64 representation.
91.Sh RETURN VALUES
92On success,
93.Fn a64l
94returns a 32-bit representation of
95.Fa s .
96If
97.Fa s
98is a null pointer or if it contains digits other than those described above,
99.Fn a64l
100returns \-1 and sets the global variable
101.Va errno
102to
103.Er EINVAL .
104.Pp
105On success,
106.Fn l64a
107returns a pointer to a string containing the radix-64 representation of
108.Fa l .
109If
110.Fa l
111is 0,
112.Fn l64a
113returns a pointer to the empty string.
114If
115.Fa l
116is negative,
117.Fn l64a
118returns a null pointer and sets the global variable
119.Va errno
120to
121.Er EINVAL .
122.Sh WARNINGS
123The value returned by
124.Fn l64a
125is a pointer into a static buffer, the contents of which
126will be overwritten by subsequent calls.
127.Pp
128The value returned by
129.Fn a64l
130may be incorrect if the value is too large; for that reason, only strings
131that resulted from a call to
132.Fn l64a
133should be used to call
134.Fn a64l .
135.Pp
136If a long integer is larger than 32 bits, only the low-order
13732 bits are used.
138.Sh STANDARDS
139The
140.Fn a64l
141and
142.Fn l64a
143functions conform to
144.St -xpg4.2 .
diff --git a/src/lib/libc/stdlib/a64l.c b/src/lib/libc/stdlib/a64l.c
index 03fc77e034..a68f0a6dcd 100644
--- a/src/lib/libc/stdlib/a64l.c
+++ b/src/lib/libc/stdlib/a64l.c
@@ -4,8 +4,11 @@
4 */ 4 */
5 5
6#if defined(LIBC_SCCS) && !defined(lint) 6#if defined(LIBC_SCCS) && !defined(lint)
7static char *rcsid = "$NetBSD: a64l.c,v 1.3 1995/05/11 23:04:47 jtc Exp $"; 7static char *rcsid = "$OpenBSD: a64l.c,v 1.3 1997/08/17 22:58:34 millert Exp $";
8#endif 8#endif /* LIBC_SCCS and not lint */
9
10#include <errno.h>
11#include <stdlib.h>
9 12
10long 13long
11a64l(s) 14a64l(s)
@@ -14,21 +17,30 @@ a64l(s)
14 long value, digit, shift; 17 long value, digit, shift;
15 int i; 18 int i;
16 19
20 if (s == NULL) {
21 errno = EINVAL;
22 return(-1L);
23 }
24
17 value = 0; 25 value = 0;
18 shift = 0; 26 shift = 0;
19 for (i = 0; *s && i < 6; i++, s++) { 27 for (i = 0; *s && i < 6; i++, s++) {
20 if (*s <= '/') 28 if (*s >= '.' && *s <= '/')
21 digit = *s - '.'; 29 digit = *s - '.';
22 else if (*s <= '9') 30 else if (*s >= '0' && *s <= '9')
23 digit = *s - '0' + 2; 31 digit = *s - '0' + 2;
24 else if (*s <= 'Z') 32 else if (*s >= 'A' && *s <= 'Z')
25 digit = *s - 'A' + 12; 33 digit = *s - 'A' + 12;
26 else 34 else if (*s >= 'a' && *s <= 'z')
27 digit = *s - 'a' + 38; 35 digit = *s - 'a' + 38;
36 else {
37 errno = EINVAL;
38 return(-1L);
39 }
28 40
29 value |= digit << shift; 41 value |= digit << shift;
30 shift += 6; 42 shift += 6;
31 } 43 }
32 44
33 return (long) value; 45 return(value);
34} 46}
diff --git a/src/lib/libc/stdlib/abort.3 b/src/lib/libc/stdlib/abort.3
index ab57327585..743d42dd8a 100644
--- a/src/lib/libc/stdlib/abort.3
+++ b/src/lib/libc/stdlib/abort.3
@@ -33,8 +33,7 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)abort.3 6.7 (Berkeley) 6/29/91 36.\" $OpenBSD: abort.3,v 1.6 2000/04/20 13:50:01 aaron Exp $
37.\" $Id: abort.3,v 1.1.1.1 1995/10/18 08:42:16 deraadt Exp $
38.\" 37.\"
39.Dd June 29, 1991 38.Dd June 29, 1991
40.Dt ABORT 3 39.Dt ABORT 3
@@ -49,23 +48,20 @@
49.Sh DESCRIPTION 48.Sh DESCRIPTION
50The 49The
51.Fn abort 50.Fn abort
52function causes abnormal program termination to occur, unless the 51function causes abnormal program termination to occur, unless the signal
53signal
54.Dv SIGABRT 52.Dv SIGABRT
55is being caught and the signal handler does not return. 53is being caught and the signal handler does not return.
56.Pp 54.Pp
57No open streams are closed or flushed. 55Any open streams are flushed and closed.
58.Sh RETURN VALUES 56.Sh RETURN VALUES
59The 57The
60.Nm abort 58.Fn abort
61function 59function never returns.
62never returns.
63.Sh SEE ALSO 60.Sh SEE ALSO
64.Xr sigaction 2 , 61.Xr sigaction 2 ,
65.Xr exit 2 62.Xr exit 3
66.Sh STANDARDS 63.Sh STANDARDS
67The 64The
68.Fn abort 65.Fn abort
69function 66function conforms to
70conforms to 67.St -p1003.1-90 .
71.St -ansiC .
diff --git a/src/lib/libc/stdlib/abort.c b/src/lib/libc/stdlib/abort.c
index c298e016b4..a833a1a8b7 100644
--- a/src/lib/libc/stdlib/abort.c
+++ b/src/lib/libc/stdlib/abort.c
@@ -32,26 +32,43 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)abort.c 5.11 (Berkeley) 2/23/91";*/ 35static char *rcsid = "$OpenBSD: abort.c,v 1.11 2002/11/05 22:19:55 marc Exp $";
36static char *rcsid = "$Id: abort.c,v 1.1.1.1 1995/10/18 08:42:16 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
38 37
39#include <signal.h> 38#include <signal.h>
40#include <stdlib.h> 39#include <stdlib.h>
41#include <unistd.h> 40#include <unistd.h>
41#include "thread_private.h"
42#include "atexit.h"
42 43
43void 44void
44abort() 45abort()
45{ 46{
47 struct atexit *p = __atexit;
48 static int cleanup_called = 0;
46 sigset_t mask; 49 sigset_t mask;
47 50
51
48 sigfillset(&mask); 52 sigfillset(&mask);
49 /* 53 /*
50 * don't block SIGABRT to give any handler a chance; we ignore 54 * don't block SIGABRT to give any handler a chance; we ignore
51 * any errors -- X311J doesn't allow abort to return anyway. 55 * any errors -- X311J doesn't allow abort to return anyway.
52 */ 56 */
53 sigdelset(&mask, SIGABRT); 57 sigdelset(&mask, SIGABRT);
54 (void)sigprocmask(SIG_SETMASK, &mask, (sigset_t *)NULL); 58 (void)_thread_sys_sigprocmask(SIG_SETMASK, &mask, (sigset_t *)NULL);
59
60 /*
61 * POSIX requires we flush stdio buffers on abort
62 */
63 if (cleanup_called == 0) {
64 while (p != NULL && p->next != NULL)
65 p = p->next;
66 if (p != NULL && p->fns[0] != NULL) {
67 cleanup_called = 1;
68 (*p->fns[0])();
69 }
70 }
71
55 (void)kill(getpid(), SIGABRT); 72 (void)kill(getpid(), SIGABRT);
56 73
57 /* 74 /*
@@ -59,7 +76,7 @@ abort()
59 * it again, only harder. 76 * it again, only harder.
60 */ 77 */
61 (void)signal(SIGABRT, SIG_DFL); 78 (void)signal(SIGABRT, SIG_DFL);
62 (void)sigprocmask(SIG_SETMASK, &mask, (sigset_t *)NULL); 79 (void)_thread_sys_sigprocmask(SIG_SETMASK, &mask, (sigset_t *)NULL);
63 (void)kill(getpid(), SIGABRT); 80 (void)kill(getpid(), SIGABRT);
64 exit(1); 81 exit(1);
65} 82}
diff --git a/src/lib/libc/stdlib/abs.3 b/src/lib/libc/stdlib/abs.3
index 4748d89e77..0f7c097ade 100644
--- a/src/lib/libc/stdlib/abs.3
+++ b/src/lib/libc/stdlib/abs.3
@@ -33,8 +33,7 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)abs.3 6.4 (Berkeley) 6/29/91 36.\" $OpenBSD: abs.3,v 1.5 2000/04/20 13:50:01 aaron Exp $
37.\" $Id: abs.3,v 1.1.1.1 1995/10/18 08:42:16 deraadt Exp $
38.\" 37.\"
39.Dd June 29, 1991 38.Dd June 29, 1991
40.Dt ABS 3 39.Dt ABS 3
@@ -49,21 +48,17 @@
49.Sh DESCRIPTION 48.Sh DESCRIPTION
50The 49The
51.Fn abs 50.Fn abs
52function 51function computes the absolute value of the integer
53computes 52.Fa j .
54the absolute value of the integer
55.Ar j .
56.Sh RETURN VALUES 53.Sh RETURN VALUES
57The 54The
58.Fn abs 55.Fn abs
59function 56function returns the absolute value.
60returns
61the absolute value.
62.Sh SEE ALSO 57.Sh SEE ALSO
63.Xr floor 3 ,
64.Xr labs 3 ,
65.Xr cabs 3 , 58.Xr cabs 3 ,
59.Xr floor 3 ,
66.Xr hypot 3 , 60.Xr hypot 3 ,
61.Xr labs 3 ,
67.Xr math 3 62.Xr math 3
68.Sh STANDARDS 63.Sh STANDARDS
69The 64The
diff --git a/src/lib/libc/stdlib/abs.c b/src/lib/libc/stdlib/abs.c
index 64468e0224..7c79e4073c 100644
--- a/src/lib/libc/stdlib/abs.c
+++ b/src/lib/libc/stdlib/abs.c
@@ -32,8 +32,7 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)abs.c 5.2 (Berkeley) 5/17/90";*/ 35static char *rcsid = "$OpenBSD: abs.c,v 1.2 1996/08/19 08:33:21 tholo Exp $";
36static char *rcsid = "$Id: abs.c,v 1.1.1.1 1995/10/18 08:42:16 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
38 37
39#include <stdlib.h> 38#include <stdlib.h>
diff --git a/src/lib/libc/stdlib/alloca.3 b/src/lib/libc/stdlib/alloca.3
index dcb97ab11c..431443a6e6 100644
--- a/src/lib/libc/stdlib/alloca.3
+++ b/src/lib/libc/stdlib/alloca.3
@@ -29,12 +29,11 @@
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE. 30.\" SUCH DAMAGE.
31.\" 31.\"
32.\" from: @(#)alloca.3 5.1 (Berkeley) 5/2/91 32.\" $OpenBSD: alloca.3,v 1.9 2001/12/06 04:21:27 deraadt Exp $
33.\" $Id: alloca.3,v 1.1.1.1 1995/10/18 08:42:16 deraadt Exp $
34.\" 33.\"
35.Dd May 2, 1991 34.Dd May 2, 1991
36.Dt ALLOCA 3 35.Dt ALLOCA 3
37.Os BSD 4 36.Os
38.Sh NAME 37.Sh NAME
39.Nm alloca 38.Nm alloca
40.Nd memory allocator 39.Nd memory allocator
@@ -45,35 +44,41 @@
45.Sh DESCRIPTION 44.Sh DESCRIPTION
46The 45The
47.Fn alloca 46.Fn alloca
48function 47function allocates
49allocates
50.Fa size 48.Fa size
51bytes of space in the stack frame of the caller. 49bytes of space in the stack frame of the caller.
52This temporary space is automatically freed on 50This temporary space is automatically freed on return.
53return.
54.Sh RETURN VALUES 51.Sh RETURN VALUES
55The 52The
56.Fn alloca 53.Fn alloca
57function returns a pointer to the beginning of the allocated space. 54function returns a pointer to the beginning of the allocated space.
58If the allocation failed, a
59.Dv NULL
60pointer is returned.
61.Sh SEE ALSO 55.Sh SEE ALSO
56.Xr pagesize 1 ,
62.Xr brk 2 , 57.Xr brk 2 ,
63.Xr pagesize 2
64.Xr calloc 3 , 58.Xr calloc 3 ,
65.Xr malloc 3 , 59.Xr malloc 3 ,
66.Xr realloc 3 , 60.Xr realloc 3
67.Sh BUGS 61.Sh BUGS
68The 62The
69.Fn alloca 63.Fn alloca
70function 64function is machine dependent; its use is discouraged.
71is machine dependent; its use is discouraged.
72.\" .Sh HISTORY 65.\" .Sh HISTORY
73.\" The 66.\" The
74.\" .Fn alloca 67.\" .Fn alloca
75.\" function appeared in 68.\" function appeared in
76.\" .Bx ?? . 69.\" .Bx ?? .
77.\" The function appeared in 32v, pwb and pwb.2 and in 3bsd 4bsd 70.\" The function appeared in 32v, pwb and pwb.2 and in 3bsd 4bsd
78.\" The first man page (or link to a man page that I can find at the 71.\" The first man page (or link to a man page that I can find at the
79.\" moment is 4.3... 72.\" moment is 4.3...
73.Pp
74The
75.Fn alloca
76function is slightly unsafe because it cannot ensure that the pointer
77returned points to a valid and usable block of memory.
78The allocation made may exceed the bounds of the stack, or even go
79further into other objects in memory, and
80.Fn alloca
81cannot determine such an error.
82Avoid
83.Fn alloca
84with large unbounded allocations.
diff --git a/src/lib/libc/stdlib/atexit.3 b/src/lib/libc/stdlib/atexit.3
index 07de054d3c..5d79ede649 100644
--- a/src/lib/libc/stdlib/atexit.3
+++ b/src/lib/libc/stdlib/atexit.3
@@ -33,8 +33,7 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)atexit.3 5.3 (Berkeley) 6/29/91 36.\" $OpenBSD: atexit.3,v 1.4 2000/04/20 13:50:01 aaron Exp $
37.\" $Id: atexit.3,v 1.1.1.1 1995/10/18 08:42:16 deraadt Exp $
38.\" 37.\"
39.Dd June 29, 1991 38.Dd June 29, 1991
40.Dt ATEXIT 3 39.Dt ATEXIT 3
@@ -49,13 +48,12 @@
49.Sh DESCRIPTION 48.Sh DESCRIPTION
50The 49The
51.Fn atexit 50.Fn atexit
52function 51function registers the given
53registers the given 52.Fa function
54.Ar function
55to be called at program exit, whether via 53to be called at program exit, whether via
56.Xr exit 3 54.Xr exit 3
57or via return from the program's 55or via return from the program's
58.Em main . 56.Fn main .
59Functions so registered are called in reverse order; 57Functions so registered are called in reverse order;
60no arguments are passed. 58no arguments are passed.
61At least 32 functions can always be registered, 59At least 32 functions can always be registered,
@@ -73,6 +71,5 @@ The existing list of functions is unmodified.
73.Sh STANDARDS 71.Sh STANDARDS
74The 72The
75.Fn atexit 73.Fn atexit
76function 74function conforms to
77conforms to
78.St -ansiC . 75.St -ansiC .
diff --git a/src/lib/libc/stdlib/atexit.c b/src/lib/libc/stdlib/atexit.c
index 4da1eb0d9c..98564d0dd3 100644
--- a/src/lib/libc/stdlib/atexit.c
+++ b/src/lib/libc/stdlib/atexit.c
@@ -1,68 +1,135 @@
1/*- 1/*
2 * Copyright (c) 1990 The Regents of the University of California. 2 * Copyright (c) 2002 Daniel Hartmeier
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
5 * This code is derived from software contributed to Berkeley by
6 * Chris Torek.
7 *
8 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions 6 * modification, are permitted provided that the following conditions
10 * are met: 7 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 * 8 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 9 * - Redistributions of source code must retain the above copyright
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 10 * notice, this list of conditions and the following disclaimer.
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 11 * - Redistributions in binary form must reproduce the above
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 12 * copyright notice, this list of conditions and the following
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 13 * disclaimer in the documentation and/or other materials provided
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 14 * with the distribution.
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 15 *
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
34 * SUCH DAMAGE. 19 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
20 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
22 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 *
35 */ 29 */
36 30
37#if defined(LIBC_SCCS) && !defined(lint) 31#if defined(LIBC_SCCS) && !defined(lint)
38/*static char *sccsid = "from: @(#)atexit.c 5.2 (Berkeley) 11/14/90";*/ 32static char *rcsid = "$OpenBSD: atexit.c,v 1.7 2002/09/14 22:03:14 dhartmei Exp $";
39static char *rcsid = "$Id: atexit.c,v 1.1.1.1 1995/10/18 08:42:16 deraadt Exp $";
40#endif /* LIBC_SCCS and not lint */ 33#endif /* LIBC_SCCS and not lint */
41 34
35#include <sys/types.h>
36#include <sys/mman.h>
42#include <stdlib.h> 37#include <stdlib.h>
38#include <unistd.h>
43#include "atexit.h" 39#include "atexit.h"
44 40
41int __atexit_invalid = 1;
45struct atexit *__atexit; 42struct atexit *__atexit;
46 43
47/* 44/*
45 * Function pointers are stored in a linked list of pages. The list
46 * is initially empty, and pages are allocated on demand. The first
47 * function pointer in the first allocated page (the last one in
48 * the linked list) is reserved for the cleanup function.
49 *
50 * Outside the following two functions, all pages are mprotect()'ed
51 * to prevent unintentional/malicious corruption.
52 *
53 * The free(malloc(1)) is a workaround causing malloc_init() to
54 * ensure that malloc.c gets the first mmap() call for its sbrk()
55 * games.
56 */
57
58/*
48 * Register a function to be performed at exit. 59 * Register a function to be performed at exit.
49 */ 60 */
50int 61int
51atexit(fn) 62atexit(fn)
52 void (*fn)(); 63 void (*fn)();
53{ 64{
54 static struct atexit __atexit0; /* one guaranteed table */ 65 register struct atexit *p = __atexit;
55 register struct atexit *p; 66 register int pgsize = getpagesize();
56 67
57 if ((p = __atexit) == NULL) 68 if (pgsize < sizeof(*p))
58 __atexit = p = &__atexit0; 69 return (-1);
59 else if (p->ind >= ATEXIT_SIZE) { 70 if (p != NULL) {
60 if ((p = malloc(sizeof(*p))) == NULL) 71 if (p->ind + 1 >= p->max)
72 p = NULL;
73 else if (mprotect(p, pgsize, PROT_READ | PROT_WRITE))
74 return (-1);
75 }
76 if (p == NULL) {
77 if (__atexit_invalid) {
78 free(malloc(1));
79 __atexit_invalid = 0;
80 }
81 p = mmap(NULL, pgsize, PROT_READ | PROT_WRITE,
82 MAP_ANON | MAP_PRIVATE, -1, 0);
83 if (p == MAP_FAILED)
61 return (-1); 84 return (-1);
62 p->ind = 0; 85 if (__atexit == NULL) {
86 p->fns[0] = NULL;
87 p->ind = 1;
88 } else
89 p->ind = 0;
90 p->max = (pgsize - ((char *)&p->fns[0] - (char *)p)) /
91 sizeof(p->fns[0]);
63 p->next = __atexit; 92 p->next = __atexit;
64 __atexit = p; 93 __atexit = p;
65 } 94 }
66 p->fns[p->ind++] = fn; 95 p->fns[p->ind++] = fn;
96 if (mprotect(p, pgsize, PROT_READ))
97 return (-1);
67 return (0); 98 return (0);
68} 99}
100
101/*
102 * Register the cleanup function
103 */
104void
105__atexit_register_cleanup(fn)
106 void (*fn)();
107{
108 register struct atexit *p = __atexit;
109 register int pgsize = getpagesize();
110
111 if (pgsize < sizeof(*p))
112 return;
113 while (p != NULL && p->next != NULL)
114 p = p->next;
115 if (p == NULL) {
116 if (__atexit_invalid) {
117 free(malloc(1));
118 __atexit_invalid = 0;
119 }
120 p = mmap(NULL, pgsize, PROT_READ | PROT_WRITE,
121 MAP_ANON | MAP_PRIVATE, -1, 0);
122 if (p == MAP_FAILED)
123 return;
124 p->ind = 1;
125 p->max = (pgsize - ((char *)&p->fns[0] - (char *)p)) /
126 sizeof(p->fns[0]);
127 p->next = NULL;
128 __atexit = p;
129 } else {
130 if (mprotect(p, pgsize, PROT_READ | PROT_WRITE))
131 return;
132 }
133 p->fns[0] = fn;
134 mprotect(p, pgsize, PROT_READ);
135}
diff --git a/src/lib/libc/stdlib/atexit.h b/src/lib/libc/stdlib/atexit.h
index 8b756e8fe2..28bf3a7f27 100644
--- a/src/lib/libc/stdlib/atexit.h
+++ b/src/lib/libc/stdlib/atexit.h
@@ -1,46 +1,41 @@
1/*- 1/* $OpenBSD: atexit.h,v 1.5 2002/08/30 07:58:07 dhartmei Exp $ */
2 * Copyright (c) 1990 The Regents of the University of California. 2
3/*
4 * Copyright (c) 2002 Daniel Hartmeier
3 * All rights reserved. 5 * All rights reserved.
4 * 6 *
5 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
7 * are met: 9 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 * 10 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 11 * - Redistributions of source code must retain the above copyright
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 12 * notice, this list of conditions and the following disclaimer.
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 13 * - Redistributions in binary form must reproduce the above
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 14 * copyright notice, this list of conditions and the following
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 15 * disclaimer in the documentation and/or other materials provided
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 16 * with the distribution.
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 17 *
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
31 * SUCH DAMAGE. 21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 * 30 *
33 * from: @(#)atexit.h 5.1 (Berkeley) 5/15/90
34 * $Id: atexit.h,v 1.1.1.1 1995/10/18 08:42:16 deraadt Exp $
35 */ 31 */
36 32
37/* must be at least 32 to guarantee ANSI conformance */
38#define ATEXIT_SIZE 32
39
40struct atexit { 33struct atexit {
41 struct atexit *next; /* next in list */ 34 struct atexit *next; /* next in list */
42 int ind; /* next index in this table */ 35 int ind; /* next index in this table */
43 void (*fns[ATEXIT_SIZE])(); /* the table itself */ 36 int max; /* max entries >= ATEXIT_SIZE */
37 void (*fns[1])(); /* the table itself */
44}; 38};
45 39
40extern int __atexit_invalid;
46extern struct atexit *__atexit; /* points to head of LIFO stack */ 41extern struct atexit *__atexit; /* points to head of LIFO stack */
diff --git a/src/lib/libc/stdlib/atof.3 b/src/lib/libc/stdlib/atof.3
index 53e04f71c5..0bd85dbe82 100644
--- a/src/lib/libc/stdlib/atof.3
+++ b/src/lib/libc/stdlib/atof.3
@@ -33,8 +33,7 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)atof.3 6.4 (Berkeley) 6/29/91 36.\" $OpenBSD: atof.3,v 1.3 1999/06/29 18:36:18 aaron Exp $
37.\" $Id: atof.3,v 1.1.1.1 1995/10/18 08:42:16 deraadt Exp $
38.\" 37.\"
39.Dd June 29, 1991 38.Dd June 29, 1991
40.Dt ATOF 3 39.Dt ATOF 3
@@ -52,9 +51,9 @@ string to double
52The 51The
53.Fn atof 52.Fn atof
54function converts the initial portion of the string pointed to by 53function converts the initial portion of the string pointed to by
55.Ar nptr 54.Fa nptr
56to 55to
57.Ar double 56.Li double
58representation. 57representation.
59.Pp 58.Pp
60It is equivalent to: 59It is equivalent to:
diff --git a/src/lib/libc/stdlib/atof.c b/src/lib/libc/stdlib/atof.c
index 9202de50bb..30bac19899 100644
--- a/src/lib/libc/stdlib/atof.c
+++ b/src/lib/libc/stdlib/atof.c
@@ -32,8 +32,7 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)atof.c 5.3 (Berkeley) 1/8/93";*/ 35static char *rcsid = "$OpenBSD: atof.c,v 1.2 1996/08/19 08:33:24 tholo Exp $";
36static char *rcsid = "$Id: atof.c,v 1.1.1.1 1995/10/18 08:42:16 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
38 37
39#include <stdlib.h> 38#include <stdlib.h>
diff --git a/src/lib/libc/stdlib/atoi.3 b/src/lib/libc/stdlib/atoi.3
index 219ba73c00..69b94be70c 100644
--- a/src/lib/libc/stdlib/atoi.3
+++ b/src/lib/libc/stdlib/atoi.3
@@ -1,5 +1,5 @@
1.\" Copyright (c) 1990, 1991 The Regents of the University of California. 1.\" Copyright (c) 1990, 1991, 1993
2.\" All rights reserved. 2.\" The Regents of the University of California. All rights reserved.
3.\" 3.\"
4.\" This code is derived from software contributed to Berkeley by 4.\" This code is derived from software contributed to Berkeley by
5.\" the American National Standards Committee X3, on Information 5.\" the American National Standards Committee X3, on Information
@@ -33,10 +33,9 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)atoi.3 5.3 (Berkeley) 6/29/91 36.\" $OpenBSD: atoi.3,v 1.5 2000/04/20 13:50:01 aaron Exp $
37.\" $Id: atoi.3,v 1.1.1.1 1995/10/18 08:42:16 deraadt Exp $
38.\" 37.\"
39.Dd June 29, 1991 38.Dd June 4, 1993
40.Dt ATOI 3 39.Dt ATOI 3
41.Os 40.Os
42.Sh NAME 41.Sh NAME
@@ -52,16 +51,27 @@ string to integer
52The 51The
53.Fn atoi 52.Fn atoi
54function converts the initial portion of the string pointed to by 53function converts the initial portion of the string pointed to by
55.Em nptr 54.Fa nptr
56to 55to
57.Em integer 56.Li integer
58representation. 57representation.
59.Pp 58.Pp
60It is equivalent to: 59It is equivalent to:
61.Pp
62.Bd -literal -offset indent 60.Bd -literal -offset indent
63(int)strtol(nptr, (char **)NULL, 10); 61(int)strtol(nptr, (char **)NULL, 10);
64.Ed 62.Ed
63.Sh CAVEATS
64.Nm
65does no overflow checking, handles unsigned numbers poorly,
66and handles strings containing trailing extra characters
67(like
68.Dq "123abc" Ns )
69poorly.
70Careful use of
71.Xr strtol 3
72and
73.Xr strtoul 3
74can alleviate these problems.
65.Sh SEE ALSO 75.Sh SEE ALSO
66.Xr atof 3 , 76.Xr atof 3 ,
67.Xr atol 3 , 77.Xr atol 3 ,
diff --git a/src/lib/libc/stdlib/atoi.c b/src/lib/libc/stdlib/atoi.c
index df7845f90c..a74d6e1351 100644
--- a/src/lib/libc/stdlib/atoi.c
+++ b/src/lib/libc/stdlib/atoi.c
@@ -32,8 +32,7 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)atoi.c 5.7 (Berkeley) 2/23/91";*/ 35static char *rcsid = "$OpenBSD: atoi.c,v 1.2 1996/08/19 08:33:24 tholo Exp $";
36static char *rcsid = "$Id: atoi.c,v 1.1.1.1 1995/10/18 08:42:16 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
38 37
39#include <stdlib.h> 38#include <stdlib.h>
diff --git a/src/lib/libc/stdlib/atol.3 b/src/lib/libc/stdlib/atol.3
index 86e3d324a3..cd276a571f 100644
--- a/src/lib/libc/stdlib/atol.3
+++ b/src/lib/libc/stdlib/atol.3
@@ -33,8 +33,7 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)atol.3 5.3 (Berkeley) 6/29/91 36.\" $OpenBSD: atol.3,v 1.5 2002/11/21 20:54:09 millert Exp $
37.\" $Id: atol.3,v 1.1.1.1 1995/10/18 08:42:16 deraadt Exp $
38.\" 37.\"
39.Dd June 29, 1991 38.Dd June 29, 1991
40.Dt ATOL 3 39.Dt ATOL 3
@@ -52,9 +51,9 @@ string to long integer
52The 51The
53.Fn atol 52.Fn atol
54function converts the initial portion of the string pointed to by 53function converts the initial portion of the string pointed to by
55.Ar nptr 54.Fa nptr
56to 55to
57.Em long integer 56.Li long integer
58representation. 57representation.
59.Pp 58.Pp
60It is equivalent to: 59It is equivalent to:
@@ -64,12 +63,12 @@ strtol(nptr, (char **)NULL, 10);
64.Sh SEE ALSO 63.Sh SEE ALSO
65.Xr atof 3 , 64.Xr atof 3 ,
66.Xr atoi 3 , 65.Xr atoi 3 ,
66.Xr atoll 3 ,
67.Xr strtod 3 , 67.Xr strtod 3 ,
68.Xr strtol 3 , 68.Xr strtol 3 ,
69.Xr strtoul 3 69.Xr strtoul 3
70.Sh STANDARDS 70.Sh STANDARDS
71The 71The
72.Fn atol 72.Fn atol
73function 73function conforms to
74conforms to 74.St -ansiC-99 .
75.St -ansiC .
diff --git a/src/lib/libc/stdlib/atol.c b/src/lib/libc/stdlib/atol.c
index 31ed06298b..528a932214 100644
--- a/src/lib/libc/stdlib/atol.c
+++ b/src/lib/libc/stdlib/atol.c
@@ -32,8 +32,7 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)atol.c 5.7 (Berkeley) 2/23/91";*/ 35static char *rcsid = "$OpenBSD: atol.c,v 1.2 1996/08/19 08:33:26 tholo Exp $";
36static char *rcsid = "$Id: atol.c,v 1.1.1.1 1995/10/18 08:42:16 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
38 37
39#include <stdlib.h> 38#include <stdlib.h>
diff --git a/src/lib/libc/stdlib/calloc.3 b/src/lib/libc/stdlib/atoll.3
index d0754b46a0..8be46407c3 100644
--- a/src/lib/libc/stdlib/calloc.3
+++ b/src/lib/libc/stdlib/atoll.3
@@ -1,4 +1,4 @@
1.\" Copyright (c) 1991 The Regents of the University of California. 1.\" Copyright (c) 1990, 1991 The Regents of the University of California.
2.\" All rights reserved. 2.\" All rights reserved.
3.\" 3.\"
4.\" This code is derived from software contributed to Berkeley by 4.\" This code is derived from software contributed to Berkeley by
@@ -33,39 +33,42 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)calloc.3 5.2 (Berkeley) 6/29/91 36.\" $OpenBSD: atoll.3,v 1.2 2002/11/21 20:54:09 millert Exp $
37.\" $Id: calloc.3,v 1.1.1.1 1995/10/18 08:42:17 deraadt Exp $
38.\" 37.\"
39.Dd June 29, 1991 38.Dd June 29, 1991
40.Dt CALLOC 3 39.Dt ATOLL 3
41.Os 40.Os
42.Sh NAME 41.Sh NAME
43.Nm calloc 42.Nm atoll
44.Nd allocate clean memory (zero initialized space) 43.Nd convert
44.Tn ASCII
45string to long long integer
45.Sh SYNOPSIS 46.Sh SYNOPSIS
46.Fd #include <stdlib.h> 47.Fd #include <stdlib.h>
47.Ft void * 48.Ft long long
48.Fn calloc "size_t nmemb" "size_t size" 49.Fn atoll "const char *nptr"
49.Sh DESCRIPTION 50.Sh DESCRIPTION
50The 51The
51.Fn calloc 52.Fn atoll
52function allocates space for an array of 53function converts the initial portion of the string pointed to by
53.Fa nmemb 54.Fa nptr
54objects, each of whose size is 55to
55.Fa size . 56.Li long integer
56The space is initialized to all bits zero. 57representation.
57.Sh RETURN VALUES 58.Pp
58The 59It is equivalent to:
59.Fn calloc 60.Bd -literal -offset indent
60function returns 61strtoll(nptr, (char **)NULL, 10);
61a pointer to the 62.Ed
62the allocated space if successful; otherwise a null pointer is returned.
63.Sh SEE ALSO 63.Sh SEE ALSO
64.Xr malloc 3 , 64.Xr atof 3 ,
65.Xr realloc 3 , 65.Xr atoi 3 ,
66.Xr free 3 66.Xr atol 3 ,
67.Xr strtod 3 ,
68.Xr strtol 3 ,
69.Xr strtoul 3
67.Sh STANDARDS 70.Sh STANDARDS
68The 71The
69.Fn calloc 72.Fn atoll
70function conforms to 73function conforms to
71.St -ansiC . 74.St -ansiC-99 .
diff --git a/src/lib/libc/stdlib/atoll.c b/src/lib/libc/stdlib/atoll.c
new file mode 100644
index 0000000000..63a5b35cd4
--- /dev/null
+++ b/src/lib/libc/stdlib/atoll.c
@@ -0,0 +1,45 @@
1/*
2 * Copyright (c) 1988 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#if defined(LIBC_SCCS) && !defined(lint)
35static char *rcsid = "$OpenBSD: atoll.c,v 1.1 2002/11/21 20:51:20 millert Exp $";
36#endif /* LIBC_SCCS and not lint */
37
38#include <stdlib.h>
39
40long long
41atoll(str)
42 const char *str;
43{
44 return(strtoll(str, (char **)NULL, 10));
45}
diff --git a/src/lib/libc/stdlib/bsearch.3 b/src/lib/libc/stdlib/bsearch.3
index 1622c96c6b..9bb9d4ece4 100644
--- a/src/lib/libc/stdlib/bsearch.3
+++ b/src/lib/libc/stdlib/bsearch.3
@@ -1,5 +1,5 @@
1.\" Copyright (c) 1990, 1991 The Regents of the University of California. 1.\" Copyright (c) 1990, 1991, 1993, 1994
2.\" All rights reserved. 2.\" The Regents of the University of California. All rights reserved.
3.\" 3.\"
4.\" This code is derived from software contributed to Berkeley by 4.\" This code is derived from software contributed to Berkeley by
5.\" the American National Standards Committee X3, on Information 5.\" the American National Standards Committee X3, on Information
@@ -33,10 +33,9 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)bsearch.3 5.6 (Berkeley) 6/29/91 36.\" $OpenBSD: bsearch.3,v 1.5 2000/04/20 13:50:01 aaron Exp $
37.\" $Id: bsearch.3,v 1.1.1.1 1995/10/18 08:42:16 deraadt Exp $
38.\" 37.\"
39.Dd June 29, 1991 38.Dd April 19, 1994
40.Dt BSEARCH 3 39.Dt BSEARCH 3
41.Os 40.Os
42.Sh NAME 41.Sh NAME
@@ -51,12 +50,12 @@ The
51.Fn bsearch 50.Fn bsearch
52function searches an array of 51function searches an array of
53.Fa nmemb 52.Fa nmemb
54objects, the initial member of which is 53objects, the initial member of which is
55pointed to by 54pointed to by
56.Fa base , 55.Fa base ,
57for a member that matches the object pointed to by 56for a member that matches the object pointed to by
58.Fa key . 57.Fa key .
59The size of each member of the array is specified by 58The size of each member of the array is specified by
60.Fa size . 59.Fa size .
61.Pp 60.Pp
62The contents of the array should be in ascending sorted order according 61The contents of the array should be in ascending sorted order according
@@ -64,9 +63,7 @@ to the comparison function referenced by
64.Fa compar . 63.Fa compar .
65The 64The
66.Fa compar 65.Fa compar
67routine 66routine is expected to have two arguments which point to the
68is expected to have two
69two arguments which point to the
70.Fa key 67.Fa key
71object and to an array member, in that order, and should return an integer 68object and to an array member, in that order, and should return an integer
72less than, equal to, or greater than zero if the 69less than, equal to, or greater than zero if the
@@ -83,7 +80,7 @@ If two members compare as equal, which member is matched is unspecified.
83.Xr db 3 , 80.Xr db 3 ,
84.Xr lsearch 3 , 81.Xr lsearch 3 ,
85.Xr qsort 3 , 82.Xr qsort 3 ,
86.\" .Xr tsearch 3 83.Xr tsearch 3
87.Sh STANDARDS 84.Sh STANDARDS
88The 85The
89.Fn bsearch 86.Fn bsearch
diff --git a/src/lib/libc/stdlib/bsearch.c b/src/lib/libc/stdlib/bsearch.c
index fac03f694f..1903202b6c 100644
--- a/src/lib/libc/stdlib/bsearch.c
+++ b/src/lib/libc/stdlib/bsearch.c
@@ -32,8 +32,7 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)bsearch.c 5.4 (Berkeley) 2/23/91";*/ 35static char *rcsid = "$OpenBSD: bsearch.c,v 1.3 2002/02/16 21:27:24 millert Exp $";
36static char *rcsid = "$Id: bsearch.c,v 1.1.1.1 1995/10/18 08:42:16 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
38 37
39#include <stdlib.h> 38#include <stdlib.h>
@@ -60,7 +59,7 @@ bsearch(key, base0, nmemb, size, compar)
60 const void *base0; 59 const void *base0;
61 size_t nmemb; 60 size_t nmemb;
62 register size_t size; 61 register size_t size;
63 register int (*compar) __P((const void *, const void *)); 62 register int (*compar)(const void *, const void *);
64{ 63{
65 register const char *base = base0; 64 register const char *base = base0;
66 register int lim, cmp; 65 register int lim, cmp;
diff --git a/src/lib/libc/stdlib/calloc.c b/src/lib/libc/stdlib/calloc.c
index 3353fab052..c75b256d14 100644
--- a/src/lib/libc/stdlib/calloc.c
+++ b/src/lib/libc/stdlib/calloc.c
@@ -32,12 +32,13 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)calloc.c 5.6 (Berkeley) 2/23/91";*/ 35static char *rcsid = "$OpenBSD: calloc.c,v 1.7 2002/07/31 09:19:04 deraadt Exp $";
36static char *rcsid = "$Id: calloc.c,v 1.1.1.1 1995/10/18 08:42:17 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
38 37
39#include <stdlib.h> 38#include <stdlib.h>
40#include <string.h> 39#include <string.h>
40#include <limits.h>
41#include <errno.h>
41 42
42void * 43void *
43calloc(num, size) 44calloc(num, size)
@@ -46,8 +47,13 @@ calloc(num, size)
46{ 47{
47 register void *p; 48 register void *p;
48 49
50 if (num && size && SIZE_T_MAX / num < size) {
51 errno = ENOMEM;
52 return NULL;
53 }
49 size *= num; 54 size *= num;
50 if (p = malloc(size)) 55 p = malloc(size);
51 memset(p, '\0', size); 56 if (p)
57 memset(p, 0, size);
52 return(p); 58 return(p);
53} 59}
diff --git a/src/lib/libc/stdlib/cfree.c b/src/lib/libc/stdlib/cfree.c
new file mode 100644
index 0000000000..3af32039a9
--- /dev/null
+++ b/src/lib/libc/stdlib/cfree.c
@@ -0,0 +1,49 @@
1/* $OpenBSD: cfree.c,v 1.1 1996/08/21 03:47:22 tholo Exp $ */
2
3/*
4 * Copyright (c) 1996 SigmaSoft, Th. Lockert <tholo@sigmasoft.com>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by SigmaSoft, Th. Lockert.
18 * 4. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
22 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
23 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
24 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
30 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33#if defined(LIBC_SCCS) && !defined(lint)
34static char rcsid[] = "$OpenBSD: cfree.c,v 1.1 1996/08/21 03:47:22 tholo Exp $";
35#endif /* LIBC_SCCS and not lint */
36
37#include <sys/cdefs.h>
38
39#ifdef __indr_reference
40__indr_reference(free, cfree);
41#else
42
43void
44cfree(p)
45 void *p;
46{
47 free(p);
48}
49#endif
diff --git a/src/lib/libc/stdlib/div.3 b/src/lib/libc/stdlib/div.3
index a4730694a5..1f651d7fd3 100644
--- a/src/lib/libc/stdlib/div.3
+++ b/src/lib/libc/stdlib/div.3
@@ -31,8 +31,7 @@
31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32.\" SUCH DAMAGE. 32.\" SUCH DAMAGE.
33.\" 33.\"
34.\" from: @(#)div.3 5.2 (Berkeley) 4/19/91 34.\" $OpenBSD: div.3,v 1.5 2000/04/20 13:50:02 aaron Exp $
35.\" $Id: div.3,v 1.1.1.1 1995/10/18 08:42:17 deraadt Exp $
36.\" 35.\"
37.Dd April 19, 1991 36.Dd April 19, 1991
38.Dt DIV 3 37.Dt DIV 3
@@ -47,24 +46,22 @@
47.Sh DESCRIPTION 46.Sh DESCRIPTION
48The 47The
49.Fn div 48.Fn div
50function 49function computes the value
51computes the value 50.Fa num Ns No / Ns Fa denom
52.Fa num/denom
53and returns the quotient and remainder in a structure named 51and returns the quotient and remainder in a structure named
54.Fa div_t 52.Fa div_t
55that contains two 53that contains two
56.Em int 54.Li int
57members named 55members named
58.Fa quot 56.Fa quot
59and 57and
60.Fa rem . 58.Fa rem .
61.Sh SEE ALSO 59.Sh SEE ALSO
62.Xr ldiv 3 , 60.Xr ldiv 3 ,
63.Xr qdiv 3 , 61.Xr math 3 ,
64.Xr math 3 62.Xr qdiv 3
65.Sh STANDARDS 63.Sh STANDARDS
66The 64The
67.Fn div 65.Fn div
68function 66function conforms to
69conforms to
70.St -ansiC . 67.St -ansiC .
diff --git a/src/lib/libc/stdlib/div.c b/src/lib/libc/stdlib/div.c
index 122ac0deec..c1fae29008 100644
--- a/src/lib/libc/stdlib/div.c
+++ b/src/lib/libc/stdlib/div.c
@@ -35,8 +35,7 @@
35 */ 35 */
36 36
37#if defined(LIBC_SCCS) && !defined(lint) 37#if defined(LIBC_SCCS) && !defined(lint)
38/*static char *sccsid = "from: @(#)div.c 5.2 (Berkeley) 4/16/91";*/ 38static char *rcsid = "$OpenBSD: div.c,v 1.2 1996/08/19 08:33:29 tholo Exp $";
39static char *rcsid = "$Id: div.c,v 1.1.1.1 1995/10/18 08:42:17 deraadt Exp $";
40#endif /* LIBC_SCCS and not lint */ 39#endif /* LIBC_SCCS and not lint */
41 40
42#include <stdlib.h> /* div_t */ 41#include <stdlib.h> /* div_t */
diff --git a/src/lib/libc/stdlib/drand48.c b/src/lib/libc/stdlib/drand48.c
index ae1a8634dc..02886d5b62 100644
--- a/src/lib/libc/stdlib/drand48.c
+++ b/src/lib/libc/stdlib/drand48.c
@@ -11,6 +11,10 @@
11 * to anyone/anything when using this software. 11 * to anyone/anything when using this software.
12 */ 12 */
13 13
14#if defined(LIBC_SCCS) && !defined(lint)
15static char rcsid[] = "$OpenBSD: drand48.c,v 1.2 1996/08/19 08:33:29 tholo Exp $";
16#endif /* LIBC_SCCS and not lint */
17
14#include "rand48.h" 18#include "rand48.h"
15 19
16extern unsigned short __rand48_seed[3]; 20extern unsigned short __rand48_seed[3];
diff --git a/src/lib/libc/stdlib/ecvt.3 b/src/lib/libc/stdlib/ecvt.3
new file mode 100644
index 0000000000..64559ec09e
--- /dev/null
+++ b/src/lib/libc/stdlib/ecvt.3
@@ -0,0 +1,172 @@
1.\" $OpenBSD
2.\"
3.\" Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
4.\" All rights reserved.
5.\"
6.\" Redistribution and use in source and binary forms, with or without
7.\" modification, are permitted provided that the following conditions
8.\" are met:
9.\" 1. Redistributions of source code must retain the above copyright
10.\" notice, this list of conditions and the following disclaimer.
11.\" 2. Redistributions in binary form must reproduce the above copyright
12.\" notice, this list of conditions and the following disclaimer in the
13.\" documentation and/or other materials provided with the distribution.
14.\" 3. The name of the author may not be used to endorse or promote products
15.\" derived from this software without specific prior written permission.
16.\"
17.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
18.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
19.\" AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
20.\" THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21.\" EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22.\" PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23.\" OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24.\" WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26.\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27.\"
28.Dd December 1, 2002
29.Dt ECVT 3
30.Os
31.Sh NAME
32.Nm ecvt ,
33.Nm fcvt ,
34.Nm gcvt
35.Nd convert double to
36.Tn ASCII
37string
38.Sh SYNOPSIS
39.Fd #include <stdlib.h>
40.Ft char *
41.Fn ecvt "double value" "int ndigit" "int *decpt" "int *sign"
42.Ft char *
43.Fn fcvt "double value" "int ndigit" "int *decpt" "int *sign"
44.Ft char *
45.Fn gcvt "double value" "int ndigit" "char *buf"
46.Sh DESCRIPTION
47.Bf -symbolic
48These functions are provided for compatibility with legacy code.
49New code should use the
50.Xr snprintf 3
51function for improved safety and portability.
52.Ef
53.Pp
54The
55.Fn ecvt ,
56.Fn fcvt
57and
58.Fn gcvt
59functions convert the double precision floating-point number
60.Fa value
61to a NUL-terminated
62.Tn ASCII
63string.
64.Pp
65The
66.Fn ecvt
67function converts
68.Fa value
69to a NUL-terminated string of exactly
70.Fa ndigit
71digits and returns a pointer to that string.
72The result is padded with zeroes from left to right as needed.
73There are no leading zeroes unless
74.Fa value
75itself is 0.
76The least significant digit is rounded in an implementation-dependent manner.
77The position of the decimal point relative to the beginning of the string
78is stored in
79.Fa decpt .
80A negative value indicates that the decimal point is located
81to the left of the returned digits (this occurs when there is no
82whole number component to
83.Fa value ) .
84If
85.Fa value
86is zero, it is unspecified whether the integer pointed to by
87.Fa decpt
88will be 0 or 1.
89The decimal point itself is not included in the returned string.
90If the sign of the result is negative, the integer pointed to by
91.Fa sign
92is non-zero; otherwise, it is 0.
93.Pp
94If the converted value is out of range or is not representable,
95the contents of the returned string are unspecified.
96.Pp
97The
98.Fn fcvt
99function is identical to
100.Fn ecvt
101with the exception that
102.Fa ndigit
103specifies the number of digits after the decimal point (zero-padded as
104needed).
105.Pp
106The
107.Fn gcvt
108function converts
109.Fa value
110to a NUL-terminated string similar to the %g
111.Xr printf 3
112format specifier and stores the result in
113.Fa buf .
114It produces
115.Fa ndigit
116significant digits similar to the %f
117.Xr printf 3
118format specifier where possible.
119If
120.Fa ndigit
121does allow sufficient precision, the result is stored in
122exponential notation similar to the %e
123.Xr printf 3
124format specifier.
125If
126.Fa value
127is less than zero,
128.Fa buf
129will be prefixed with a minus sign.
130A decimal point is included in the returned string if
131.Fa value
132is not a whole number.
133Unlike the
134.Fn ecvt
135and
136.Fn fcvt
137functions,
138.Fa buf
139is not zero-padded.
140.Sh RETURN VALUES
141The
142.Fn ecvt ,
143.Fn fcvt
144and
145.Fn gcvt
146functions return a NUL-terminated string representation of
147.Fa value .
148.Sh WARNINGS
149The
150.Fn ecvt
151and
152.Fn fcvt
153functions return a pointer to internal storage space that will be
154overwritten by subsequent calls to either function.
155.Pp
156The maximum possible precision of the return value is limited by the
157precision of a double and may not be the same on all architectures.
158.Pp
159The
160.Xr snprintf 3
161function is preferred over these functions for new code.
162.Sh SEE ALSO
163.Xr printf 3 ,
164.Xr strtod 3
165.Sh STANDARDS
166The
167.Fn ecvt ,
168.Fn fcvt
169and
170.Fn gcvt
171functions conform to
172.St -susv3 .
diff --git a/src/lib/libc/stdlib/ecvt.c b/src/lib/libc/stdlib/ecvt.c
new file mode 100644
index 0000000000..7460407c84
--- /dev/null
+++ b/src/lib/libc/stdlib/ecvt.c
@@ -0,0 +1,110 @@
1/* $OpenBSD: ecvt.c,v 1.1 2002/12/02 15:38:54 millert Exp $ */
2
3/*
4 * Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
19 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
20 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
27 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char rcsid[] = "$OpenBSD: ecvt.c,v 1.1 2002/12/02 15:38:54 millert Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <stdio.h>
35#include <stdlib.h>
36#include <string.h>
37
38extern char *__dtoa(double, int, int, int *, int *, char **);
39static char *__cvt(double, int, int *, int *, int, int);
40
41static char *
42__cvt(double value, int ndigit, int *decpt, int *sign, int fmode, int pad)
43{
44 static char *s;
45 char *p, *rve;
46 size_t siz;
47
48 if (ndigit == 0) {
49 *sign = value < 0.0;
50 *decpt = 0;
51 return ("");
52 }
53
54 if (s) {
55 free(s);
56 s = NULL;
57 }
58
59 if (ndigit < 0)
60 siz = -ndigit + 1;
61 else
62 siz = ndigit + 1;
63
64
65 /* __dtoa() doesn't allocate space for 0 so we do it by hand */
66 if (value == 0.0) {
67 *decpt = 1 - fmode; /* 1 for 'e', 0 for 'f' */
68 *sign = 0;
69 if ((rve = s = (char *)malloc(siz)) == NULL)
70 return(NULL);
71 *rve++ = '0';
72 *rve = '\0';
73 } else {
74 p = __dtoa(value, fmode + 2, ndigit, decpt, sign, &rve);
75 if (*decpt == 9999) {
76 /* Nan or Infinity */
77 *decpt = 0;
78 return(p);
79 }
80 /* make a local copy and adjust rve to be in terms of s */
81 if (pad && fmode)
82 siz += *decpt;
83 if ((s = (char *)malloc(siz)) == NULL)
84 return(NULL);
85 (void) strlcpy(s, p, siz);
86 rve = s + (rve - p);
87 }
88
89 /* Add trailing zeros (unless we got NaN or Inf) */
90 if (pad && *decpt != 9999) {
91 siz -= rve - s;
92 while (--siz)
93 *rve++ = '0';
94 *rve = '\0';
95 }
96
97 return(s);
98}
99
100char *
101ecvt(double value, int ndigit, int *decpt, int *sign)
102{
103 return(__cvt(value, ndigit, decpt, sign, 0, 1));
104}
105
106char *
107fcvt(double value, int ndigit, int *decpt, int *sign)
108{
109 return(__cvt(value, ndigit, decpt, sign, 1, 1));
110}
diff --git a/src/lib/libc/stdlib/erand48.c b/src/lib/libc/stdlib/erand48.c
index cc9fbf770c..b92dacffcc 100644
--- a/src/lib/libc/stdlib/erand48.c
+++ b/src/lib/libc/stdlib/erand48.c
@@ -11,6 +11,10 @@
11 * to anyone/anything when using this software. 11 * to anyone/anything when using this software.
12 */ 12 */
13 13
14#if defined(LIBC_SCCS) && !defined(lint)
15static char rcsid[] = "$OpenBSD: erand48.c,v 1.2 1996/08/19 08:33:29 tholo Exp $";
16#endif /* LIBC_SCCS and not lint */
17
14#include "rand48.h" 18#include "rand48.h"
15 19
16double 20double
diff --git a/src/lib/libc/stdlib/exit.3 b/src/lib/libc/stdlib/exit.3
index adb81ffcb4..fb499e0946 100644
--- a/src/lib/libc/stdlib/exit.3
+++ b/src/lib/libc/stdlib/exit.3
@@ -33,8 +33,7 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)exit.3 6.6 (Berkeley) 6/29/91 36.\" $OpenBSD: exit.3,v 1.8 2003/05/10 06:48:30 jmc Exp $
37.\" $Id: exit.3,v 1.1.1.1 1995/10/18 08:42:17 deraadt Exp $
38.\" 37.\"
39.Dd June 29, 1991 38.Dd June 29, 1991
40.Dt EXIT 3 39.Dt EXIT 3
@@ -47,8 +46,9 @@
47.Ft void 46.Ft void
48.Fn exit "int status" 47.Fn exit "int status"
49.Sh DESCRIPTION 48.Sh DESCRIPTION
50.Fn Exit 49The
51terminates a process. 50.Fn exit
51function terminates a process.
52.Pp 52.Pp
53Before termination it performs the following functions in the 53Before termination it performs the following functions in the
54order listed: 54order listed:
@@ -66,19 +66,28 @@ Unlink all files created with the
66.Xr tmpfile 3 66.Xr tmpfile 3
67function. 67function.
68.El 68.El
69.Pp
70Following this,
71.Fn exit
72calls
73.Xr _exit 2 .
74Note that typically
75.Xr _exit 2
76only passes the lower 8 bits of
77.Fa status
78on to the parent, thus negative values have less meaning.
69.Sh RETURN VALUES 79.Sh RETURN VALUES
70The 80The
71.Fn exit 81.Fn exit
72function 82function never returns.
73never returns.
74.Sh SEE ALSO 83.Sh SEE ALSO
75.Xr _exit 2 , 84.Xr _exit 2 ,
76.Xr atexit 3 , 85.Xr atexit 3 ,
77.Xr intro 3 , 86.Xr intro 3 ,
87.Xr sysexits 3 ,
78.Xr tmpfile 3 88.Xr tmpfile 3
79.Sh STANDARDS 89.Sh STANDARDS
80The 90The
81.Fn exit 91.Fn exit
82function 92function conforms to
83conforms to
84.St -ansiC . 93.St -ansiC .
diff --git a/src/lib/libc/stdlib/exit.c b/src/lib/libc/stdlib/exit.c
index b1412f42bb..e22bd5178e 100644
--- a/src/lib/libc/stdlib/exit.c
+++ b/src/lib/libc/stdlib/exit.c
@@ -32,15 +32,24 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)exit.c 5.4 (Berkeley) 2/23/91";*/ 35static char *rcsid = "$OpenBSD: exit.c,v 1.8 2002/09/14 22:03:14 dhartmei Exp $";
36static char *rcsid = "$Id: exit.c,v 1.1.1.1 1995/10/18 08:42:17 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
38 37
38#include <sys/types.h>
39#include <sys/mman.h>
39#include <stdlib.h> 40#include <stdlib.h>
40#include <unistd.h> 41#include <unistd.h>
41#include "atexit.h" 42#include "atexit.h"
43#include "thread_private.h"
42 44
43void (*__cleanup)(); 45/*
46 * This variable is zero until a process has created a thread.
47 * It is used to avoid calling locking functions in libc when they
48 * are not required. By default, libc is intended to be(come)
49 * thread-safe, but without a (significant) penalty to non-threaded
50 * processes.
51 */
52int __isthreaded = 0;
44 53
45/* 54/*
46 * Exit, flushing stdio buffers if necessary. 55 * Exit, flushing stdio buffers if necessary.
@@ -49,13 +58,20 @@ void
49exit(status) 58exit(status)
50 int status; 59 int status;
51{ 60{
52 register struct atexit *p; 61 register struct atexit *p, *q;
53 register int n; 62 register int n, pgsize = getpagesize();
54 63
55 for (p = __atexit; p; p = p->next) 64 if (!__atexit_invalid) {
56 for (n = p->ind; --n >= 0;) 65 p = __atexit;
57 (*p->fns[n])(); 66 while (p != NULL) {
58 if (__cleanup) 67 for (n = p->ind; --n >= 0;)
59 (*__cleanup)(); 68 if (p->fns[n] != NULL)
69 (*p->fns[n])();
70 q = p;
71 p = p->next;
72 munmap(q, pgsize);
73 }
74 }
75 /* cleanup, if registered, was called through fns[0] in the last page */
60 _exit(status); 76 _exit(status);
61} 77}
diff --git a/src/lib/libc/stdlib/free.3 b/src/lib/libc/stdlib/free.3
deleted file mode 100644
index 3d0131d7de..0000000000
--- a/src/lib/libc/stdlib/free.3
+++ /dev/null
@@ -1,82 +0,0 @@
1.\" Copyright (c) 1991 The Regents of the University of California.
2.\" All rights reserved.
3.\"
4.\" This code is derived from software contributed to Berkeley by
5.\" the American National Standards Committee X3, on Information
6.\" Processing Systems.
7.\"
8.\" Redistribution and use in source and binary forms, with or without
9.\" modification, are permitted provided that the following conditions
10.\" are met:
11.\" 1. Redistributions of source code must retain the above copyright
12.\" notice, this list of conditions and the following disclaimer.
13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution.
16.\" 3. All advertising materials mentioning features or use of this software
17.\" must display the following acknowledgement:
18.\" This product includes software developed by the University of
19.\" California, Berkeley and its contributors.
20.\" 4. Neither the name of the University nor the names of its contributors
21.\" may be used to endorse or promote products derived from this software
22.\" without specific prior written permission.
23.\"
24.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE.
35.\"
36.\" from: @(#)free.3 5.2 (Berkeley) 6/29/91
37.\" $Id: free.3,v 1.1.1.1 1995/10/18 08:42:17 deraadt Exp $
38.\"
39.Dd June 29, 1991
40.Dt FREE 3
41.Os
42.Sh NAME
43.Nm free
44.Nd free up memory allocated with malloc, calloc or realloc
45.Sh SYNOPSIS
46.Fd #include <stdlib.h>
47.Ft void
48.Fn free "void *ptr"
49.Sh DESCRIPTION
50The
51.Fn free
52function causes the space pointed to by
53.Fa ptr
54to be deallocated, that is, made available
55for further allocation.
56If
57.Fa ptr
58is a null pointer, no action occurs.
59Otherwise, if the argument does not match a pointer earlier
60returned by the
61.Xr calloc ,
62.Xr malloc ,
63or
64.Xr realloc
65function, or if the space has been deallocated by a call to
66.Fn free
67or
68.Xr realloc ,
69general havoc may occur.
70.Sh RETURN VALUES
71The
72.Fn free
73function returns no value.
74.Sh SEE ALSO
75.Xr calloc 3 ,
76.Xr malloc 3 ,
77.Xr realloc 3
78.Sh STANDARDS
79The
80.Fn free
81function conforms to
82.St -ansiC .
diff --git a/src/lib/libc/stdlib/gcvt.c b/src/lib/libc/stdlib/gcvt.c
new file mode 100644
index 0000000000..240c4db5b0
--- /dev/null
+++ b/src/lib/libc/stdlib/gcvt.c
@@ -0,0 +1,106 @@
1/* $OpenBSD: gcvt.c,v 1.3 2003/05/09 20:01:43 millert Exp $ */
2
3/*
4 * Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
19 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
20 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
27 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char rcsid[] = "$OpenBSD: gcvt.c,v 1.3 2003/05/09 20:01:43 millert Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <stdio.h>
35#include <stdlib.h>
36#include <string.h>
37
38extern char *__dtoa(double, int, int, int *, int *, char **);
39
40char *
41gcvt(double value, int ndigit, char *buf)
42{
43 char *digits, *dst, *src;
44 int i, decpt, sign;
45
46 if (ndigit == 0) {
47 buf[0] = '\0';
48 return (buf);
49 }
50
51 digits = __dtoa(value, 2, ndigit, &decpt, &sign, NULL);
52 if (decpt == 9999) {
53 /* Infinity or NaN, assume buffer is at least ndigit long. */
54 strlcpy(buf, digits, ndigit + 1);
55 return (buf);
56 }
57
58 dst = buf;
59 if (sign)
60 *dst++ = '-';
61
62 if (decpt < 0 || decpt > ndigit) {
63 /* exponential format */
64 if (--decpt < 0) {
65 sign = 1;
66 decpt = -decpt;
67 } else
68 sign = 0;
69 for (src = digits; *src != '\0'; )
70 *dst++ = *src++;
71 *dst++ = 'e';
72 if (sign)
73 *dst++ = '-';
74 else
75 *dst++ = '+';
76 if (decpt < 10) {
77 *dst++ = '0';
78 *dst++ = '0' + decpt;
79 *dst = '\0';
80 } else {
81 /* XXX - optimize */
82 for (sign = decpt, i = 0; (sign /= 10) != 0; i++)
83 sign /= 10;
84 while (decpt != 0) {
85 dst[i--] = '0' + decpt % 10;
86 decpt /= 10;
87 }
88 }
89 } else {
90 /* standard format */
91 for (i = 0, src = digits; i < decpt; i++) {
92 if (*src != '\0')
93 *dst++ = *src++;
94 else
95 *dst++ = '0';
96 }
97 if (*src != '\0') {
98 *dst++ = '.'; /* XXX - locale-specific (LC_NUMERIC) */
99 for (i = decpt; digits[i] != '\0'; i++) {
100 *dst++ = digits[i];
101 }
102 }
103 *dst = '\0';
104 }
105 return (buf);
106}
diff --git a/src/lib/libc/stdlib/getenv.3 b/src/lib/libc/stdlib/getenv.3
index 411eb35da4..b2aa0080d6 100644
--- a/src/lib/libc/stdlib/getenv.3
+++ b/src/lib/libc/stdlib/getenv.3
@@ -1,5 +1,5 @@
1.\" Copyright (c) 1988, 1991 The Regents of the University of California. 1.\" Copyright (c) 1988, 1991, 1993
2.\" All rights reserved. 2.\" The Regents of the University of California. All rights reserved.
3.\" 3.\"
4.\" This code is derived from software contributed to Berkeley by 4.\" This code is derived from software contributed to Berkeley by
5.\" the American National Standards Committee X3, on Information 5.\" the American National Standards Committee X3, on Information
@@ -33,10 +33,9 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)getenv.3 6.11 (Berkeley) 6/29/91 36.\" $OpenBSD: getenv.3,v 1.7 2000/04/20 13:50:02 aaron Exp $
37.\" $Id: getenv.3,v 1.1.1.1 1995/10/18 08:42:17 deraadt Exp $
38.\" 37.\"
39.Dd June 29, 1991 38.Dd December 11, 1993
40.Dt GETENV 3 39.Dt GETENV 3
41.Os 40.Os
42.Sh NAME 41.Sh NAME
@@ -56,59 +55,51 @@
56.Ft void 55.Ft void
57.Fn unsetenv "const char *name" 56.Fn unsetenv "const char *name"
58.Sh DESCRIPTION 57.Sh DESCRIPTION
59These functions set, unset and fetch environment variables from the 58These functions set, unset, and fetch environment variables from the host
60host
61.Em environment list . 59.Em environment list .
62For compatibility with differing environment conventions, 60For compatibility with differing environment conventions, the given arguments
63the given arguments 61.Fa name
64.Ar name
65and 62and
66.Ar value 63.Fa value
67may be appended and prepended, 64may be appended and prepended, respectively, with an equal sign
68respectively,
69with an equal sign
70.Dq Li \&= . 65.Dq Li \&= .
71.Pp 66.Pp
72The 67The
73.Fn getenv 68.Fn getenv
74function obtains the current value of the environment variable, 69function obtains the current value of the environment variable,
75.Ar name . 70.Fa name .
76If the variable 71If the variable
77.Ar name 72.Fa name
78is not in the current environment , 73is not in the current environment, a null pointer is returned.
79a null pointer is returned.
80.Pp 74.Pp
81The 75The
82.Fn setenv 76.Fn setenv
83function inserts or resets the environment variable 77function inserts or resets the environment variable
84.Ar name 78.Fa name
85in the current environment list. 79in the current environment list.
86If the variable 80If the variable
87.Ar name 81.Fa name
88does not exist in the list, 82does not exist in the list, it is inserted with the given
89it is inserted with the given 83.Fa value .
90.Ar value.
91If the variable does exist, the argument 84If the variable does exist, the argument
92.Ar overwrite 85.Fa overwrite
93is tested; if 86is tested; if
94.Ar overwrite is 87.Fa overwrite
95zero, the 88is zero, the variable is not reset, otherwise it is reset to the given
96variable is not reset, otherwise it is reset 89.Fa value .
97to the given
98.Ar value .
99.Pp 90.Pp
100The 91The
101.Fn putenv 92.Fn putenv
102function takes an argument of the form ``name=value'' and is 93function takes an argument of the form
103equivalent to: 94.Ar name Ns No = Ns Ar value
95and is equivalent to:
104.Bd -literal -offset indent 96.Bd -literal -offset indent
105setenv(name, value, 1); 97setenv(name, value, 1);
106.Ed 98.Ed
107.Pp 99.Pp
108The 100The
109.Fn unsetenv 101.Fn unsetenv
110function 102function deletes all instances of the variable name pointed to by
111deletes all instances of the variable name pointed to by
112.Fa name 103.Fa name
113from the list. 104from the list.
114.Sh RETURN VALUES 105.Sh RETURN VALUES
@@ -118,10 +109,13 @@ and
118.Fn putenv 109.Fn putenv
119return zero if successful; otherwise the global variable 110return zero if successful; otherwise the global variable
120.Va errno 111.Va errno
121is set to indicate the error and a 112is set to indicate the error and \-1 is returned.
122\-1 is returned. 113.Pp
114If
115.Fn getenv
116is successful, the string returned should be considered read-only.
123.Sh ERRORS 117.Sh ERRORS
124.Bl -tag -width Er 118.Bl -tag -width [ENOMEM]
125.It Bq Er ENOMEM 119.It Bq Er ENOMEM
126The function 120The function
127.Fn setenv 121.Fn setenv
diff --git a/src/lib/libc/stdlib/getenv.c b/src/lib/libc/stdlib/getenv.c
index 09d47f2149..934f10928f 100644
--- a/src/lib/libc/stdlib/getenv.c
+++ b/src/lib/libc/stdlib/getenv.c
@@ -1,6 +1,6 @@
1/* 1/*
2 * Copyright (c) 1987 Regents of the University of California. 2 * Copyright (c) 1987, 1993
3 * All rights reserved. 3 * The Regents of the University of California. All rights reserved.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions 6 * modification, are permitted provided that the following conditions
@@ -32,26 +32,13 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)getenv.c 5.8 (Berkeley) 2/23/91";*/ 35static char *rcsid = "$OpenBSD: getenv.c,v 1.5 2002/12/10 22:44:12 mickey Exp $";
36static char *rcsid = "$Id: getenv.c,v 1.1.1.1 1995/10/18 08:42:17 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
38 37
39#include <stdlib.h> 38#include <stdlib.h>
40#include <string.h> 39#include <string.h>
41 40
42/* 41char *__findenv(const char *name, int *offset);
43 * getenv --
44 * Returns ptr to value associated with name, if any, else NULL.
45 */
46char *
47getenv(name)
48 const char *name;
49{
50 int offset;
51 char *__findenv();
52
53 return(__findenv(name, &offset));
54}
55 42
56/* 43/*
57 * __findenv -- 44 * __findenv --
@@ -63,20 +50,39 @@ getenv(name)
63 * This routine *should* be a static; don't use it. 50 * This routine *should* be a static; don't use it.
64 */ 51 */
65char * 52char *
66__findenv(name, offset) 53__findenv(const char *name, int *offset)
67 register char *name;
68 int *offset;
69{ 54{
70 extern char **environ; 55 extern char **environ;
71 register int len; 56 register int len, i;
72 register char **P, *C; 57 register const char *np;
58 register char **p, *cp;
59
60 if (name == NULL || environ == NULL)
61 return (NULL);
62 for (np = name; *np && *np != '='; ++np)
63 ;
64 len = np - name;
65 for (p = environ; (cp = *p) != NULL; ++p) {
66 for (np = name, i = len; i && *cp; i--)
67 if (*cp++ != *np++)
68 break;
69 if (i == 0 && *cp++ == '=') {
70 *offset = p - environ;
71 return (cp);
72 }
73 }
74 return (NULL);
75}
76
77/*
78 * getenv --
79 * Returns ptr to value associated with name, if any, else NULL.
80 */
81char *
82getenv(name)
83 const char *name;
84{
85 int offset;
73 86
74 for (C = name, len = 0; *C && *C != '='; ++C, ++len); 87 return (__findenv(name, &offset));
75 for (P = environ; *P; ++P)
76 if (!strncmp(*P, name, len))
77 if (*(C = *P + len) == '=') {
78 *offset = P - environ;
79 return(++C);
80 }
81 return(NULL);
82} 88}
diff --git a/src/lib/libc/stdlib/getopt.3 b/src/lib/libc/stdlib/getopt.3
index f843881afd..d25b497035 100644
--- a/src/lib/libc/stdlib/getopt.3
+++ b/src/lib/libc/stdlib/getopt.3
@@ -29,11 +29,11 @@
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE. 30.\" SUCH DAMAGE.
31.\" 31.\"
32.\" @(#)getopt.3 8.4 (Berkeley) 4/19/94 32.\" $OpenBSD: getopt.3,v 1.22 2003/05/10 06:48:30 jmc Exp $
33.\" 33.\"
34.Dd April 19, 1994 34.Dd December 8, 2002
35.Dt GETOPT 3 35.Dt GETOPT 3
36.Os BSD 4.3 36.Os
37.Sh NAME 37.Sh NAME
38.Nm getopt 38.Nm getopt
39.Nd get option character from command line argument list 39.Nd get option character from command line argument list
@@ -51,30 +51,28 @@ The
51.Fn getopt 51.Fn getopt
52function incrementally parses a command line argument list 52function incrementally parses a command line argument list
53.Fa argv 53.Fa argv
54and returns the next 54and returns the next known option character.
55.Em known
56option character.
57An option character is 55An option character is
58.Em known 56.Dq known
59if it has been specified in the string of accepted option characters, 57if it has been specified in the string of accepted option characters,
60.Fa optstring . 58.Fa optstring .
61.Pp 59.Pp
62The option string 60The option string
63.Fa optstring 61.Fa optstring
64may contain the following elements: individual characters, and 62may contain the following elements: individual characters and
65characters followed by a colon to indicate an option argument 63characters followed by a colon to indicate an option argument
66is to follow. 64is to follow.
67For example, an option string 65For example, an option string
68.Li "\&""x"" 66.Qq x
69recognizes an option 67recognizes an option
70.Dq Fl x , 68.Fl x ,
71and an option string 69and an option string
72.Li "\&""x:"" 70.Qq Li x:
73recognizes an option and argument 71recognizes an option and argument
74.Dq Fl x Ar argument . 72.Fl x Ar argument .
75It does not matter to 73It does not matter to
76.Fn getopt 74.Fn getopt
77if a following argument has leading white space. 75if a following argument has leading whitespace.
78.Pp 76.Pp
79On return from 77On return from
80.Fn getopt , 78.Fn getopt ,
@@ -89,12 +87,10 @@ to
89.Fn getopt . 87.Fn getopt .
90The variable 88The variable
91.Va optopt 89.Va optopt
92saves the last 90saves the last known option character returned by
93.Em known
94option character returned by
95.Fn getopt . 91.Fn getopt .
96.Pp 92.Pp
97The variable 93The variables
98.Va opterr 94.Va opterr
99and 95and
100.Va optind 96.Va optind
@@ -119,10 +115,7 @@ must be reinitialized.
119.Pp 115.Pp
120The 116The
121.Fn getopt 117.Fn getopt
122function 118function returns \-1 when the argument list is exhausted.
123returns \-1
124when the argument list is exhausted, or a non-recognized
125option is encountered.
126The interpretation of options in the argument list may be cancelled 119The interpretation of options in the argument list may be cancelled
127by the option 120by the option
128.Ql -- 121.Ql --
@@ -133,49 +126,36 @@ When all options have been processed (i.e., up to the first non-option
133argument), 126argument),
134.Fn getopt 127.Fn getopt
135returns \-1. 128returns \-1.
136.Sh DIAGNOSTICS 129.Sh RETURN VALUES
137If the 130The
138.Fn getopt 131.Fn getopt
139function encounters a character not found in the string 132function returns the next known option character in
140.Va optarg 133.Fa optstring .
141or detects
142a missing option argument it writes an error message and returns
143.Ql ?
144to the
145.Em stderr .
146Setting
147.Va opterr
148to a zero will disable these error messages.
149If 134If
150.Va optstring 135.Fn getopt
151has a leading 136encounters a character not found in
152.Ql \&: 137.Fa optstring
153then a missing option argument causes a 138or if it detects a missing option argument,
154.Ql \&: 139it returns
155to be returned in addition to suppressing any error messages. 140.Sq ? .
156.Pp 141If
157Option arguments are allowed to begin with 142.Fa optstring
158.Dq Li \- ; 143has a leading
159this is reasonable but 144.Sq \:
160reduces the amount of error checking possible. 145then a missing option argument causes
161.Sh EXTENSIONS 146.Sq \:
147to be returned instead of
148.Sq ? .
162The 149The
163.Va optreset
164variable was added to make it possible to call the
165.Fn getopt 150.Fn getopt
166function multiple times. 151function returns \-1 when the argument list is exhausted.
167This is an extension to the 152.Sh EXAMPLES
168.St -p1003.2
169specification.
170.Sh EXAMPLE
171.Bd -literal -compact 153.Bd -literal -compact
172extern char *optarg;
173extern int optind;
174int bflag, ch, fd; 154int bflag, ch, fd;
175 155
176bflag = 0; 156bflag = 0;
177while ((ch = getopt(argc, argv, "bf:")) != -1) 157while ((ch = getopt(argc, argv, "bf:")) != -1) {
178 switch(ch) { 158 switch (ch) {
179 case 'b': 159 case 'b':
180 bflag = 1; 160 bflag = 1;
181 break; 161 break;
@@ -189,31 +169,69 @@ while ((ch = getopt(argc, argv, "bf:")) != -1)
189 case '?': 169 case '?':
190 default: 170 default:
191 usage(); 171 usage();
172 }
192} 173}
193argc -= optind; 174argc -= optind;
194argv += optind; 175argv += optind;
195.Ed 176.Ed
177.Sh SEE ALSO
178.Xr getopt 1 ,
179.Xr getopt_long 3 ,
180.Xr getsubopt 3
181.Sh DIAGNOSTICS
182If the
183.Fn getopt
184function encounters a character not found in the string
185.Va optstring
186or detects
187a missing option argument it writes an error message to
188.Em stderr
189and returns
190.Ql ? .
191Setting
192.Va opterr
193to a zero will disable these error messages.
194If
195.Va optstring
196has a leading
197.Ql \&:
198then a missing option argument causes a
199.Ql \&:
200to be returned in addition to suppressing any error messages.
201.Pp
202Option arguments are allowed to begin with
203.Ql - ;
204this is reasonable but reduces the amount of error checking possible.
205.Sh EXTENSIONS
206The
207.Va optreset
208variable was added to make it possible to call the
209.Fn getopt
210function multiple times.
211This is an extension to the
212.St -p1003.2
213specification.
196.Sh HISTORY 214.Sh HISTORY
197The 215The
198.Fn getopt 216.Fn getopt
199function appeared 217function appeared in
200.Bx 4.3 . 218.Bx 4.3 .
201.Sh BUGS 219.Sh BUGS
202The 220The
203.Fn getopt 221.Fn getopt
204function was once specified to return 222function was once specified to return
205.Dv EOF 223.Dv EOF
206instead of \-1. 224instead of \-1.
207This was changed by 225This was changed by
208.St -p1003.2-92 226.St -p1003.2-92
209to decouple 227to decouple
210.Fn getopt 228.Fn getopt
211from 229from
212.Pa <stdio.h> . 230.Pa <stdio.h> .
213.Pp 231.Pp
214A single dash 232A single dash
215.Dq Li - 233.Pq Ql -
216may be specified as an character in 234may be specified as a character in
217.Fa optstring , 235.Fa optstring ,
218however it should 236however it should
219.Em never 237.Em never
@@ -221,15 +239,25 @@ have an argument associated with it.
221This allows 239This allows
222.Fn getopt 240.Fn getopt
223to be used with programs that expect 241to be used with programs that expect
224.Dq Li - 242.Ql -
225as an option flag. 243as an option flag.
226This practice is wrong, and should not be used in any current development. 244This practice is wrong, and should not be used in any current development.
227It is provided for backward compatibility 245It is provided for backward compatibility
228.Em only . 246.Em only .
247Care should be taken not to use
248.Ql -
249as the first character in
250.Fa optstring
251to avoid a semantic conflict with
252.Tn GNU
253.Fn getopt ,
254which assigns different meaning to an
255.Fa optstring
256that begins with a
257.Ql - .
229By default, a single dash causes 258By default, a single dash causes
230.Fn getopt 259.Fn getopt
231to return \-1. 260to return \-1.
232This is, we believe, compatible with System V.
233.Pp 261.Pp
234It is also possible to handle digits as option letters. 262It is also possible to handle digits as option letters.
235This allows 263This allows
@@ -242,18 +270,19 @@ It is provided for backward compatibility
242.Em only . 270.Em only .
243The following code fragment works in most cases. 271The following code fragment works in most cases.
244.Bd -literal -offset indent 272.Bd -literal -offset indent
245int length; 273int ch;
274long length;
246char *p; 275char *p;
247 276
248while ((c = getopt(argc, argv, "0123456789")) != -1) 277while ((ch = getopt(argc, argv, "0123456789")) != -1) {
249 switch (c) { 278 switch (ch) {
250 case '0': case '1': case '2': case '3': case '4': 279 case '0': case '1': case '2': case '3': case '4':
251 case '5': case '6': case '7': case '8': case '9': 280 case '5': case '6': case '7': case '8': case '9':
252 p = argv[optind - 1]; 281 p = argv[optind - 1];
253 if (p[0] == '-' && p[1] == ch && !p[2]) 282 if (p[0] == '-' && p[1] == ch && !p[2])
254 length = atoi(++p); 283 length = ch - '0';
255 else 284 else
256 length = atoi(argv[optind] + 1); 285 length = strtol(argv[optind] + 1, NULL, 10);
257 break; 286 break;
258 } 287 }
259} 288}
diff --git a/src/lib/libc/stdlib/getopt.c b/src/lib/libc/stdlib/getopt.c
index 63c5e6a479..fc0f8c1bc7 100644
--- a/src/lib/libc/stdlib/getopt.c
+++ b/src/lib/libc/stdlib/getopt.c
@@ -32,8 +32,7 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35/* static char sccsid[] = "from: @(#)getopt.c 8.2 (Berkeley) 4/2/94"; */ 35static char *rcsid = "$OpenBSD: getopt.c,v 1.4 2002/12/08 22:57:14 millert Exp $";
36static char *rcsid = "$Id: getopt.c,v 1.1.1.1 1995/10/18 08:42:17 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
38 37
39#include <stdio.h> 38#include <stdio.h>
@@ -64,6 +63,9 @@ getopt(nargc, nargv, ostr)
64 static char *place = EMSG; /* option letter processing */ 63 static char *place = EMSG; /* option letter processing */
65 char *oli; /* option letter list index */ 64 char *oli; /* option letter list index */
66 65
66 if (ostr == NULL)
67 return (-1);
68
67 if (optreset || !*place) { /* update scanning pointer */ 69 if (optreset || !*place) { /* update scanning pointer */
68 optreset = 0; 70 optreset = 0;
69 if (optind >= nargc || *(place = nargv[optind]) != '-') { 71 if (optind >= nargc || *(place = nargv[optind]) != '-') {
diff --git a/src/lib/libc/stdlib/getopt_long.3 b/src/lib/libc/stdlib/getopt_long.3
new file mode 100644
index 0000000000..2589bd7b03
--- /dev/null
+++ b/src/lib/libc/stdlib/getopt_long.3
@@ -0,0 +1,373 @@
1.\" $OpenBSD: getopt_long.3,v 1.6 2003/05/10 06:48:30 jmc Exp $
2.\" $NetBSD: getopt_long.3,v 1.11 2002/10/02 10:54:19 wiz Exp $
3.\"
4.\" Copyright (c) 1988, 1991, 1993
5.\" The Regents of the University of California. All rights reserved.
6.\"
7.\" Redistribution and use in source and binary forms, with or without
8.\" modification, are permitted provided that the following conditions
9.\" are met:
10.\" 1. Redistributions of source code must retain the above copyright
11.\" notice, this list of conditions and the following disclaimer.
12.\" 2. Redistributions in binary form must reproduce the above copyright
13.\" notice, this list of conditions and the following disclaimer in the
14.\" documentation and/or other materials provided with the distribution.
15.\" 3. All advertising materials mentioning features or use of this software
16.\" must display the following acknowledgement:
17.\" This product includes software developed by the University of
18.\" California, Berkeley and its contributors.
19.\" 4. Neither the name of the University nor the names of its contributors
20.\" may be used to endorse or promote products derived from this software
21.\" without specific prior written permission.
22.\"
23.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33.\" SUCH DAMAGE.
34.\"
35.\" @(#)getopt.3 8.5 (Berkeley) 4/27/95
36.\"
37.Dd April 1, 2000
38.Dt GETOPT_LONG 3
39.Os
40.Sh NAME
41.Nm getopt_long ,
42.Nm getopt_long_only
43.Nd get long options from command line argument list
44.Sh SYNOPSIS
45.Fd #include <getopt.h>
46.Vt extern char *optarg;
47.Vt extern int optind;
48.Vt extern int optopt;
49.Vt extern int opterr;
50.Vt extern int optreset;
51.Ft int
52.Fn getopt_long "int argc" "char * const *argv" "const char *optstring" "const struct option *longopts" "int *index"
53.Ft int
54.Fn getopt_long_only "int argc" "char * const *argv" "const char *optstring" "const struct option *longopts" "int *index"
55.Sh DESCRIPTION
56The
57.Fn getopt_long
58function is similar to
59.Xr getopt 3
60but it accepts options in two forms: words and characters.
61The
62.Fn getopt_long
63function provides a superset of the functionality of
64.Xr getopt 3 .
65.Fn getopt_long
66can be used in two ways.
67In the first way, every long option understood by the program has a
68corresponding short option, and the option structure is only used to
69translate from long options to short options.
70When used in this fashion,
71.Fn getopt_long
72behaves identically to
73.Xr getopt 3 .
74This is a good way to add long option processing to an existing program
75with the minimum of rewriting.
76.Pp
77In the second mechanism, a long option sets a flag in the
78.Fa option
79structure passed, or will store a pointer to the command line argument
80in the
81.Fa option
82structure passed to it for options that take arguments.
83Additionally, the long option's argument may be specified as a single
84argument with an equal sign, e.g.
85.Bd -literal
86myprogram --myoption=somevalue
87.Ed
88.Pp
89When a long option is processed the call to
90.Fn getopt_long
91will return 0.
92For this reason, long option processing without
93shortcuts is not backwards compatible with
94.Xr getopt 3 .
95.Pp
96It is possible to combine these methods, providing for long options
97processing with short option equivalents for some options.
98Less frequently used options would be processed as long options only.
99.Pp
100The
101.Fn getopt_long
102call requires a structure to be initialized describing the long
103options.
104The structure is:
105.Bd -literal
106struct option {
107 char *name;
108 int has_arg;
109 int *flag;
110 int val;
111};
112.Ed
113.Pp
114The
115.Fa name
116field should contain the option name without the leading double dash.
117.Pp
118The
119.Fa has_arg
120field should be one of:
121.Bl -tag -width "optional_argument"
122.It Li no_argument
123no argument to the option is expect.
124.It Li required_argument
125an argument to the option is required.
126.It Li optional_argument
127an argument to the option may be presented.
128.El
129.Pp
130If
131.Fa flag
132is not
133.Dv NULL ,
134then the integer pointed to by it will be set to the value in the
135.Fa val
136field.
137If the
138.Fa flag
139field is
140.Dv NULL ,
141then the
142.Fa val
143field will be returned.
144Setting
145.Fa flag
146to
147.Dv NULL
148and setting
149.Fa val
150to the corresponding short option will make this function act just
151like
152.Xr getopt 3 .
153.Pp
154The
155.Fn getopt_long_only
156function behaves identically to
157.Fn getopt_long
158with the exception that long options may start with
159.Sq -
160in addition to
161.Sq -- .
162If an option starting with
163.Sq -
164does not match a long option but does match a single-character option,
165the single-character option is returned.
166.Sh RETURN VALUES
167If the
168.Fa flag
169field in
170.Li struct option
171is
172.Dv NULL ,
173.Fn getopt_long
174and
175.Fn getopt_long_only
176return the value specified in the
177.Fa val
178field, which is usually just the corresponding short option.
179If
180.Fa flag
181is not
182.Dv NULL ,
183these functions return 0 and store
184.Fa val
185in the location pointed to by
186.Fa flag .
187These functions return
188.Sq \:
189if there was a missing option argument,
190.Sq ?
191if the user specified an unknown or ambiguous option, and
192\-1 when the argument list has been exhausted.
193.Sh EXAMPLES
194.Bd -literal -compact
195int bflag, ch, fd;
196int daggerset;
197
198/* options descriptor */
199static struct option longopts[] = {
200 { "buffy", no_argument, 0, 'b' },
201 { "fluoride", required_argument, 0, 'f' },
202 { "daggerset", no_argument, &daggerset, 1 },
203 { 0, 0, 0, 0 }
204};
205
206bflag = 0;
207while ((ch = getopt_long(argc, argv, "bf:", longopts, NULL)) != -1)
208 switch(ch) {
209 case 'b':
210 bflag = 1;
211 break;
212 case 'f':
213 if ((fd = open(optarg, O_RDONLY, 0)) == -1)
214 err(1, "unable to open %s", optarg);
215 break;
216 case 0:
217 if (daggerset) {
218 fprintf(stderr,"Buffy will use her dagger to "
219 "apply fluoride to dracula's teeth\en");
220 }
221 break;
222 case '?':
223 default:
224 usage();
225}
226argc -= optind;
227argv += optind;
228.Ed
229.Sh IMPLEMENTATION DIFFERENCES
230This section describes differences to the GNU implementation
231found in glibc-2.1.3:
232.Bl -tag -width "xxx"
233.It Li o
234handling of - as first char of option string in presence of
235environment variable POSIXLY_CORRECT:
236.Bl -tag -width "OpenBSD"
237.It Li GNU
238ignores POSIXLY_CORRECT and returns non-options as
239arguments to option '\e1'.
240.It Li OpenBSD
241honors POSIXLY_CORRECT and stops at the first non-option.
242.El
243.It Li o
244handling of - within the option string (not the first character):
245.Bl -tag -width "OpenBSD"
246.It Li GNU
247treats a
248.Ql -
249on the command line as a non-argument.
250.It Li OpenBSD
251a
252.Ql -
253within the option string matches a
254.Ql -
255(single dash) on the command line.
256This functionality is provided for backward compatibility with
257programs, such as
258.Xr su 1 ,
259that use
260.Ql -
261as an option flag.
262This practice is wrong, and should not be used in any current development.
263.El
264.It Li o
265handling of :: in options string in presence of POSIXLY_CORRECT:
266.Bl -tag -width "OpenBSD"
267.It Li Both
268GNU and OpenBSD ignore POSIXLY_CORRECT here and take :: to
269mean the preceding option takes an optional argument.
270.El
271.It Li o
272return value in case of missing argument if first character
273(after + or -) in option string is not ':':
274.Bl -tag -width "OpenBSD"
275.It Li GNU
276returns '?'
277.It OpenBSD
278returns ':' (since OpenBSD's getopt does).
279.El
280.It Li o
281handling of --a in getopt:
282.Bl -tag -width "OpenBSD"
283.It Li GNU
284parses this as option '-', option 'a'.
285.It Li OpenBSD
286parses this as '--', and returns \-1 (ignoring the a).
287(Because the original getopt does.)
288.El
289.It Li o
290setting of optopt for long options with flag !=
291.Dv NULL :
292.Bl -tag -width "OpenBSD"
293.It Li GNU
294sets optopt to val.
295.It Li OpenBSD
296sets optopt to 0 (since val would never be returned).
297.El
298.It Li o
299handling of -W with W; in option string in getopt (not getopt_long):
300.Bl -tag -width "OpenBSD"
301.It Li GNU
302causes a segfault.
303.It Li OpenBSD
304no special handling is done;
305.Dq W;
306is interpreted as two separate options, neither of which take an argument.
307.El
308.It Li o
309setting of optarg for long options without an argument that are
310invoked via -W (W; in option string):
311.Bl -tag -width "OpenBSD"
312.It Li GNU
313sets optarg to the option name (the argument of -W).
314.It Li OpenBSD
315sets optarg to
316.Dv NULL
317(the argument of the long option).
318.El
319.It Li o
320handling of -W with an argument that is not (a prefix to) a known
321long option (W; in option string):
322.Bl -tag -width "OpenBSD"
323.It Li GNU
324returns -W with optarg set to the unknown option.
325.It Li OpenBSD
326treats this as an error (unknown option) and returns '?' with
327optopt set to 0 and optarg set to
328.Dv NULL
329(as GNU's man page documents).
330.El
331.It Li o
332The error messages are different.
333.It Li o
334OpenBSD does not permute the argument vector at the same points in
335the calling sequence as GNU does.
336The aspects normally used by the caller
337(ordering after \-1 is returned, value of optind relative
338to current positions) are the same, though.
339(We do fewer variable swaps.)
340.El
341.Sh ENVIRONMENT
342.Bl -tag -width POSIXLY_CORRECT
343.It Ev POSIXLY_CORRECT
344If set, option processing stops when the first non-option is found and
345a leading
346.Sq -
347or
348.Sq +
349in the
350.Ar optstring
351is ignored.
352.El
353.Sh SEE ALSO
354.Xr getopt 3
355.Sh HISTORY
356The
357.Fn getopt_long
358and
359.Fn getopt_long_only
360functions first appeared in GNU libiberty.
361This implementation first appeared in
362.Ox 3.3 .
363.Sh BUGS
364The
365.Ar argv
366argument is not really
367.Dv const
368as its elements may be permuted (unless
369.Ev POSIXLY_CORRECT
370is set).
371.Pp
372In a future release, this implementation should completely replace
373.Xr getopt 3 .
diff --git a/src/lib/libc/stdlib/getopt_long.c b/src/lib/libc/stdlib/getopt_long.c
new file mode 100644
index 0000000000..0cdc4d652f
--- /dev/null
+++ b/src/lib/libc/stdlib/getopt_long.c
@@ -0,0 +1,543 @@
1/* $OpenBSD: getopt_long.c,v 1.11 2002/12/10 17:51:42 millert Exp $ */
2/* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */
3
4/*
5 * Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
20 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
21 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
22 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30/*-
31 * Copyright (c) 2000 The NetBSD Foundation, Inc.
32 * All rights reserved.
33 *
34 * This code is derived from software contributed to The NetBSD Foundation
35 * by Dieter Baron and Thomas Klausner.
36 *
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
39 * are met:
40 * 1. Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in the
44 * documentation and/or other materials provided with the distribution.
45 * 3. All advertising materials mentioning features or use of this software
46 * must display the following acknowledgement:
47 * This product includes software developed by the NetBSD
48 * Foundation, Inc. and its contributors.
49 * 4. Neither the name of The NetBSD Foundation nor the names of its
50 * contributors may be used to endorse or promote products derived
51 * from this software without specific prior written permission.
52 *
53 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
54 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
55 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
56 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
57 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
58 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
59 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
60 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
61 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
62 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
63 * POSSIBILITY OF SUCH DAMAGE.
64 */
65
66#if defined(LIBC_SCCS) && !defined(lint)
67static char *rcsid = "$OpenBSD: getopt_long.c,v 1.11 2002/12/10 17:51:42 millert Exp $";
68#endif /* LIBC_SCCS and not lint */
69
70#include <err.h>
71#include <errno.h>
72#include <getopt.h>
73#include <stdlib.h>
74#include <string.h>
75
76#ifdef REPLACE_GETOPT
77int opterr = 1; /* if error message should be printed */
78int optind = 1; /* index into parent argv vector */
79int optopt = '?'; /* character checked for validity */
80int optreset; /* reset getopt */
81char *optarg; /* argument associated with option */
82#endif
83
84#define PRINT_ERROR ((opterr) && (*options != ':'))
85
86#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */
87#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */
88#define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */
89
90/* return values */
91#define BADCH (int)'?'
92#define BADARG ((*options == ':') ? (int)':' : (int)'?')
93#define INORDER (int)1
94
95#define EMSG ""
96
97static int getopt_internal(int, char * const *, const char *,
98 const struct option *, int *, int);
99static int parse_long_options(char * const *, const char *,
100 const struct option *, int *, int);
101static int gcd(int, int);
102static void permute_args(int, int, int, char * const *);
103
104static char *place = EMSG; /* option letter processing */
105
106/* XXX: set optreset to 1 rather than these two */
107static int nonopt_start = -1; /* first non option argument (for permute) */
108static int nonopt_end = -1; /* first option after non options (for permute) */
109
110/* Error messages */
111static const char recargchar[] = "option requires an argument -- %c";
112static const char recargstring[] = "option requires an argument -- %s";
113static const char ambig[] = "ambiguous option -- %.*s";
114static const char noarg[] = "option doesn't take an argument -- %.*s";
115static const char illoptchar[] = "unknown option -- %c";
116static const char illoptstring[] = "unknown option -- %s";
117
118/*
119 * Compute the greatest common divisor of a and b.
120 */
121static int
122gcd(int a, int b)
123{
124 int c;
125
126 c = a % b;
127 while (c != 0) {
128 a = b;
129 b = c;
130 c = a % b;
131 }
132
133 return (b);
134}
135
136/*
137 * Exchange the block from nonopt_start to nonopt_end with the block
138 * from nonopt_end to opt_end (keeping the same order of arguments
139 * in each block).
140 */
141static void
142permute_args(int panonopt_start, int panonopt_end, int opt_end,
143 char * const *nargv)
144{
145 int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
146 char *swap;
147
148 /*
149 * compute lengths of blocks and number and size of cycles
150 */
151 nnonopts = panonopt_end - panonopt_start;
152 nopts = opt_end - panonopt_end;
153 ncycle = gcd(nnonopts, nopts);
154 cyclelen = (opt_end - panonopt_start) / ncycle;
155
156 for (i = 0; i < ncycle; i++) {
157 cstart = panonopt_end+i;
158 pos = cstart;
159 for (j = 0; j < cyclelen; j++) {
160 if (pos >= panonopt_end)
161 pos -= nnonopts;
162 else
163 pos += nopts;
164 swap = nargv[pos];
165 /* LINTED const cast */
166 ((char **) nargv)[pos] = nargv[cstart];
167 /* LINTED const cast */
168 ((char **)nargv)[cstart] = swap;
169 }
170 }
171}
172
173/*
174 * parse_long_options --
175 * Parse long options in argc/argv argument vector.
176 * Returns -1 if short_too is set and the option does not match long_options.
177 */
178static int
179parse_long_options(char * const *nargv, const char *options,
180 const struct option *long_options, int *idx, int short_too)
181{
182 char *current_argv, *has_equal;
183 size_t current_argv_len;
184 int i, match;
185
186 current_argv = place;
187 match = -1;
188
189 optind++;
190
191 if ((has_equal = strchr(current_argv, '=')) != NULL) {
192 /* argument found (--option=arg) */
193 current_argv_len = has_equal - current_argv;
194 has_equal++;
195 } else
196 current_argv_len = strlen(current_argv);
197
198 for (i = 0; long_options[i].name; i++) {
199 /* find matching long option */
200 if (strncmp(current_argv, long_options[i].name,
201 current_argv_len))
202 continue;
203
204 if (strlen(long_options[i].name) == current_argv_len) {
205 /* exact match */
206 match = i;
207 break;
208 }
209 /*
210 * If this is a known short option, don't allow
211 * a partial match of a single character.
212 */
213 if (short_too && current_argv_len == 1)
214 continue;
215
216 if (match == -1) /* partial match */
217 match = i;
218 else {
219 /* ambiguous abbreviation */
220 if (PRINT_ERROR)
221 warnx(ambig, (int)current_argv_len,
222 current_argv);
223 optopt = 0;
224 return (BADCH);
225 }
226 }
227 if (match != -1) { /* option found */
228 if (long_options[match].has_arg == no_argument
229 && has_equal) {
230 if (PRINT_ERROR)
231 warnx(noarg, (int)current_argv_len,
232 current_argv);
233 /*
234 * XXX: GNU sets optopt to val regardless of flag
235 */
236 if (long_options[match].flag == NULL)
237 optopt = long_options[match].val;
238 else
239 optopt = 0;
240 return (BADARG);
241 }
242 if (long_options[match].has_arg == required_argument ||
243 long_options[match].has_arg == optional_argument) {
244 if (has_equal)
245 optarg = has_equal;
246 else if (long_options[match].has_arg ==
247 required_argument) {
248 /*
249 * optional argument doesn't use next nargv
250 */
251 optarg = nargv[optind++];
252 }
253 }
254 if ((long_options[match].has_arg == required_argument)
255 && (optarg == NULL)) {
256 /*
257 * Missing argument; leading ':' indicates no error
258 * should be generated.
259 */
260 if (PRINT_ERROR)
261 warnx(recargstring,
262 current_argv);
263 /*
264 * XXX: GNU sets optopt to val regardless of flag
265 */
266 if (long_options[match].flag == NULL)
267 optopt = long_options[match].val;
268 else
269 optopt = 0;
270 --optind;
271 return (BADARG);
272 }
273 } else { /* unknown option */
274 if (short_too) {
275 --optind;
276 return (-1);
277 }
278 if (PRINT_ERROR)
279 warnx(illoptstring, current_argv);
280 optopt = 0;
281 return (BADCH);
282 }
283 if (idx)
284 *idx = match;
285 if (long_options[match].flag) {
286 *long_options[match].flag = long_options[match].val;
287 return (0);
288 } else
289 return (long_options[match].val);
290}
291
292/*
293 * getopt_internal --
294 * Parse argc/argv argument vector. Called by user level routines.
295 */
296static int
297getopt_internal(int nargc, char * const *nargv, const char *options,
298 const struct option *long_options, int *idx, int flags)
299{
300 char *oli; /* option letter list index */
301 int optchar, short_too;
302 static int posixly_correct = -1;
303
304 if (options == NULL)
305 return (-1);
306
307 /*
308 * Disable GNU extensions if POSIXLY_CORRECT is set or options
309 * string begins with a '+'.
310 */
311 if (posixly_correct == -1)
312 posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
313 if (posixly_correct || *options == '+')
314 flags &= ~FLAG_PERMUTE;
315 else if (*options == '-')
316 flags |= FLAG_ALLARGS;
317 if (*options == '+' || *options == '-')
318 options++;
319
320 /*
321 * XXX Some GNU programs (like cvs) set optind to 0 instead of
322 * XXX using optreset. Work around this braindamage.
323 */
324 if (optind == 0)
325 optind = optreset = 1;
326
327 optarg = NULL;
328 if (optreset)
329 nonopt_start = nonopt_end = -1;
330start:
331 if (optreset || !*place) { /* update scanning pointer */
332 optreset = 0;
333 if (optind >= nargc) { /* end of argument vector */
334 place = EMSG;
335 if (nonopt_end != -1) {
336 /* do permutation, if we have to */
337 permute_args(nonopt_start, nonopt_end,
338 optind, nargv);
339 optind -= nonopt_end - nonopt_start;
340 }
341 else if (nonopt_start != -1) {
342 /*
343 * If we skipped non-options, set optind
344 * to the first of them.
345 */
346 optind = nonopt_start;
347 }
348 nonopt_start = nonopt_end = -1;
349 return (-1);
350 }
351 if (*(place = nargv[optind]) != '-' ||
352 (place[1] == '\0' && strchr(options, '-') == NULL)) {
353 place = EMSG; /* found non-option */
354 if (flags & FLAG_ALLARGS) {
355 /*
356 * GNU extension:
357 * return non-option as argument to option 1
358 */
359 optarg = nargv[optind++];
360 return (INORDER);
361 }
362 if (!(flags & FLAG_PERMUTE)) {
363 /*
364 * If no permutation wanted, stop parsing
365 * at first non-option.
366 */
367 return (-1);
368 }
369 /* do permutation */
370 if (nonopt_start == -1)
371 nonopt_start = optind;
372 else if (nonopt_end != -1) {
373 permute_args(nonopt_start, nonopt_end,
374 optind, nargv);
375 nonopt_start = optind -
376 (nonopt_end - nonopt_start);
377 nonopt_end = -1;
378 }
379 optind++;
380 /* process next argument */
381 goto start;
382 }
383 if (nonopt_start != -1 && nonopt_end == -1)
384 nonopt_end = optind;
385
386 /*
387 * Check for "--" or "--foo" with no long options
388 * but if place is simply "-" leave it unmolested.
389 */
390 if (place[1] != '\0' && *++place == '-' &&
391 (place[1] == '\0' || long_options == NULL)) {
392 optind++;
393 place = EMSG;
394 /*
395 * We found an option (--), so if we skipped
396 * non-options, we have to permute.
397 */
398 if (nonopt_end != -1) {
399 permute_args(nonopt_start, nonopt_end,
400 optind, nargv);
401 optind -= nonopt_end - nonopt_start;
402 }
403 nonopt_start = nonopt_end = -1;
404 return (-1);
405 }
406 }
407
408 /*
409 * Check long options if:
410 * 1) we were passed some
411 * 2) the arg is not just "-"
412 * 3) either the arg starts with -- we are getopt_long_only()
413 */
414 if (long_options != NULL && place != nargv[optind] &&
415 (*place == '-' || (flags & FLAG_LONGONLY))) {
416 short_too = 0;
417 if (*place == '-')
418 place++; /* --foo long option */
419 else if (*place != ':' && strchr(options, *place) != NULL)
420 short_too = 1; /* could be short option too */
421
422 optchar = parse_long_options(nargv, options, long_options,
423 idx, short_too);
424 if (optchar != -1) {
425 place = EMSG;
426 return (optchar);
427 }
428 }
429
430 if ((optchar = (int)*place++) == (int)':' ||
431 (oli = strchr(options, optchar)) == NULL) {
432 /*
433 * If the user didn't specify '-' as an option,
434 * assume it means -1 as POSIX specifies.
435 */
436 if (optchar == (int)'-')
437 return (-1);
438 /* option letter unknown or ':' */
439 if (!*place)
440 ++optind;
441 if (PRINT_ERROR)
442 warnx(illoptchar, optchar);
443 optopt = optchar;
444 return (BADCH);
445 }
446 if (long_options != NULL && optchar == 'W' && oli[1] == ';') {
447 /* -W long-option */
448 if (*place) /* no space */
449 /* NOTHING */;
450 else if (++optind >= nargc) { /* no arg */
451 place = EMSG;
452 if (PRINT_ERROR)
453 warnx(recargchar, optchar);
454 optopt = optchar;
455 return (BADARG);
456 } else /* white space */
457 place = nargv[optind];
458 optchar = parse_long_options(nargv, options, long_options,
459 idx, 0);
460 place = EMSG;
461 return (optchar);
462 }
463 if (*++oli != ':') { /* doesn't take argument */
464 if (!*place)
465 ++optind;
466 } else { /* takes (optional) argument */
467 optarg = NULL;
468 if (*place) /* no white space */
469 optarg = place;
470 /* XXX: disable test for :: if PC? (GNU doesn't) */
471 else if (oli[1] != ':') { /* arg not optional */
472 if (++optind >= nargc) { /* no arg */
473 place = EMSG;
474 if (PRINT_ERROR)
475 warnx(recargchar, optchar);
476 optopt = optchar;
477 return (BADARG);
478 } else
479 optarg = nargv[optind];
480 }
481 place = EMSG;
482 ++optind;
483 }
484 /* dump back option letter */
485 return (optchar);
486}
487
488#ifdef REPLACE_GETOPT
489/*
490 * getopt --
491 * Parse argc/argv argument vector.
492 *
493 * [eventually this will replace the BSD getopt]
494 */
495int
496getopt(int nargc, char * const *nargv, const char *options)
497{
498
499 /*
500 * We dont' pass FLAG_PERMUTE to getopt_internal() since
501 * the BSD getopt(3) (unlike GNU) has never done this.
502 *
503 * Furthermore, since many privileged programs call getopt()
504 * before dropping privileges it makes sense to keep things
505 * as simple (and bug-free) as possible.
506 */
507 return (getopt_internal(nargc, nargv, options, NULL, NULL, 0));
508}
509#endif /* REPLACE_GETOPT */
510
511/*
512 * getopt_long --
513 * Parse argc/argv argument vector.
514 */
515int
516getopt_long(nargc, nargv, options, long_options, idx)
517 int nargc;
518 char * const *nargv;
519 const char *options;
520 const struct option *long_options;
521 int *idx;
522{
523
524 return (getopt_internal(nargc, nargv, options, long_options, idx,
525 FLAG_PERMUTE));
526}
527
528/*
529 * getopt_long_only --
530 * Parse argc/argv argument vector.
531 */
532int
533getopt_long_only(nargc, nargv, options, long_options, idx)
534 int nargc;
535 char * const *nargv;
536 const char *options;
537 const struct option *long_options;
538 int *idx;
539{
540
541 return (getopt_internal(nargc, nargv, options, long_options, idx,
542 FLAG_PERMUTE|FLAG_LONGONLY));
543}
diff --git a/src/lib/libc/stdlib/getsubopt.3 b/src/lib/libc/stdlib/getsubopt.3
new file mode 100644
index 0000000000..e2d8641016
--- /dev/null
+++ b/src/lib/libc/stdlib/getsubopt.3
@@ -0,0 +1,147 @@
1.\" $OpenBSD: getsubopt.3,v 1.6 2003/05/10 06:48:30 jmc Exp $
2.\"
3.\" Copyright (c) 1990, 1991, 1993
4.\" The Regents of the University of California. All rights reserved.
5.\"
6.\" Redistribution and use in source and binary forms, with or without
7.\" modification, are permitted provided that the following conditions
8.\" are met:
9.\" 1. Redistributions of source code must retain the above copyright
10.\" notice, this list of conditions and the following disclaimer.
11.\" 2. Redistributions in binary form must reproduce the above copyright
12.\" notice, this list of conditions and the following disclaimer in the
13.\" documentation and/or other materials provided with the distribution.
14.\" 3. All advertising materials mentioning features or use of this software
15.\" must display the following acknowledgement:
16.\" This product includes software developed by the University of
17.\" California, Berkeley and its contributors.
18.\" 4. Neither the name of the University nor the names of its contributors
19.\" may be used to endorse or promote products derived from this software
20.\" without specific prior written permission.
21.\"
22.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32.\" SUCH DAMAGE.
33.\"
34.\" @(#)getsubopt.3 8.1 (Berkeley) 6/9/93
35.\"
36.Dd June 9, 1993
37.Dt GETSUBOPT 3
38.Os
39.Sh NAME
40.Nm getsubopt
41.Nd get sub options from an argument
42.Sh SYNOPSIS
43.Fd #include <stdlib.h>
44.Vt extern char *suboptarg;
45.Ft int
46.Fn getsubopt "char **optionp" "char * const *tokens" "char **valuep"
47.Sh DESCRIPTION
48The
49.Fn getsubopt
50function parses a string containing tokens delimited by one or more
51tab, space or comma
52.Pq Ql \&,
53characters.
54It is intended for use in parsing groups of option arguments provided
55as part of a utility command line.
56.Pp
57The argument
58.Fa optionp
59is a pointer to a pointer to the string.
60The argument
61.Fa tokens
62is a pointer to a null-terminated array of pointers to strings.
63.Pp
64The
65.Fn getsubopt
66function returns the zero-based offset of the pointer in the
67.Fa tokens
68array referencing a string which matches the first token
69in the string, or \-1 if the string contains no tokens or
70.Fa tokens
71does not contain a matching string.
72.Pp
73If the token is of the form
74.Ar name Ns No = Ns Ar value ,
75the location referenced by
76.Fa valuep
77will be set to point to the start of the
78.Dq value
79portion of the token.
80.Pp
81On return from
82.Fn getsubopt ,
83.Fa optionp
84will be set to point to the start of the next token in the string,
85or the null at the end of the string if no more tokens are present.
86The external variable
87.Fa suboptarg
88will be set to point to the start of the current token, or
89.Dv NULL
90if no tokens were present.
91The argument
92.Fa valuep
93will be set to point to the value portion of the token, or
94.Dv NULL
95if no value portion was present.
96.Sh EXAMPLES
97.Bd -literal -compact
98char *tokens[] = {
99 #define ONE 0
100 "one",
101 #define TWO 1
102 "two",
103 NULL
104};
105
106\&...
107
108extern char *optarg, *suboptarg;
109char *options, *value;
110
111while ((ch = getopt(argc, argv, "ab:")) != \-1) {
112 switch(ch) {
113 case 'a':
114 /* process ``a'' option */
115 break;
116 case 'b':
117 options = optarg;
118 while (*options) {
119 switch(getsubopt(&options, tokens, &value)) {
120 case ONE:
121 /* process ``one'' sub option */
122 break;
123 case TWO:
124 /* process ``two'' sub option */
125 if (!value)
126 error("no value for two");
127 i = atoi(value);
128 break;
129 case \-1:
130 if (suboptarg)
131 error("illegal sub option %s",
132 suboptarg);
133 else
134 error("missing sub option");
135 break;
136 }
137 break;
138 }
139.Ed
140.Sh SEE ALSO
141.Xr getopt 3 ,
142.Xr strsep 3
143.Sh HISTORY
144The
145.Fn getsubopt
146function first appeared in
147.Bx 4.4 .
diff --git a/src/lib/libc/stdlib/getsubopt.c b/src/lib/libc/stdlib/getsubopt.c
new file mode 100644
index 0000000000..1667a31d7d
--- /dev/null
+++ b/src/lib/libc/stdlib/getsubopt.c
@@ -0,0 +1,106 @@
1/* $OpenBSD: getsubopt.c,v 1.1 1997/08/20 04:02:17 millert Exp $ */
2
3/*-
4 * Copyright (c) 1990, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36#ifndef lint
37#if 0
38static char sccsid[] = "@(#)getsubopt.c 8.1 (Berkeley) 6/4/93";
39#else
40static char rcsid[] = "$OpenBSD: getsubopt.c,v 1.1 1997/08/20 04:02:17 millert Exp $";
41#endif
42#endif /* not lint */
43
44#include <unistd.h>
45#include <stdlib.h>
46#include <string.h>
47
48/*
49 * The SVID interface to getsubopt provides no way of figuring out which
50 * part of the suboptions list wasn't matched. This makes error messages
51 * tricky... The extern variable suboptarg is a pointer to the token
52 * which didn't match.
53 */
54char *suboptarg;
55
56int
57getsubopt(optionp, tokens, valuep)
58 register char **optionp, **valuep;
59 register char * const *tokens;
60{
61 register int cnt;
62 register char *p;
63
64 suboptarg = *valuep = NULL;
65
66 if (!optionp || !*optionp)
67 return(-1);
68
69 /* skip leading white-space, commas */
70 for (p = *optionp; *p && (*p == ',' || *p == ' ' || *p == '\t'); ++p);
71
72 if (!*p) {
73 *optionp = p;
74 return(-1);
75 }
76
77 /* save the start of the token, and skip the rest of the token. */
78 for (suboptarg = p;
79 *++p && *p != ',' && *p != '=' && *p != ' ' && *p != '\t';);
80
81 if (*p) {
82 /*
83 * If there's an equals sign, set the value pointer, and
84 * skip over the value part of the token. Terminate the
85 * token.
86 */
87 if (*p == '=') {
88 *p = '\0';
89 for (*valuep = ++p;
90 *p && *p != ',' && *p != ' ' && *p != '\t'; ++p);
91 if (*p)
92 *p++ = '\0';
93 } else
94 *p++ = '\0';
95 /* Skip any whitespace or commas after this token. */
96 for (; *p && (*p == ',' || *p == ' ' || *p == '\t'); ++p);
97 }
98
99 /* set optionp for next round. */
100 *optionp = p;
101
102 for (cnt = 0; *tokens; ++tokens, ++cnt)
103 if (!strcmp(suboptarg, *tokens))
104 return(cnt);
105 return(-1);
106}
diff --git a/src/lib/libc/stdlib/heapsort.c b/src/lib/libc/stdlib/heapsort.c
index bd998fa357..2770e5b977 100644
--- a/src/lib/libc/stdlib/heapsort.c
+++ b/src/lib/libc/stdlib/heapsort.c
@@ -35,8 +35,7 @@
35 */ 35 */
36 36
37#if defined(LIBC_SCCS) && !defined(lint) 37#if defined(LIBC_SCCS) && !defined(lint)
38/*static char sccsid[] = "from: @(#)heapsort.c 8.1 (Berkeley) 6/4/93";*/ 38static char *rcsid = "$OpenBSD: heapsort.c,v 1.3 2002/02/16 21:27:24 millert Exp $";
39static char *rcsid = "$Id: heapsort.c,v 1.1.1.1 1995/10/18 08:42:17 deraadt Exp $";
40#endif /* LIBC_SCCS and not lint */ 39#endif /* LIBC_SCCS and not lint */
41 40
42#include <sys/types.h> 41#include <sys/types.h>
@@ -142,7 +141,7 @@ int
142heapsort(vbase, nmemb, size, compar) 141heapsort(vbase, nmemb, size, compar)
143 void *vbase; 142 void *vbase;
144 size_t nmemb, size; 143 size_t nmemb, size;
145 int (*compar) __P((const void *, const void *)); 144 int (*compar)(const void *, const void *);
146{ 145{
147 register int cnt, i, j, l; 146 register int cnt, i, j, l;
148 register char tmp, *tmp1, *tmp2; 147 register char tmp, *tmp1, *tmp2;
diff --git a/src/lib/libc/stdlib/insque.3 b/src/lib/libc/stdlib/insque.3
new file mode 100644
index 0000000000..b87adb87bc
--- /dev/null
+++ b/src/lib/libc/stdlib/insque.3
@@ -0,0 +1,100 @@
1.\" $OpenBSD: insque.3,v 1.1 2003/05/08 23:26:30 millert Exp $
2.\" Copyright (c) 1993 John Brezak
3.\" All rights reserved.
4.\"
5.\" Redistribution and use in source and binary forms, with or without
6.\" modification, are permitted provided that the following conditions
7.\" are met:
8.\" 1. Redistributions of source code must retain the above copyright
9.\" notice, this list of conditions and the following disclaimer.
10.\" 2. Redistributions in binary form must reproduce the above copyright
11.\" notice, this list of conditions and the following disclaimer in the
12.\" documentation and/or other materials provided with the distribution.
13.\" 3. The name of the author may be used to endorse or promote products
14.\" derived from this software without specific prior written permission.
15.\"
16.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND
17.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
20.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26.\" SUCH DAMAGE.
27.\"
28.\"
29.Dd August 12, 1993
30.Dt INSQUE 3
31.Os
32.Sh NAME
33.Nm insque ,
34.Nm remque
35.Nd insert/remove element from a queue
36.Sh SYNOPSIS
37.Fd #include <search.h>
38.Ft void
39.Fn insque "void *elem" "void *pred"
40.Ft void
41.Fn remque "void *elem"
42.Sh DESCRIPTION
43.Bf -symbolic
44These interfaces have been superceded by the
45.Xr queue 3
46macros and are provided for compatibility with legacy code.
47.Ef
48.Pp
49.Fn insque
50and
51.Fn remque
52manipulate queues built from doubly linked lists.
53The queue can be either circular or linear.
54Each element in the queue must be of the following form:
55.Bd -literal
56struct qelem {
57 struct qelem *q_forw;
58 struct qelem *q_back;
59 char q_data[];
60};
61.Ed
62.Pp
63The first two elements in the struct must be pointers of the
64same type that point to the previous and next elements in
65the queue respectively.
66Any subsequent data in the struct is application-dependent.
67.Pp
68The
69.Fn insque
70function inserts
71.Fa elem
72into a queue immediately after
73.Fa pred .
74.Pp
75The
76.Fn remque
77function removes
78.Fa elem
79from the queue.
80.Sh DIAGNOSTICS
81These functions are not atomic unless that machine architecture allows it.
82.Sh SEE ALSO
83.Xr queue 3
84.Sh STANDARDS
85The
86.Fn lsearch
87and
88.Fn lfind
89functions conform to the
90.St -p1003.1-01
91and
92.St -xpg4.3 .
93specifications.
94.Sh HISTORY
95The
96.Fn insque
97and
98.Fn remque
99functions are derived from the insque and remque instructions on a
100.Tn VAX .
diff --git a/src/lib/libc/stdlib/insque.c b/src/lib/libc/stdlib/insque.c
new file mode 100644
index 0000000000..549246c71f
--- /dev/null
+++ b/src/lib/libc/stdlib/insque.c
@@ -0,0 +1,52 @@
1/* $OpenBSD: insque.c,v 1.1 2003/05/08 23:26:30 millert Exp $ */
2
3/*
4 * Copyright (c) 1993 John Brezak
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#if defined(LIBC_SCCS) && !defined(lint)
32static char *rcsid = "$OpenBSD: insque.c,v 1.1 2003/05/08 23:26:30 millert Exp $";
33#endif /* LIBC_SCCS and not lint */
34
35#include <search.h>
36
37struct qelem {
38 struct qelem *q_forw;
39 struct qelem *q_back;
40};
41
42void
43insque(void *entry, void *pred)
44{
45 struct qelem *e = (struct qelem *) entry;
46 struct qelem *p = (struct qelem *) pred;
47
48 e->q_forw = p->q_forw;
49 e->q_back = p;
50 p->q_forw->q_back = e;
51 p->q_forw = e;
52}
diff --git a/src/lib/libc/stdlib/jrand48.c b/src/lib/libc/stdlib/jrand48.c
index 205781e0ee..99cddb71e5 100644
--- a/src/lib/libc/stdlib/jrand48.c
+++ b/src/lib/libc/stdlib/jrand48.c
@@ -11,6 +11,10 @@
11 * to anyone/anything when using this software. 11 * to anyone/anything when using this software.
12 */ 12 */
13 13
14#if defined(LIBC_SCCS) && !defined(lint)
15static char rcsid[] = "$OpenBSD: jrand48.c,v 1.2 1996/08/19 08:33:33 tholo Exp $";
16#endif /* LIBC_SCCS and not lint */
17
14#include "rand48.h" 18#include "rand48.h"
15 19
16long 20long
diff --git a/src/lib/libc/stdlib/l64a.c b/src/lib/libc/stdlib/l64a.c
index 3069b31bf6..4e99391254 100644
--- a/src/lib/libc/stdlib/l64a.c
+++ b/src/lib/libc/stdlib/l64a.c
@@ -4,13 +4,14 @@
4 */ 4 */
5 5
6#if defined(LIBC_SCCS) && !defined(lint) 6#if defined(LIBC_SCCS) && !defined(lint)
7static char *rcsid = "$NetBSD: l64a.c,v 1.4 1995/05/11 23:04:52 jtc Exp $"; 7static char *rcsid = "$OpenBSD: l64a.c,v 1.3 1997/08/17 22:58:34 millert Exp $";
8#endif 8#endif /* LIBC_SCCS and not lint */
9 9
10#include <errno.h>
10#include <stdlib.h> 11#include <stdlib.h>
11 12
12char * 13char *
13l64a (value) 14l64a(value)
14 long value; 15 long value;
15{ 16{
16 static char buf[8]; 17 static char buf[8];
@@ -18,8 +19,10 @@ l64a (value)
18 int digit; 19 int digit;
19 int i; 20 int i;
20 21
21 if (!value) 22 if (value < 0) {
22 return NULL; 23 errno = EINVAL;
24 return(NULL);
25 }
23 26
24 for (i = 0; value != 0 && i < 6; i++) { 27 for (i = 0; value != 0 && i < 6; i++) {
25 digit = value & 0x3f; 28 digit = value & 0x3f;
@@ -39,5 +42,5 @@ l64a (value)
39 42
40 *s = '\0'; 43 *s = '\0';
41 44
42 return buf; 45 return(buf);
43} 46}
diff --git a/src/lib/libc/stdlib/labs.3 b/src/lib/libc/stdlib/labs.3
index 28e4d2053c..fe39ca24dc 100644
--- a/src/lib/libc/stdlib/labs.3
+++ b/src/lib/libc/stdlib/labs.3
@@ -33,8 +33,7 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)labs.3 5.3 (Berkeley) 6/29/91 36.\" $OpenBSD: labs.3,v 1.5 2000/04/20 13:50:02 aaron Exp $
37.\" $Id: labs.3,v 1.1.1.1 1995/10/18 08:42:17 deraadt Exp $
38.\" 37.\"
39.Dd June 29, 1991 38.Dd June 29, 1991
40.Dt LABS 3 39.Dt LABS 3
@@ -49,19 +48,17 @@
49.Sh DESCRIPTION 48.Sh DESCRIPTION
50The 49The
51.Fn labs 50.Fn labs
52function 51function returns the absolute value of the long integer
53returns the absolute value of the long integer 52.Fa j .
54.Ar j .
55.Sh SEE ALSO 53.Sh SEE ALSO
56.Xr abs 3 , 54.Xr abs 3 ,
57.Xr floor 3 ,
58.Xr cabs 3 , 55.Xr cabs 3 ,
56.Xr floor 3 ,
59.Xr math 3 57.Xr math 3
60.Sh STANDARDS 58.Sh STANDARDS
61The 59The
62.Fn labs 60.Fn labs
63function 61function conforms to
64conforms to
65.St -ansiC . 62.St -ansiC .
66.Sh BUGS 63.Sh BUGS
67The absolute value of the most negative integer remains negative. 64The absolute value of the most negative integer remains negative.
diff --git a/src/lib/libc/stdlib/labs.c b/src/lib/libc/stdlib/labs.c
index ccf1415792..f20e2c29be 100644
--- a/src/lib/libc/stdlib/labs.c
+++ b/src/lib/libc/stdlib/labs.c
@@ -32,8 +32,7 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)labs.c 5.2 (Berkeley) 5/17/90";*/ 35static char *rcsid = "$OpenBSD: labs.c,v 1.2 1996/08/19 08:33:34 tholo Exp $";
36static char *rcsid = "$Id: labs.c,v 1.1.1.1 1995/10/18 08:42:17 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
38 37
39#include <stdlib.h> 38#include <stdlib.h>
diff --git a/src/lib/libc/stdlib/lcong48.c b/src/lib/libc/stdlib/lcong48.c
index 965d46b17a..44bd74e48a 100644
--- a/src/lib/libc/stdlib/lcong48.c
+++ b/src/lib/libc/stdlib/lcong48.c
@@ -11,6 +11,10 @@
11 * to anyone/anything when using this software. 11 * to anyone/anything when using this software.
12 */ 12 */
13 13
14#if defined(LIBC_SCCS) && !defined(lint)
15static char rcsid[] = "$OpenBSD: lcong48.c,v 1.2 1996/08/19 08:33:35 tholo Exp $";
16#endif /* LIBC_SCCS and not lint */
17
14#include "rand48.h" 18#include "rand48.h"
15 19
16extern unsigned short __rand48_seed[3]; 20extern unsigned short __rand48_seed[3];
diff --git a/src/lib/libc/stdlib/ldiv.3 b/src/lib/libc/stdlib/ldiv.3
index a7b5ccf878..b5301b1b21 100644
--- a/src/lib/libc/stdlib/ldiv.3
+++ b/src/lib/libc/stdlib/ldiv.3
@@ -33,8 +33,7 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)ldiv.3 5.3 (Berkeley) 6/29/91 36.\" $OpenBSD: ldiv.3,v 1.5 2000/04/20 13:50:02 aaron Exp $
37.\" $Id: ldiv.3,v 1.1.1.1 1995/10/18 08:42:18 deraadt Exp $
38.\" 37.\"
39.Dd June 29, 1991 38.Dd June 29, 1991
40.Dt LDIV 3 39.Dt LDIV 3
@@ -49,24 +48,22 @@
49.Sh DESCRIPTION 48.Sh DESCRIPTION
50The 49The
51.Fn ldiv 50.Fn ldiv
52function 51function computes the value
53computes the value 52.Fa num Ns No / Ns Fa denom
54.Ar num/denom
55and returns the quotient and remainder in a structure named 53and returns the quotient and remainder in a structure named
56.Ar ldiv_t 54.Li ldiv_t
57that contains two 55that contains two
58.Em long integer 56.Li long integer
59members named 57members named
60.Ar quot 58.Fa quot
61and 59and
62.Ar rem . 60.Fa rem .
63.Sh SEE ALSO 61.Sh SEE ALSO
64.Xr div 3 , 62.Xr div 3 ,
65.Xr qdiv 3 , 63.Xr math 3 ,
66.Xr math 3 64.Xr qdiv 3
67.Sh STANDARDS 65.Sh STANDARDS
68The 66The
69.Fn ldiv 67.Fn ldiv
70function 68function conforms to
71conforms to
72.St -ansiC . 69.St -ansiC .
diff --git a/src/lib/libc/stdlib/ldiv.c b/src/lib/libc/stdlib/ldiv.c
index f7074507e5..908c2bf0aa 100644
--- a/src/lib/libc/stdlib/ldiv.c
+++ b/src/lib/libc/stdlib/ldiv.c
@@ -35,8 +35,7 @@
35 */ 35 */
36 36
37#if defined(LIBC_SCCS) && !defined(lint) 37#if defined(LIBC_SCCS) && !defined(lint)
38/*static char *sccsid = "from: @(#)ldiv.c 5.2 (Berkeley) 4/16/91";*/ 38static char *rcsid = "$OpenBSD: ldiv.c,v 1.2 1996/08/19 08:33:35 tholo Exp $";
39static char *rcsid = "$Id: ldiv.c,v 1.1.1.1 1995/10/18 08:42:18 deraadt Exp $";
40#endif /* LIBC_SCCS and not lint */ 39#endif /* LIBC_SCCS and not lint */
41 40
42#include <stdlib.h> /* ldiv_t */ 41#include <stdlib.h> /* ldiv_t */
diff --git a/src/lib/libc/stdlib/lrand48.c b/src/lib/libc/stdlib/lrand48.c
index 8e7f26237f..6b7524a51b 100644
--- a/src/lib/libc/stdlib/lrand48.c
+++ b/src/lib/libc/stdlib/lrand48.c
@@ -11,6 +11,10 @@
11 * to anyone/anything when using this software. 11 * to anyone/anything when using this software.
12 */ 12 */
13 13
14#if defined(LIBC_SCCS) && !defined(lint)
15static char rcsid[] = "$OpenBSD: lrand48.c,v 1.2 1996/08/19 08:33:36 tholo Exp $";
16#endif /* LIBC_SCCS and not lint */
17
14#include "rand48.h" 18#include "rand48.h"
15 19
16extern unsigned short __rand48_seed[3]; 20extern unsigned short __rand48_seed[3];
diff --git a/src/lib/libc/stdlib/realloc.3 b/src/lib/libc/stdlib/lsearch.3
index 66f09b2081..3e17d131e4 100644
--- a/src/lib/libc/stdlib/realloc.3
+++ b/src/lib/libc/stdlib/lsearch.3
@@ -1,5 +1,5 @@
1.\" Copyright (c) 1991 The Regents of the University of California. 1.\" Copyright (c) 1989, 1991, 1993
2.\" All rights reserved. 2.\" The Regents of the University of California. All rights reserved.
3.\" 3.\"
4.\" Redistribution and use in source and binary forms, with or without 4.\" Redistribution and use in source and binary forms, with or without
5.\" modification, are permitted provided that the following conditions 5.\" modification, are permitted provided that the following conditions
@@ -29,72 +29,79 @@
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE. 30.\" SUCH DAMAGE.
31.\" 31.\"
32.\" from: @(#)realloc.3 5.1 (Berkeley) 5/2/91 32.\" @(#)lsearch.3 8.1 (Berkeley) 6/4/93
33.\" $Id: realloc.3,v 1.1.1.1 1995/10/18 08:42:19 deraadt Exp $
34.\" 33.\"
35.Dd May 2, 1991 34.Dd June 4, 1993
36.Dt REALLOC 3 35.Dt LSEARCH 3
37.Os 36.Os
38.Sh NAME 37.Sh NAME
39.Nm realloc 38.Nm lsearch ,
40.Nd reallocation of memory function 39.Nm lfind
40.Nd linear searching routines
41.Sh SYNOPSIS 41.Sh SYNOPSIS
42.Fd #include <stdlib.h> 42.Ft char *
43.Ft void * 43.Fn lsearch "const void *key" "const void *base" "size_t *nelp" "size_t width" "int (*compar)(void *, void *)"
44.Fn realloc "void *ptr" "size_t size" 44.Ft char *
45.Fn lfind "const void *key" "const void *base" "size_t *nelp" "size_t width" "int (*compar)(void *, void *)"
45.Sh DESCRIPTION 46.Sh DESCRIPTION
47The functions
48.Fn lsearch ,
49and
50.Fn lfind
51provide basic linear searching functionality.
52.Pp
53.Fa base
54is the pointer to the beginning of an array.
55The argument
56.Fa nelp
57is the current number of elements in the array, where each element
58is
59.Fa width
60bytes long.
46The 61The
47.Fn realloc 62.Fa compar
48function changes the size of the object pointed to by 63function
49.Fa ptr 64is a comparison routine which is used to compare two elements.
50to the size specified by 65It takes two arguments which point to the
51.Fa size . 66.Fa key
52The contents of the object are unchanged up to the lesser 67object and to an array member, in that order, and must return an integer
53of the new and old sizes. 68less than, equivalent to, or greater than zero if the
54If the new size is larger, the value of the newly allocated portion 69.Fa key
55of the object is indeterminate. 70object is considered, respectively, to be less than, equal to, or greater
56If 71than the array member.
57.Fa ptr
58is a null pointer, the
59.Fn realloc
60function behaves like the
61.Xr malloc 3
62function for the specified size.
63Otherwise, if
64.Fa ptr
65does not match a pointer earlier returned by the
66.Xr calloc 3 ,
67.Xr malloc 3 ,
68or
69.Fn realloc
70function, or if the space has been deallocated
71by a call to the
72.Xr free
73or
74.Fn realloc
75function, unpredictable and usually detrimental
76behavior will occur.
77If the space cannot be allocated, the object
78pointed to by
79.Fa ptr
80is unchanged.
81If
82.Fa size
83is zero and
84.Fa ptr
85is not a null pointer, the object it points to is freed.
86.Pp 72.Pp
87The 73The
88.Fn realloc 74.Fn lsearch
89function returns either a null pointer or a pointer 75and
90to the possibly moved allocated space. 76.Fn lfind
77functions
78return a pointer into the array referenced by
79.Fa base
80where
81.Fa key
82is located.
83If
84.Fa key
85does not exist,
86.Fn lfind
87will return a null pointer and
88.Fn lsearch
89will add it to the array.
90When an element is added to the array by
91.Fn lsearch
92the location referenced by the argument
93.Fa nelp
94is incremented by one.
91.Sh SEE ALSO 95.Sh SEE ALSO
92.Xr alloca 3 , 96.Xr bsearch 3 ,
93.Xr calloc 3 , 97.Xr db 3
94.Xr free 3 ,
95.Xr malloc 3 ,
96.Sh STANDARDS 98.Sh STANDARDS
97The 99The
98.Fn realloc 100.Fn lsearch
99function conforms to 101and
100.St -ansiC . 102.Fn lfind
103functions conform to the
104.St -p1003.1-01
105and
106.St -xpg4.3 .
107specifications.
diff --git a/src/lib/libc/stdlib/lsearch.c b/src/lib/libc/stdlib/lsearch.c
new file mode 100644
index 0000000000..ba0aad3cfc
--- /dev/null
+++ b/src/lib/libc/stdlib/lsearch.c
@@ -0,0 +1,90 @@
1/*
2 * Copyright (c) 1989, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Roger L. Snyder.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37#if defined(LIBC_SCCS) && !defined(lint)
38static char sccsid[] = "@(#)lsearch.c 8.1 (Berkeley) 6/4/93";
39#endif /* LIBC_SCCS and not lint */
40
41#include <sys/types.h>
42#include <string.h>
43#include <search.h>
44
45typedef int (*cmp_fn_t)(const void *, const void *);
46static void *linear_base(const void *, const void *, size_t *, size_t,
47 cmp_fn_t, int);
48
49void *
50lsearch(const void *key, const void *base, size_t *nelp, size_t width,
51 cmp_fn_t compar)
52{
53
54 return(linear_base(key, base, nelp, width, compar, 1));
55}
56
57void *
58lfind(const void *key, const void *base, size_t *nelp, size_t width,
59 cmp_fn_t compar)
60{
61 return(linear_base(key, base, nelp, width, compar, 0));
62}
63
64static void *
65linear_base(const void *key, const void *base, size_t *nelp, size_t width,
66 cmp_fn_t compar, int add_flag)
67{
68 const char *element, *end;
69
70 end = (const char *)base + *nelp * width;
71 for (element = base; element < end; element += width)
72 if (!compar(key, element)) /* key found */
73 return((void *)element);
74
75 if (!add_flag) /* key not found */
76 return(NULL);
77
78 /*
79 * The UNIX System User's Manual, 1986 edition claims that
80 * a NULL pointer is returned by lsearch with errno set
81 * appropriately, if there is not enough room in the table
82 * to add a new item. This can't be done as none of these
83 * routines have any method of determining the size of the
84 * table. This comment isn't in the 1986-87 System V
85 * manual.
86 */
87 ++*nelp;
88 memcpy((void *)end, key, width);
89 return((void *)end);
90}
diff --git a/src/lib/libc/stdlib/malloc.3 b/src/lib/libc/stdlib/malloc.3
index 3bbf2bf65e..4e31ad4355 100644
--- a/src/lib/libc/stdlib/malloc.3
+++ b/src/lib/libc/stdlib/malloc.3
@@ -1,5 +1,6 @@
1.\" Copyright (c) 1980, 1991 Regents of the University of California. 1.\"
2.\" All rights reserved. 2.\" Copyright (c) 1980, 1991, 1993
3.\" The Regents of the University of California. All rights reserved.
3.\" 4.\"
4.\" This code is derived from software contributed to Berkeley by 5.\" This code is derived from software contributed to Berkeley by
5.\" the American National Standards Committee X3, on Information 6.\" the American National Standards Committee X3, on Information
@@ -33,19 +34,32 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 35.\" SUCH DAMAGE.
35.\" 36.\"
36.\" from: @(#)malloc.3 6.7 (Berkeley) 6/29/91 37.\" $OpenBSD: malloc.3,v 1.25 2003/01/21 19:59:09 jmc Exp $
37.\" $Id: malloc.3,v 1.1.1.1 1995/10/18 08:42:18 deraadt Exp $
38.\" 38.\"
39.Dd June 29, 1991 39.Dd August 27, 1996
40.Dt MALLOC 3 40.Dt MALLOC 3
41.Os BSD 4 41.Os
42.Sh NAME 42.Sh NAME
43.Nm malloc 43.Nm malloc ,
44.Nd general memory allocation function 44.Nm calloc ,
45.Nm realloc ,
46.Nm free ,
47.Nm cfree
48.Nd memory allocation and deallocation
45.Sh SYNOPSIS 49.Sh SYNOPSIS
46.Fd #include <stdlib.h> 50.Fd #include <stdlib.h>
47.Ft void * 51.Ft void *
48.Fn malloc "size_t size" 52.Fn malloc "size_t size"
53.Ft void *
54.Fn calloc "size_t nmemb" "size_t size"
55.Ft void *
56.Fn realloc "void *ptr" "size_t size"
57.Ft void
58.Fn free "void *ptr"
59.Ft void
60.Fn cfree "void *ptr"
61.Ft char *
62.Va malloc_options
49.Sh DESCRIPTION 63.Sh DESCRIPTION
50The 64The
51.Fn malloc 65.Fn malloc
@@ -59,33 +73,347 @@ space from the appropriate list.
59.Pp 73.Pp
60The allocated space is 74The allocated space is
61suitably aligned (after possible pointer 75suitably aligned (after possible pointer
62coercion) for storage of any type of object. If the space is of 76coercion) for storage of any type of object.
77If the space is of
63.Em pagesize 78.Em pagesize
64or larger, the memory returned will be page-aligned. 79or larger, the memory returned will be page-aligned.
80.Pp
81Allocation of a zero size object returns a pointer to a zero size object.
82This zero size object is access protected, so any access to it will
83generate an exception (SIGSEGV).
84Many zero-sized objects can be placed consecutively in shared
85protected pages.
86The minimum size of the protection on each object is suitably aligned and
87sized as previously stated, but the protection may extend further depending
88on where in a protected zone the object lands.
89.Pp
90The
91.Fn calloc
92function allocates space for an array of
93.Fa nmemb
94objects, each of whose size is
95.Fa size .
96The space is initialized to all bits zero.
97.Pp
98The
99.Fn free
100function causes the space pointed to by
101.Fa ptr
102to be deallocated, that is, at least made available for further allocation,
103but if possible, it will passed back to the kernel with
104.Xr sbrk 2 .
105If
106.Fa ptr
107is a null pointer, no action occurs.
108.Pp
109A
110.Fn cfree
111function is also provided for compatibility with old systems and other
112.Nm malloc
113libraries; it is simply an alias for
114.Fn free .
115.Pp
116The
117.Fn realloc
118function changes the size of the object pointed to by
119.Fa ptr
120to
121.Fa size
122bytes and returns a pointer to the (possibly moved) object.
123The contents of the object are unchanged up to the lesser
124of the new and old sizes.
125If the new size is larger, the value of the newly allocated portion
126of the object is indeterminate and uninitialized.
127If
128.Fa ptr
129is a null pointer, the
130.Fn realloc
131function behaves like the
132.Fn malloc
133function for the specified size.
134If the space cannot be allocated, the object
135pointed to by
136.Fa ptr
137is unchanged.
138If
139.Fa size
140is zero and
141.Fa ptr
142is not a null pointer, the object it points to is freed and a new zero size
143object is returned.
144.Pp
145When using
146.Fn realloc
147one must be careful to avoid the following idiom:
148.Pp
149.Bd -literal -offset indent
150if ((p = realloc(p, nsize)) == NULL)
151 return NULL;
152.Ed
153.Pp
154In most cases, this will result in a leak of memory.
155As stated earlier, a return value of
156.Dv NULL
157indicates that the old object still remains allocated.
158Better code looks like this:
159.Bd -literal -offset indent
160if ((p2 = realloc(p, nsize)) == NULL) {
161 if (p)
162 free(p);
163 p = NULL;
164 return NULL;
165}
166p = p2;
167.Ed
168.Pp
169Malloc will first look for a symbolic link called
170.Pa /etc/malloc.conf
171and next check the environment for a variable called
172.Ev MALLOC_OPTIONS
173and finally for the global variable
174.Va malloc_options
175and scan them for flags in that order.
176Flags are single letters, uppercase means on, lowercase means off.
177.Bl -tag -width indent
178.It Cm A
179.Dq Abort .
180.Fn malloc
181will coredump the process, rather than tolerate failure.
182This is a very handy debugging aid, since the core file will represent the
183time of failure, rather than when the null pointer was accessed.
184.Pp
185.It Cm D
186.Dq Dump .
187.Fn malloc
188will dump statistics in a file called
189.Pa malloc.out
190at exit.
191This option requires the library to have been compiled with -DMALLOC_STATS in
192order to have any effect.
193.Pp
194.It Cm J
195.Dq Junk .
196Fill some junk into the area allocated.
197Currently junk is bytes of 0xd0; this is pronounced
198.Dq Duh .
199\&:-)
200.Pp
201.It Cm H
202.Dq Hint .
203Pass a hint to the kernel about pages we don't use.
204If the machine is paging a lot this may help a bit.
205.Pp
206.It Cm N
207Do not output warning messages when encountering possible corruption
208or bad pointers.
209.Pp
210.It Cm R
211.Dq realloc .
212Always reallocate when
213.Fn realloc
214is called, even if the initial allocation was big enough.
215This can substantially aid in compacting memory.
216.\".Pp
217.\".It Cm U
218.\".Dq utrace .
219.\"Generate entries for
220.\".Xr ktrace 1
221.\"for all operations.
222.\"Consult the source for this one.
223.Pp
224.It Cm X
225.Dq xmalloc .
226Rather than return failure,
227.Xr abort 3
228the program with a diagnostic message on stderr.
229It is the intention that this option be set at compile time by
230including in the source:
231.Bd -literal -offset indent
232extern char *malloc_options;
233malloc_options = "X";
234.Ed
235.Pp
236.It Cm Z
237.Dq Zero .
238Fill some junk into the area allocated (see
239.Cm J ) ,
240except for the exact length the user asked for, which is zeroed.
241.Pp
242.It Cm <
243.Dq Half the cache size .
244Reduce the size of the cache by a factor of two.
245.Pp
246.It Cm >
247.Dq Double the cache size .
248Double the size of the cache by a factor of two.
249.El
250.Pp
251So to set a systemwide reduction of cache size and coredumps on problems
252one would:
253.Li ln -s 'A<' /etc/malloc.conf
254.Pp
255The
256.Cm J
257and
258.Cm Z
259flags are mostly for testing and debugging.
260If a program changes behavior if either of these options are used,
261it is buggy.
262.Pp
263The default cache size is 16 pages.
264.Sh ENVIRONMENT
265See above.
65.Sh RETURN VALUES 266.Sh RETURN VALUES
66The 267The
67.Fn malloc 268.Fn malloc
68function returns 269and
69a pointer to the allocated space if successful; otherwise 270.Fn calloc
70a null pointer is returned. 271functions return a pointer to the allocated space if successful; otherwise,
272a null pointer is returned and
273.Va errno
274is set to
275.Er ENOMEM .
276.Pp
277The
278.Fn free
279and
280.Fn cfree
281functions return no value.
282.Pp
283The
284.Fn realloc
285function returns a pointer to the (possibly moved) allocated space
286if successful; otherwise, a null pointer is returned and
287.Va errno
288is set to
289.Er ENOMEM .
290.Sh DIAGNOSTICS
291If
292.Fn malloc ,
293.Fn calloc ,
294.Fn realloc ,
295or
296.Fn free
297detect an error or warning condition,
298a message will be printed to file descriptor
2992 (not using stdio).
300Errors will always result in the process being
301.Xr abort 3 'ed.
302If the
303.Cm A
304option has been specified, warnings will also
305.Xr abort 3
306the process.
307.Pp
308Here is a brief description of the error messages and what they mean:
309.Bl -tag -width Fl
310.It Dq (ES): mumble mumble mumble
311.Fn malloc
312has been compiled with
313.Dv \&-DEXTRA_SANITY
314and something looks fishy in there.
315Consult sources and/or wizards.
316.It Dq allocation failed
317If the
318.Cm A
319option is specified it is an error for
320.Fn malloc ,
321.Fn calloc ,
322or
323.Fn realloc
324to return
325.Dv NULL .
326.It Dq mmap(2) failed, check limits.
327This is a rather weird condition that is most likely to indicate a
328seriously overloaded system or a
329.Xr ulimit 1
330restriction.
331.It Dq freelist is destroyed.
332.Fn malloc Ns 's
333internal freelist has been stomped on.
334.El
335.Pp
336Here is a brief description of the warning messages and what they mean:
337.Bl -tag -width Fl
338.It Dq chunk/page is already free.
339A pointer to a free chunk is attempted freed again.
340.It Dq junk pointer, too high to make sense.
341The pointer doesn't make sense.
342It's above the area of memory that
343.Fn malloc
344knows something about.
345This could be a pointer from some
346.Xr mmap 2 'ed
347memory.
348.It Dq junk pointer, too low to make sense.
349The pointer doesn't make sense.
350It's below the area of memory that
351.Fn malloc
352knows something about.
353This pointer probably came from your data or bss segments.
354.It Dq malloc() has never been called.
355Nothing has ever been allocated, yet something is being freed or
356realloc'ed.
357.It Dq modified (chunk-/page-) pointer.
358The pointer passed to free or realloc has been modified.
359.It Dq pointer to wrong page.
360The pointer that
361.Fn malloc
362is trying to free is not pointing to
363a sensible page.
364.It Dq recursive call.
365An attempt was made to call recursively into these functions, i.e., from a
366signal handler.
367This behavior is not supported.
368In particular, signal handlers should
369.Em not
370use any of the
371.Fn malloc
372functions nor utilize any other functions which may call
373.Fn malloc
374(e.g.,
375.Xr stdio 3
376routines).
377.It Dq unknown char in MALLOC_OPTIONS
378We found something we didn't understand.
379.El
380.Sh FILES
381.Bl -tag -width "/etc/malloc.conf"
382.It Pa /etc/malloc.conf
383symbolic link to filename containing option flags
384.El
71.Sh SEE ALSO 385.Sh SEE ALSO
72.Xr brk 2 , 386.Xr brk 2 ,
73.Xr getpagesize 2 ,
74.Xr free 3 ,
75.Xr calloc 3 ,
76.Xr alloca 3 , 387.Xr alloca 3 ,
77.Xr realloc 3 , 388.Xr getpagesize 3 ,
78.Xr memory 3 389.Xr memory 3
390.Pa /usr/share/doc/papers/malloc.ascii.gz
79.Sh STANDARDS 391.Sh STANDARDS
80The 392The
81.Fn malloc 393.Fn malloc
82function conforms to 394function conforms to
83.St -ansiC . 395.St -ansiC .
84.Sh BUGS 396.Sh HISTORY
85The current implementation of 397The present implementation of
86.Xr malloc 398.Fn malloc
87does not always fail gracefully when system 399started out as a filesystem on a drum
88memory limits are approached. 400attached to a 20-bit binary challenged computer built with discrete germanium
89It may fail to allocate memory when larger free blocks could be broken 401transistors, and it has since graduated to handle primary storage rather than
90up, or when limits are exceeded because the size is rounded up. 402secondary.
91It is optimized for sizes that are powers of two. 403.Pp
404The main difference from other
405.Fn malloc
406implementations are believed to be that
407the free pages are not accessed until allocated.
408Most
409.Fn malloc
410implementations will store a data structure containing a,
411possibly double-, linked list in the free chunks of memory, used to tie
412all the free memory together.
413That is a quite suboptimal thing to do.
414Every time the free-list is traversed, all the otherwise unused, and very
415likely paged out, pages get faulted into primary memory, just to see what
416lies after them in the list.
417.Pp
418On systems which are paging, this can make a factor five in difference on the
419page-faults of a process.
diff --git a/src/lib/libc/stdlib/malloc.c b/src/lib/libc/stdlib/malloc.c
index 3c57fad024..c8aef635d4 100644
--- a/src/lib/libc/stdlib/malloc.c
+++ b/src/lib/libc/stdlib/malloc.c
@@ -1,421 +1,1287 @@
1/* 1/*
2 * Copyright (c) 1983 Regents of the University of California. 2 * ----------------------------------------------------------------------------
3 * All rights reserved. 3 * "THE BEER-WARE LICENSE" (Revision 42):
4 * 4 * <phk@FreeBSD.ORG> wrote this file. As long as you retain this notice you
5 * Redistribution and use in source and binary forms, with or without 5 * can do whatever you want with this stuff. If we meet some day, and you think
6 * modification, are permitted provided that the following conditions 6 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
7 * are met: 7 * ----------------------------------------------------------------------------
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */ 8 */
33 9
34#if defined(LIBC_SCCS) && !defined(lint) 10#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)malloc.c 5.11 (Berkeley) 2/23/91";*/ 11static char rcsid[] = "$OpenBSD: malloc.c,v 1.54 2003/01/14 02:27:16 millert Exp $";
36static char *rcsid = "$Id: malloc.c,v 1.1.1.1 1995/10/18 08:42:18 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 12#endif /* LIBC_SCCS and not lint */
38 13
39/* 14/*
40 * malloc.c (Caltech) 2/21/82 15 * Defining MALLOC_EXTRA_SANITY will enable extra checks which are
41 * Chris Kingsley, kingsley@cit-20. 16 * related to internal conditions and consistency in malloc.c. This has
42 * 17 * a noticeable runtime performance hit, and generally will not do you
43 * This is a very fast storage allocator. It allocates blocks of a small 18 * any good unless you fiddle with the internals of malloc or want
44 * number of different sizes, and keeps free lists of each size. Blocks that 19 * to catch random pointer corruption as early as possible.
45 * don't exactly fit are passed up to the next larger size. In this 20 */
46 * implementation, the available sizes are 2^n-4 (or 2^n-10) bytes long. 21#ifndef MALLOC_EXTRA_SANITY
47 * This is designed for use in a virtual memory environment. 22#undef MALLOC_EXTRA_SANITY
23#endif
24
25/*
26 * Defining MALLOC_STATS will enable you to call malloc_dump() and set
27 * the [dD] options in the MALLOC_OPTIONS environment variable.
28 * It has no run-time performance hit, but does pull in stdio...
29 */
30#ifndef MALLOC_STATS
31#undef MALLOC_STATS
32#endif
33
34/*
35 * What to use for Junk. This is the byte value we use to fill with
36 * when the 'J' option is enabled.
48 */ 37 */
38#define SOME_JUNK 0xd0 /* as in "Duh" :-) */
49 39
50#include <sys/types.h> 40#include <sys/types.h>
41#include <sys/param.h>
42#include <sys/mman.h>
43#include <sys/uio.h>
44#include <stdio.h>
51#include <stdlib.h> 45#include <stdlib.h>
52#include <string.h> 46#include <string.h>
53#include <unistd.h> 47#include <unistd.h>
48#include <fcntl.h>
49#include <limits.h>
50#include <errno.h>
51
52#include "thread_private.h"
54 53
55#define NULL 0 54/*
55 * The basic parameters you can tweak.
56 *
57 * malloc_pageshift pagesize = 1 << malloc_pageshift
58 * It's probably best if this is the native
59 * page size, but it shouldn't have to be.
60 *
61 * malloc_minsize minimum size of an allocation in bytes.
62 * If this is too small it's too much work
63 * to manage them. This is also the smallest
64 * unit of alignment used for the storage
65 * returned by malloc/realloc.
66 *
67 */
56 68
57static void morecore(); 69#if defined(__OpenBSD__) && defined(__sparc__)
58static int findbucket(); 70# define malloc_pageshift 13U
71#endif /* __OpenBSD__ */
59 72
60/* 73/*
61 * The overhead on a block is at least 4 bytes. When free, this space 74 * No user serviceable parts behind this point.
62 * contains a pointer to the next free block, and the bottom two bits must 75 *
63 * be zero. When in use, the first byte is set to MAGIC, and the second 76 * This structure describes a page worth of chunks.
64 * byte is the size index. The remaining bytes are for alignment.
65 * If range checking is enabled then a second word holds the size of the
66 * requested block, less 1, rounded up to a multiple of sizeof(RMAGIC).
67 * The order of elements is critical: ov_magic must overlay the low order
68 * bits of ov_next, and ov_magic can not be a valid ov_next bit pattern.
69 */ 77 */
70union overhead { 78
71 union overhead *ov_next; /* when free */ 79struct pginfo {
72 struct { 80 struct pginfo *next; /* next on the free list */
73 u_char ovu_magic; /* magic number */ 81 void *page; /* Pointer to the page */
74 u_char ovu_index; /* bucket # */ 82 u_short size; /* size of this page's chunks */
75#ifdef RCHECK 83 u_short shift; /* How far to shift for this size chunks */
76 u_short ovu_rmagic; /* range magic number */ 84 u_short free; /* How many free chunks */
77 u_long ovu_size; /* actual block size */ 85 u_short total; /* How many chunk */
78#endif 86 u_long bits[1]; /* Which chunks are free */
79 } ovu;
80#define ov_magic ovu.ovu_magic
81#define ov_index ovu.ovu_index
82#define ov_rmagic ovu.ovu_rmagic
83#define ov_size ovu.ovu_size
84}; 87};
85 88
86#define MAGIC 0xef /* magic # on accounting info */ 89/*
87#define RMAGIC 0x5555 /* magic # on range info */ 90 * This structure describes a number of free pages.
91 */
92
93struct pgfree {
94 struct pgfree *next; /* next run of free pages */
95 struct pgfree *prev; /* prev run of free pages */
96 void *page; /* pointer to free pages */
97 void *end; /* pointer to end of free pages */
98 u_long size; /* number of bytes free */
99};
88 100
89#ifdef RCHECK 101/*
90#define RSLOP sizeof (u_short) 102 * How many bits per u_long in the bitmap.
103 * Change only if not 8 bits/byte
104 */
105#define MALLOC_BITS (8*sizeof(u_long))
106
107/*
108 * Magic values to put in the page_directory
109 */
110#define MALLOC_NOT_MINE ((struct pginfo*) 0)
111#define MALLOC_FREE ((struct pginfo*) 1)
112#define MALLOC_FIRST ((struct pginfo*) 2)
113#define MALLOC_FOLLOW ((struct pginfo*) 3)
114#define MALLOC_MAGIC ((struct pginfo*) 4)
115
116#ifndef malloc_pageshift
117#define malloc_pageshift (PGSHIFT)
118#endif
119
120#ifndef malloc_minsize
121#define malloc_minsize 16U
122#endif
123
124#ifndef malloc_pageshift
125#error "malloc_pageshift undefined"
126#endif
127
128#if !defined(malloc_pagesize)
129#define malloc_pagesize (1UL<<malloc_pageshift)
130#endif
131
132#if ((1UL<<malloc_pageshift) != malloc_pagesize)
133#error "(1UL<<malloc_pageshift) != malloc_pagesize"
134#endif
135
136#ifndef malloc_maxsize
137#define malloc_maxsize ((malloc_pagesize)>>1)
138#endif
139
140/* A mask for the offset inside a page. */
141#define malloc_pagemask ((malloc_pagesize)-1)
142
143#define pageround(foo) (((foo) + (malloc_pagemask))&(~(malloc_pagemask)))
144#define ptr2index(foo) (((u_long)(foo) >> malloc_pageshift)-malloc_origo)
145
146/* fd of /dev/zero */
147#ifdef USE_DEV_ZERO
148static int fdzero;
149#define MMAP_FD fdzero
150#define INIT_MMAP() \
151 { if ((fdzero=open("/dev/zero", O_RDWR, 0000)) == -1) \
152 wrterror("open of /dev/zero"); }
91#else 153#else
92#define RSLOP 0 154#define MMAP_FD (-1)
155#define INIT_MMAP()
93#endif 156#endif
94 157
158/* Set when initialization has been done */
159static unsigned int malloc_started;
160
161/* Number of free pages we cache */
162static unsigned int malloc_cache = 16;
163
164/* The offset from pagenumber to index into the page directory */
165static u_long malloc_origo;
166
167/* The last index in the page directory we care about */
168static u_long last_index;
169
170/* Pointer to page directory. Allocated "as if with" malloc */
171static struct pginfo **page_dir;
172
173/* How many slots in the page directory */
174static size_t malloc_ninfo;
175
176/* Free pages line up here */
177static struct pgfree free_list;
178
179/* Abort(), user doesn't handle problems. */
180static int malloc_abort;
181
182/* Are we trying to die ? */
183static int suicide;
184
185#ifdef MALLOC_STATS
186/* dump statistics */
187static int malloc_stats;
188#endif
189
190/* avoid outputting warnings? */
191static int malloc_silent;
192
193/* always realloc ? */
194static int malloc_realloc;
195
196#if defined(__FreeBSD__) || (defined(__OpenBSD__) && defined(MADV_FREE))
197/* pass the kernel a hint on free pages ? */
198static int malloc_hint;
199#endif
200
201/* xmalloc behaviour ? */
202static int malloc_xmalloc;
203
204/* zero fill ? */
205static int malloc_zero;
206
207/* junk fill ? */
208static int malloc_junk;
209
210#ifdef __FreeBSD__
211/* utrace ? */
212static int malloc_utrace;
213
214struct ut { void *p; size_t s; void *r; };
215
216void utrace(struct ut *, int);
217
218#define UTRACE(a, b, c) \
219 if (malloc_utrace) \
220 {struct ut u; u.p=a; u.s = b; u.r=c; utrace(&u, sizeof u);}
221#else /* !__FreeBSD__ */
222#define UTRACE(a,b,c)
223#endif
224
225/* my last break. */
226static void *malloc_brk;
227
228/* one location cache for free-list holders */
229static struct pgfree *px;
230
231/* compile-time options */
232char *malloc_options;
233
234/* Name of the current public function */
235static char *malloc_func;
236
237/* Macro for mmap */
238#define MMAP(size) \
239 mmap((void *)0, (size), PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, \
240 MMAP_FD, (off_t)0);
241
95/* 242/*
96 * nextf[i] is the pointer to the next free block of size 2^(i+3). The 243 * Necessary function declarations
97 * smallest allocatable block is 8 bytes. The overhead information
98 * precedes the data area returned to the user.
99 */ 244 */
100#define NBUCKETS 30 245static int extend_pgdir(u_long index);
101static union overhead *nextf[NBUCKETS]; 246static void *imalloc(size_t size);
102extern char *sbrk(); 247static void ifree(void *ptr);
248static void *irealloc(void *ptr, size_t size);
249static void *malloc_bytes(size_t size);
250
251#ifdef MALLOC_STATS
252void
253malloc_dump(fd)
254 FILE *fd;
255{
256 struct pginfo **pd;
257 struct pgfree *pf;
258 int j;
259
260 pd = page_dir;
261
262 /* print out all the pages */
263 for(j=0;j<=last_index;j++) {
264 fprintf(fd, "%08lx %5d ", (j+malloc_origo) << malloc_pageshift, j);
265 if (pd[j] == MALLOC_NOT_MINE) {
266 for(j++;j<=last_index && pd[j] == MALLOC_NOT_MINE;j++)
267 ;
268 j--;
269 fprintf(fd, ".. %5d not mine\n", j);
270 } else if (pd[j] == MALLOC_FREE) {
271 for(j++;j<=last_index && pd[j] == MALLOC_FREE;j++)
272 ;
273 j--;
274 fprintf(fd, ".. %5d free\n", j);
275 } else if (pd[j] == MALLOC_FIRST) {
276 for(j++;j<=last_index && pd[j] == MALLOC_FOLLOW;j++)
277 ;
278 j--;
279 fprintf(fd, ".. %5d in use\n", j);
280 } else if (pd[j] < MALLOC_MAGIC) {
281 fprintf(fd, "(%p)\n", pd[j]);
282 } else {
283 fprintf(fd, "%p %d (of %d) x %d @ %p --> %p\n",
284 pd[j], pd[j]->free, pd[j]->total,
285 pd[j]->size, pd[j]->page, pd[j]->next);
286 }
287 }
288
289 for(pf=free_list.next; pf; pf=pf->next) {
290 fprintf(fd, "Free: @%p [%p...%p[ %ld ->%p <-%p\n",
291 pf, pf->page, pf->end, pf->size, pf->prev, pf->next);
292 if (pf == pf->next) {
293 fprintf(fd, "Free_list loops.\n");
294 break;
295 }
296 }
297
298 /* print out various info */
299 fprintf(fd, "Minsize\t%d\n", malloc_minsize);
300 fprintf(fd, "Maxsize\t%d\n", malloc_maxsize);
301 fprintf(fd, "Pagesize\t%lu\n", (u_long)malloc_pagesize);
302 fprintf(fd, "Pageshift\t%d\n", malloc_pageshift);
303 fprintf(fd, "FirstPage\t%ld\n", malloc_origo);
304 fprintf(fd, "LastPage\t%ld %lx\n", last_index+malloc_pageshift,
305 (last_index + malloc_pageshift) << malloc_pageshift);
306 fprintf(fd, "Break\t%ld\n", (u_long)sbrk(0) >> malloc_pageshift);
307}
308#endif /* MALLOC_STATS */
309
310extern char *__progname;
311
312static void
313wrterror(p)
314 char *p;
315{
316 char *q = " error: ";
317 struct iovec iov[4];
318
319 iov[0].iov_base = __progname;
320 iov[0].iov_len = strlen(__progname);
321 iov[1].iov_base = malloc_func;
322 iov[1].iov_len = strlen(malloc_func);
323 iov[2].iov_base = q;
324 iov[2].iov_len = strlen(q);
325 iov[3].iov_base = p;
326 iov[3].iov_len = strlen(p);
327 writev(STDERR_FILENO, iov, 4);
328
329 suicide = 1;
330#ifdef MALLOC_STATS
331 if (malloc_stats)
332 malloc_dump(stderr);
333#endif /* MALLOC_STATS */
334 abort();
335}
336
337static void
338wrtwarning(p)
339 char *p;
340{
341 char *q = " warning: ";
342 struct iovec iov[4];
343
344 if (malloc_abort)
345 wrterror(p);
346 else if (malloc_silent)
347 return;
348
349 iov[0].iov_base = __progname;
350 iov[0].iov_len = strlen(__progname);
351 iov[1].iov_base = malloc_func;
352 iov[1].iov_len = strlen(malloc_func);
353 iov[2].iov_base = q;
354 iov[2].iov_len = strlen(q);
355 iov[3].iov_base = p;
356 iov[3].iov_len = strlen(p);
357 writev(STDERR_FILENO, iov, 4);
358}
359
360#ifdef MALLOC_STATS
361static void
362malloc_exit()
363{
364 FILE *fd = fopen("malloc.out", "a");
365 char *q = "malloc() warning: Couldn't dump stats.\n";
366 if (fd) {
367 malloc_dump(fd);
368 fclose(fd);
369 } else
370 write(STDERR_FILENO, q, strlen(q));
371}
372#endif /* MALLOC_STATS */
103 373
104static int pagesz; /* page size */
105static int pagebucket; /* page size bucket */
106 374
107#ifdef MSTATS
108/* 375/*
109 * nmalloc[i] is the difference between the number of mallocs and frees 376 * Allocate a number of pages from the OS
110 * for a given block size.
111 */ 377 */
112static u_int nmalloc[NBUCKETS]; 378static void *
113#include <stdio.h> 379map_pages(pages)
114#endif 380 size_t pages;
381{
382 caddr_t result, tail;
115 383
116#if defined(DEBUG) || defined(RCHECK) 384 result = (caddr_t)pageround((u_long)sbrk(0));
117#define ASSERT(p) if (!(p)) botch("p") 385 pages <<= malloc_pageshift;
118#include <stdio.h> 386 if (pages > SIZE_T_MAX - (size_t)result) {
119static 387#ifdef MALLOC_EXTRA_SANITY
120botch(s) 388 wrterror("(ES): overflow in map_pages fails\n");
121 char *s; 389#endif /* MALLOC_EXTRA_SANITY */
390 return 0;
391 }
392 tail = result + pages;
393
394 if (brk(tail)) {
395#ifdef MALLOC_EXTRA_SANITY
396 wrterror("(ES): map_pages fails\n");
397#endif /* MALLOC_EXTRA_SANITY */
398 return 0;
399 }
400
401 last_index = ptr2index(tail) - 1;
402 malloc_brk = tail;
403
404 if ((last_index+1) >= malloc_ninfo && !extend_pgdir(last_index))
405 return 0;
406
407 return result;
408}
409
410/*
411 * Extend page directory
412 */
413static int
414extend_pgdir(index)
415 u_long index;
122{ 416{
123 fprintf(stderr, "\r\nassertion botched: %s\r\n", s); 417 struct pginfo **new, **old;
124 (void) fflush(stderr); /* just in case user buffered it */ 418 size_t i, oldlen;
125 abort(); 419
420 /* Make it this many pages */
421 i = index * sizeof *page_dir;
422 i /= malloc_pagesize;
423 i += 2;
424
425 /* remember the old mapping size */
426 oldlen = malloc_ninfo * sizeof *page_dir;
427
428 /*
429 * NOTE: we allocate new pages and copy the directory rather than tempt
430 * fate by trying to "grow" the region.. There is nothing to prevent
431 * us from accidently re-mapping space that's been allocated by our caller
432 * via dlopen() or other mmap().
433 *
434 * The copy problem is not too bad, as there is 4K of page index per
435 * 4MB of malloc arena.
436 *
437 * We can totally avoid the copy if we open a file descriptor to associate
438 * the anon mappings with. Then, when we remap the pages at the new
439 * address, the old pages will be "magically" remapped.. But this means
440 * keeping open a "secret" file descriptor.....
441 */
442
443 /* Get new pages */
444 new = (struct pginfo**) MMAP(i * malloc_pagesize);
445 if (new == MAP_FAILED)
446 return 0;
447
448 /* Copy the old stuff */
449 memcpy(new, page_dir,
450 malloc_ninfo * sizeof *page_dir);
451
452 /* register the new size */
453 malloc_ninfo = i * malloc_pagesize / sizeof *page_dir;
454
455 /* swap the pointers */
456 old = page_dir;
457 page_dir = new;
458
459 /* Now free the old stuff */
460 munmap(old, oldlen);
461 return 1;
126} 462}
127#else
128#define ASSERT(p)
129#endif
130 463
131void * 464/*
132malloc(nbytes) 465 * Initialize the world
133 size_t nbytes; 466 */
467static void
468malloc_init ()
134{ 469{
135 register union overhead *op; 470 char *p, b[64];
136 register long bucket, n; 471 int i, j;
137 register unsigned amt; 472 int save_errno = errno;
138 473
139 /* 474 _MALLOC_LOCK_INIT();
140 * First time malloc is called, setup page size and 475
141 * align break pointer so all data will be page aligned. 476 INIT_MMAP();
142 */ 477
143 if (pagesz == 0) { 478#ifdef MALLOC_EXTRA_SANITY
144 pagesz = n = getpagesize(); 479 malloc_junk = 1;
145 op = (union overhead *)sbrk(0); 480#endif /* MALLOC_EXTRA_SANITY */
146 n = n - sizeof (*op) - ((long)op & (n - 1)); 481
147 if (n < 0) 482 for (i = 0; i < 3; i++) {
148 n += pagesz; 483 if (i == 0) {
149 if (n) { 484 j = readlink("/etc/malloc.conf", b, sizeof b - 1);
150 if (sbrk(n) == (char *)-1) 485 if (j <= 0)
151 return (NULL); 486 continue;
152 } 487 b[j] = '\0';
153 bucket = 0; 488 p = b;
154 amt = 8; 489 } else if (i == 1) {
155 while (pagesz > amt) { 490 if (issetugid() == 0)
156 amt <<= 1; 491 p = getenv("MALLOC_OPTIONS");
157 bucket++; 492 else
158 } 493 continue;
159 pagebucket = bucket; 494 } else if (i == 2) {
160 } 495 p = malloc_options;
161 /*
162 * Convert amount of memory requested into closest block size
163 * stored in hash buckets which satisfies request.
164 * Account for space used per block for accounting.
165 */
166 if (nbytes <= (n = pagesz - sizeof (*op) - RSLOP)) {
167#ifndef RCHECK
168 amt = 8; /* size of first bucket */
169 bucket = 0;
170#else
171 amt = 16; /* size of first bucket */
172 bucket = 1;
173#endif
174 n = -((long)sizeof (*op) + RSLOP);
175 } else {
176 amt = pagesz;
177 bucket = pagebucket;
178 } 496 }
179 while (nbytes > amt + n) { 497 for (; p && *p; p++) {
180 amt <<= 1; 498 switch (*p) {
181 if (amt == 0) 499 case '>': malloc_cache <<= 1; break;
182 return (NULL); 500 case '<': malloc_cache >>= 1; break;
183 bucket++; 501 case 'a': malloc_abort = 0; break;
502 case 'A': malloc_abort = 1; break;
503#ifdef MALLOC_STATS
504 case 'd': malloc_stats = 0; break;
505 case 'D': malloc_stats = 1; break;
506#endif /* MALLOC_STATS */
507#if defined(__FreeBSD__) || (defined(__OpenBSD__) && defined(MADV_FREE))
508 case 'h': malloc_hint = 0; break;
509 case 'H': malloc_hint = 1; break;
510#endif /* __FreeBSD__ */
511 case 'r': malloc_realloc = 0; break;
512 case 'R': malloc_realloc = 1; break;
513 case 'j': malloc_junk = 0; break;
514 case 'J': malloc_junk = 1; break;
515 case 'n': malloc_silent = 0; break;
516 case 'N': malloc_silent = 1; break;
517#ifdef __FreeBSD__
518 case 'u': malloc_utrace = 0; break;
519 case 'U': malloc_utrace = 1; break;
520#endif /* __FreeBSD__ */
521 case 'x': malloc_xmalloc = 0; break;
522 case 'X': malloc_xmalloc = 1; break;
523 case 'z': malloc_zero = 0; break;
524 case 'Z': malloc_zero = 1; break;
525 default:
526 j = malloc_abort;
527 malloc_abort = 0;
528 wrtwarning("unknown char in MALLOC_OPTIONS\n");
529 malloc_abort = j;
530 break;
531 }
184 } 532 }
185 /* 533 }
186 * If nothing in hash bucket right now, 534
187 * request more memory from the system. 535 UTRACE(0, 0, 0);
188 */ 536
189 if ((op = nextf[bucket]) == NULL) { 537 /*
190 morecore(bucket); 538 * We want junk in the entire allocation, and zero only in the part
191 if ((op = nextf[bucket]) == NULL) 539 * the user asked for.
192 return (NULL); 540 */
541 if (malloc_zero)
542 malloc_junk=1;
543
544#ifdef MALLOC_STATS
545 if (malloc_stats && (atexit(malloc_exit) == -1))
546 wrtwarning("atexit(2) failed. Will not be able to dump malloc stats on exit.\n");
547#endif /* MALLOC_STATS */
548
549 /* Allocate one page for the page directory */
550 page_dir = (struct pginfo **) MMAP(malloc_pagesize);
551
552 if (page_dir == MAP_FAILED)
553 wrterror("mmap(2) failed, check limits.\n");
554
555 /*
556 * We need a maximum of malloc_pageshift buckets, steal these from the
557 * front of the page_directory;
558 */
559 malloc_origo = ((u_long)pageround((u_long)sbrk(0))) >> malloc_pageshift;
560 malloc_origo -= malloc_pageshift;
561
562 malloc_ninfo = malloc_pagesize / sizeof *page_dir;
563
564 /* Been here, done that */
565 malloc_started++;
566
567 /* Recalculate the cache size in bytes, and make sure it's nonzero */
568
569 if (!malloc_cache)
570 malloc_cache++;
571
572 malloc_cache <<= malloc_pageshift;
573
574 /*
575 * This is a nice hack from Kaleb Keithly (kaleb@x.org).
576 * We can sbrk(2) further back when we keep this on a low address.
577 */
578 px = (struct pgfree *) imalloc (sizeof *px);
579 errno = save_errno;
580}
581
582/*
583 * Allocate a number of complete pages
584 */
585static void *
586malloc_pages(size)
587 size_t size;
588{
589 void *p, *delay_free = 0;
590 int i;
591 struct pgfree *pf;
592 u_long index;
593
594 size = pageround(size);
595
596 p = 0;
597 /* Look for free pages before asking for more */
598 for(pf = free_list.next; pf; pf = pf->next) {
599
600#ifdef MALLOC_EXTRA_SANITY
601 if (pf->size & malloc_pagemask)
602 wrterror("(ES): junk length entry on free_list\n");
603 if (!pf->size)
604 wrterror("(ES): zero length entry on free_list\n");
605 if (pf->page == pf->end)
606 wrterror("(ES): zero entry on free_list\n");
607 if (pf->page > pf->end)
608 wrterror("(ES): sick entry on free_list\n");
609 if ((void*)pf->page >= (void*)sbrk(0))
610 wrterror("(ES): entry on free_list past brk\n");
611 if (page_dir[ptr2index(pf->page)] != MALLOC_FREE)
612 wrterror("(ES): non-free first page on free-list\n");
613 if (page_dir[ptr2index(pf->end)-1] != MALLOC_FREE)
614 wrterror("(ES): non-free last page on free-list\n");
615#endif /* MALLOC_EXTRA_SANITY */
616
617 if (pf->size < size)
618 continue;
619
620 if (pf->size == size) {
621 p = pf->page;
622 if (pf->next)
623 pf->next->prev = pf->prev;
624 pf->prev->next = pf->next;
625 delay_free = pf;
626 break;
193 } 627 }
194 /* remove from linked list */ 628
195 nextf[bucket] = op->ov_next; 629 p = pf->page;
196 op->ov_magic = MAGIC; 630 pf->page = (char *)pf->page + size;
197 op->ov_index = bucket; 631 pf->size -= size;
198#ifdef MSTATS 632 break;
199 nmalloc[bucket]++; 633 }
200#endif 634
201#ifdef RCHECK 635#ifdef MALLOC_EXTRA_SANITY
202 /* 636 if (p && page_dir[ptr2index(p)] != MALLOC_FREE)
203 * Record allocated size of block and 637 wrterror("(ES): allocated non-free page on free-list\n");
204 * bound space with magic numbers. 638#endif /* MALLOC_EXTRA_SANITY */
205 */ 639
206 op->ov_size = (nbytes + RSLOP - 1) & ~(RSLOP - 1); 640 size >>= malloc_pageshift;
207 op->ov_rmagic = RMAGIC; 641
208 *(u_short *)((caddr_t)(op + 1) + op->ov_size) = RMAGIC; 642 /* Map new pages */
209#endif 643 if (!p)
210 return ((char *)(op + 1)); 644 p = map_pages(size);
645
646 if (p) {
647
648 index = ptr2index(p);
649 page_dir[index] = MALLOC_FIRST;
650 for (i=1;i<size;i++)
651 page_dir[index+i] = MALLOC_FOLLOW;
652
653 if (malloc_junk)
654 memset(p, SOME_JUNK, size << malloc_pageshift);
655 }
656
657 if (delay_free) {
658 if (!px)
659 px = delay_free;
660 else
661 ifree(delay_free);
662 }
663
664 return p;
211} 665}
212 666
213/* 667/*
214 * Allocate more memory to the indicated bucket. 668 * Allocate a page of fragments
215 */ 669 */
216static void 670
217morecore(bucket) 671static __inline__ int
218 int bucket; 672malloc_make_chunks(bits)
673 int bits;
219{ 674{
220 register union overhead *op; 675 struct pginfo *bp;
221 register long sz; /* size of desired block */ 676 void *pp;
222 long amt; /* amount to allocate */ 677 int i, k, l;
223 int nblks; /* how many blocks we get */
224 678
225 /* 679 /* Allocate a new bucket */
226 * sbrk_size <= 0 only for big, FLUFFY, requests (about 680 pp = malloc_pages((size_t)malloc_pagesize);
227 * 2^30 bytes on a VAX, I think) or for a negative arg. 681 if (!pp)
228 */ 682 return 0;
229 sz = 1 << (bucket + 3); 683
230#ifdef DEBUG 684 /* Find length of admin structure */
231 ASSERT(sz > 0); 685 l = sizeof *bp - sizeof(u_long);
232#else 686 l += sizeof(u_long) *
233 if (sz <= 0) 687 (((malloc_pagesize >> bits)+MALLOC_BITS-1) / MALLOC_BITS);
234 return; 688
235#endif 689 /* Don't waste more than two chunks on this */
236 if (sz < pagesz) { 690 /*
237 amt = pagesz; 691 * If we are to allocate a memory protected page for the malloc(0)
238 nblks = amt / sz; 692 * case (when bits=0), it must be from a different page than the
239 } else { 693 * pginfo page.
240 amt = sz + pagesz; 694 * --> Treat it like the big chunk alloc, get a second data page.
241 nblks = 1; 695 */
696 if (bits != 0 && (1UL<<(bits)) <= l+l) {
697 bp = (struct pginfo *)pp;
698 } else {
699 bp = (struct pginfo *)imalloc(l);
700 if (!bp) {
701 ifree(pp);
702 return 0;
242 } 703 }
243 op = (union overhead *)sbrk(amt); 704 }
244 /* no more room! */ 705
245 if ((long)op == -1) 706 /* memory protect the page allocated in the malloc(0) case */
246 return; 707 if (bits == 0) {
247 /* 708
248 * Add new memory allocated to that on 709 bp->size = 0;
249 * free list for this hash bucket. 710 bp->shift = 1;
250 */ 711 i = malloc_minsize-1;
251 nextf[bucket] = op; 712 while (i >>= 1)
252 while (--nblks > 0) { 713 bp->shift++;
253 op->ov_next = (union overhead *)((caddr_t)op + sz); 714 bp->total = bp->free = malloc_pagesize >> bp->shift;
254 op = (union overhead *)((caddr_t)op + sz); 715 bp->page = pp;
255 } 716
717 k = mprotect(pp, malloc_pagesize, PROT_NONE);
718 if (k < 0) {
719 ifree(pp);
720 ifree(bp);
721 return 0;
722 }
723 } else {
724 bp->size = (1UL<<bits);
725 bp->shift = bits;
726 bp->total = bp->free = malloc_pagesize >> bits;
727 bp->page = pp;
728 }
729
730 /* set all valid bits in the bitmap */
731 k = bp->total;
732 i = 0;
733
734 /* Do a bunch at a time */
735 for(;k-i >= MALLOC_BITS; i += MALLOC_BITS)
736 bp->bits[i / MALLOC_BITS] = ~0UL;
737
738 for(; i < k; i++)
739 bp->bits[i/MALLOC_BITS] |= 1UL<<(i%MALLOC_BITS);
740
741 if (bp == bp->page) {
742 /* Mark the ones we stole for ourselves */
743 for(i=0;l > 0;i++) {
744 bp->bits[i/MALLOC_BITS] &= ~(1UL<<(i%MALLOC_BITS));
745 bp->free--;
746 bp->total--;
747 l -= (1 << bits);
748 }
749 }
750
751 /* MALLOC_LOCK */
752
753 page_dir[ptr2index(pp)] = bp;
754
755 bp->next = page_dir[bits];
756 page_dir[bits] = bp;
757
758 /* MALLOC_UNLOCK */
759
760 return 1;
256} 761}
257 762
258void 763/*
259free(cp) 764 * Allocate a fragment
260 void *cp; 765 */
261{ 766static void *
262 register long size; 767malloc_bytes(size)
263 register union overhead *op; 768 size_t size;
264 769{
265 if (cp == NULL) 770 int i,j;
266 return; 771 u_long u;
267 op = (union overhead *)((caddr_t)cp - sizeof (union overhead)); 772 struct pginfo *bp;
268#ifdef DEBUG 773 int k;
269 ASSERT(op->ov_magic == MAGIC); /* make sure it was in use */ 774 u_long *lp;
270#else 775
271 if (op->ov_magic != MAGIC) 776 /* Don't bother with anything less than this */
272 return; /* sanity */ 777 /* unless we have a malloc(0) requests */
273#endif 778 if (size != 0 && size < malloc_minsize)
274#ifdef RCHECK 779 size = malloc_minsize;
275 ASSERT(op->ov_rmagic == RMAGIC); 780
276 ASSERT(*(u_short *)((caddr_t)(op + 1) + op->ov_size) == RMAGIC); 781 /* Find the right bucket */
277#endif 782 if (size == 0)
278 size = op->ov_index; 783 j=0;
279 ASSERT(size < NBUCKETS); 784 else {
280 op->ov_next = nextf[size]; /* also clobbers ov_magic */ 785 j = 1;
281 nextf[size] = op; 786 i = size-1;
282#ifdef MSTATS 787 while (i >>= 1)
283 nmalloc[size]--; 788 j++;
284#endif 789 }
790
791 /* If it's empty, make a page more of that size chunks */
792 if (!page_dir[j] && !malloc_make_chunks(j))
793 return 0;
794
795 bp = page_dir[j];
796
797 /* Find first word of bitmap which isn't empty */
798 for (lp = bp->bits; !*lp; lp++)
799 ;
800
801 /* Find that bit, and tweak it */
802 u = 1;
803 k = 0;
804 while (!(*lp & u)) {
805 u += u;
806 k++;
807 }
808 *lp ^= u;
809
810 /* If there are no more free, remove from free-list */
811 if (!--bp->free) {
812 page_dir[j] = bp->next;
813 bp->next = 0;
814 }
815
816 /* Adjust to the real offset of that chunk */
817 k += (lp-bp->bits)*MALLOC_BITS;
818 k <<= bp->shift;
819
820 if (malloc_junk && bp->size != 0)
821 memset((char *)bp->page + k, SOME_JUNK, bp->size);
822
823 return (u_char *)bp->page + k;
285} 824}
286 825
287/* 826/*
288 * When a program attempts "storage compaction" as mentioned in the 827 * Allocate a piece of memory
289 * old malloc man page, it realloc's an already freed block. Usually
290 * this is the last block it freed; occasionally it might be farther
291 * back. We have to search all the free lists for the block in order
292 * to determine its bucket: 1st we make one pass thru the lists
293 * checking only the first block in each; if that fails we search
294 * ``realloc_srchlen'' blocks in each list for a match (the variable
295 * is extern so the caller can modify it). If that fails we just copy
296 * however many bytes was given to realloc() and hope it's not huge.
297 */ 828 */
298int realloc_srchlen = 4; /* 4 should be plenty, -1 =>'s whole list */ 829static void *
830imalloc(size)
831 size_t size;
832{
833 void *result;
299 834
300void * 835 if (!malloc_started)
301realloc(cp, nbytes) 836 malloc_init();
302 void *cp; 837
303 size_t nbytes; 838 if (suicide)
304{ 839 abort();
305 register u_long onb; 840
306 register long i; 841 if ((size + malloc_pagesize) < size) /* Check for overflow */
307 union overhead *op; 842 result = 0;
308 char *res; 843 else if (size <= malloc_maxsize)
309 int was_alloced = 0; 844 result = malloc_bytes(size);
310 845 else
311 if (cp == NULL) 846 result = malloc_pages(size);
312 return (malloc(nbytes)); 847
313 op = (union overhead *)((caddr_t)cp - sizeof (union overhead)); 848 if (malloc_abort && !result)
314 if (op->ov_magic == MAGIC) { 849 wrterror("allocation failed.\n");
315 was_alloced++; 850
316 i = op->ov_index; 851 if (malloc_zero && result)
317 } else { 852 memset(result, 0, size);
318 /* 853
319 * Already free, doing "compaction". 854 return result;
320 * 855}
321 * Search for the old block of memory on the 856
322 * free list. First, check the most common 857/*
323 * case (last element free'd), then (this failing) 858 * Change the size of an allocation.
324 * the last ``realloc_srchlen'' items free'd. 859 */
325 * If all lookups fail, then assume the size of 860static void *
326 * the memory block being realloc'd is the 861irealloc(ptr, size)
327 * largest possible (so that all "nbytes" of new 862 void *ptr;
328 * memory are copied into). Note that this could cause 863 size_t size;
329 * a memory fault if the old area was tiny, and the moon 864{
330 * is gibbous. However, that is very unlikely. 865 void *p;
331 */ 866 u_long osize, index;
332 if ((i = findbucket(op, 1)) < 0 && 867 struct pginfo **mp;
333 (i = findbucket(op, realloc_srchlen)) < 0) 868 int i;
334 i = NBUCKETS; 869
870 if (suicide)
871 abort();
872
873 if (!malloc_started) {
874 wrtwarning("malloc() has never been called.\n");
875 return 0;
876 }
877
878 index = ptr2index(ptr);
879
880 if (index < malloc_pageshift) {
881 wrtwarning("junk pointer, too low to make sense.\n");
882 return 0;
883 }
884
885 if (index > last_index) {
886 wrtwarning("junk pointer, too high to make sense.\n");
887 return 0;
888 }
889
890 mp = &page_dir[index];
891
892 if (*mp == MALLOC_FIRST) { /* Page allocation */
893
894 /* Check the pointer */
895 if ((u_long)ptr & malloc_pagemask) {
896 wrtwarning("modified (page-) pointer.\n");
897 return 0;
335 } 898 }
336 onb = 1 << (i + 3); 899
337 if (onb < pagesz) 900 /* Find the size in bytes */
338 onb -= sizeof (*op) + RSLOP; 901 for (osize = malloc_pagesize; *++mp == MALLOC_FOLLOW;)
339 else 902 osize += malloc_pagesize;
340 onb += pagesz - sizeof (*op) - RSLOP; 903
341 /* avoid the copy if same size block */ 904 if (!malloc_realloc && /* Unless we have to, */
342 if (was_alloced) { 905 size <= osize && /* .. or are too small, */
343 if (i) { 906 size > (osize - malloc_pagesize)) { /* .. or can free a page, */
344 i = 1 << (i + 2); 907 if (malloc_junk)
345 if (i < pagesz) 908 memset((char *)ptr + size, SOME_JUNK, osize-size);
346 i -= sizeof (*op) + RSLOP; 909 return ptr; /* ..don't do anything else. */
347 else 910 }
348 i += pagesz - sizeof (*op) - RSLOP; 911
349 } 912 } else if (*mp >= MALLOC_MAGIC) { /* Chunk allocation */
350 if (nbytes <= onb && nbytes > i) { 913
351#ifdef RCHECK 914 /* Check the pointer for sane values */
352 op->ov_size = (nbytes + RSLOP - 1) & ~(RSLOP - 1); 915 if ((u_long)ptr & ((1UL<<((*mp)->shift))-1)) {
353 *(u_short *)((caddr_t)(op + 1) + op->ov_size) = RMAGIC; 916 wrtwarning("modified (chunk-) pointer.\n");
354#endif 917 return 0;
355 return(cp); 918 }
356 } else 919
357 free(cp); 920 /* Find the chunk index in the page */
921 i = ((u_long)ptr & malloc_pagemask) >> (*mp)->shift;
922
923 /* Verify that it isn't a free chunk already */
924 if ((*mp)->bits[i/MALLOC_BITS] & (1UL<<(i%MALLOC_BITS))) {
925 wrtwarning("chunk is already free.\n");
926 return 0;
927 }
928
929 osize = (*mp)->size;
930
931 if (!malloc_realloc && /* Unless we have to, */
932 size <= osize && /* ..or are too small, */
933 (size > osize/2 || /* ..or could use a smaller size, */
934 osize == malloc_minsize)) { /* ..(if there is one) */
935 if (malloc_junk)
936 memset((char *)ptr + size, SOME_JUNK, osize-size);
937 return ptr; /* ..don't do anything else. */
938 }
939
940 } else {
941 wrtwarning("pointer to wrong page.\n");
942 return 0;
943 }
944
945 p = imalloc(size);
946
947 if (p) {
948 /* copy the lesser of the two sizes, and free the old one */
949 /* Don't move from/to 0 sized region !!! */
950 if (osize != 0 && size != 0) {
951 if (osize < size)
952 memcpy(p, ptr, osize);
953 else
954 memcpy(p, ptr, size);
358 } 955 }
359 if ((res = malloc(nbytes)) == NULL) 956 ifree(ptr);
360 return (NULL); 957 }
361 if (cp != res) /* common optimization if "compacting" */ 958 return p;
362 bcopy(cp, res, (nbytes < onb) ? nbytes : onb);
363 return (res);
364} 959}
365 960
366/* 961/*
367 * Search ``srchlen'' elements of each free list for a block whose 962 * Free a sequence of pages
368 * header starts at ``freep''. If srchlen is -1 search the whole list.
369 * Return bucket number, or -1 if not found.
370 */ 963 */
371static 964
372findbucket(freep, srchlen) 965static __inline__ void
373 union overhead *freep; 966free_pages(ptr, index, info)
374 int srchlen; 967 void *ptr;
968 int index;
969 struct pginfo *info;
375{ 970{
376 register union overhead *p; 971 int i;
377 register int i, j; 972 struct pgfree *pf, *pt=0;
378 973 u_long l;
379 for (i = 0; i < NBUCKETS; i++) { 974 void *tail;
380 j = 0; 975
381 for (p = nextf[i]; p && j != srchlen; p = p->ov_next) { 976 if (info == MALLOC_FREE) {
382 if (p == freep) 977 wrtwarning("page is already free.\n");
383 return (i); 978 return;
384 j++; 979 }
385 } 980
981 if (info != MALLOC_FIRST) {
982 wrtwarning("pointer to wrong page.\n");
983 return;
984 }
985
986 if ((u_long)ptr & malloc_pagemask) {
987 wrtwarning("modified (page-) pointer.\n");
988 return;
989 }
990
991 /* Count how many pages and mark them free at the same time */
992 page_dir[index] = MALLOC_FREE;
993 for (i = 1; page_dir[index+i] == MALLOC_FOLLOW; i++)
994 page_dir[index + i] = MALLOC_FREE;
995
996 l = i << malloc_pageshift;
997
998 if (malloc_junk)
999 memset(ptr, SOME_JUNK, l);
1000
1001#if defined(__FreeBSD__) || (defined(__OpenBSD__) && defined(MADV_FREE))
1002 if (malloc_hint)
1003 madvise(ptr, l, MADV_FREE);
1004#endif
1005
1006 tail = (char *)ptr+l;
1007
1008 /* add to free-list */
1009 if (!px)
1010 px = imalloc(sizeof *px); /* This cannot fail... */
1011 px->page = ptr;
1012 px->end = tail;
1013 px->size = l;
1014 if (!free_list.next) {
1015
1016 /* Nothing on free list, put this at head */
1017 px->next = free_list.next;
1018 px->prev = &free_list;
1019 free_list.next = px;
1020 pf = px;
1021 px = 0;
1022
1023 } else {
1024
1025 /* Find the right spot, leave pf pointing to the modified entry. */
1026 tail = (char *)ptr+l;
1027
1028 for(pf = free_list.next; pf->end < ptr && pf->next; pf = pf->next)
1029 ; /* Race ahead here */
1030
1031 if (pf->page > tail) {
1032 /* Insert before entry */
1033 px->next = pf;
1034 px->prev = pf->prev;
1035 pf->prev = px;
1036 px->prev->next = px;
1037 pf = px;
1038 px = 0;
1039 } else if (pf->end == ptr ) {
1040 /* Append to the previous entry */
1041 pf->end = (char *)pf->end + l;
1042 pf->size += l;
1043 if (pf->next && pf->end == pf->next->page ) {
1044 /* And collapse the next too. */
1045 pt = pf->next;
1046 pf->end = pt->end;
1047 pf->size += pt->size;
1048 pf->next = pt->next;
1049 if (pf->next)
1050 pf->next->prev = pf;
1051 }
1052 } else if (pf->page == tail) {
1053 /* Prepend to entry */
1054 pf->size += l;
1055 pf->page = ptr;
1056 } else if (!pf->next) {
1057 /* Append at tail of chain */
1058 px->next = 0;
1059 px->prev = pf;
1060 pf->next = px;
1061 pf = px;
1062 px = 0;
1063 } else {
1064 wrterror("freelist is destroyed.\n");
386 } 1065 }
387 return (-1); 1066 }
1067
1068 /* Return something to OS ? */
1069 if (!pf->next && /* If we're the last one, */
1070 pf->size > malloc_cache && /* ..and the cache is full, */
1071 pf->end == malloc_brk && /* ..and none behind us, */
1072 malloc_brk == sbrk(0)) { /* ..and it's OK to do... */
1073
1074 /*
1075 * Keep the cache intact. Notice that the '>' above guarantees that
1076 * the pf will always have at least one page afterwards.
1077 */
1078 pf->end = (char *)pf->page + malloc_cache;
1079 pf->size = malloc_cache;
1080
1081 brk(pf->end);
1082 malloc_brk = pf->end;
1083
1084 index = ptr2index(pf->end);
1085
1086 for(i=index;i <= last_index;)
1087 page_dir[i++] = MALLOC_NOT_MINE;
1088
1089 last_index = index - 1;
1090
1091 /* XXX: We could realloc/shrink the pagedir here I guess. */
1092 }
1093 if (pt)
1094 ifree(pt);
388} 1095}
389 1096
390#ifdef MSTATS
391/* 1097/*
392 * mstats - print out statistics about malloc 1098 * Free a chunk, and possibly the page it's on, if the page becomes empty.
393 *
394 * Prints two lines of numbers, one showing the length of the free list
395 * for each size category, the second showing the number of mallocs -
396 * frees for each size category.
397 */ 1099 */
398mstats(s) 1100
399 char *s; 1101/* ARGSUSED */
1102static __inline__ void
1103free_bytes(ptr, index, info)
1104 void *ptr;
1105 int index;
1106 struct pginfo *info;
400{ 1107{
401 register int i, j; 1108 int i;
402 register union overhead *p; 1109 struct pginfo **mp;
403 int totfree = 0, 1110 void *vp;
404 totused = 0; 1111
405 1112 /* Find the chunk number on the page */
406 fprintf(stderr, "Memory allocation statistics %s\nfree:\t", s); 1113 i = ((u_long)ptr & malloc_pagemask) >> info->shift;
407 for (i = 0; i < NBUCKETS; i++) { 1114
408 for (j = 0, p = nextf[i]; p; p = p->ov_next, j++) 1115 if ((u_long)ptr & ((1UL<<(info->shift))-1)) {
409 ; 1116 wrtwarning("modified (chunk-) pointer.\n");
410 fprintf(stderr, " %d", j); 1117 return;
411 totfree += j * (1 << (i + 3)); 1118 }
412 } 1119
413 fprintf(stderr, "\nused:\t"); 1120 if (info->bits[i/MALLOC_BITS] & (1UL<<(i%MALLOC_BITS))) {
414 for (i = 0; i < NBUCKETS; i++) { 1121 wrtwarning("chunk is already free.\n");
415 fprintf(stderr, " %d", nmalloc[i]); 1122 return;
416 totused += nmalloc[i] * (1 << (i + 3)); 1123 }
417 } 1124
418 fprintf(stderr, "\n\tTotal in use: %d, total free: %d\n", 1125 if (malloc_junk && info->size != 0)
419 totused, totfree); 1126 memset(ptr, SOME_JUNK, info->size);
1127
1128 info->bits[i/MALLOC_BITS] |= 1UL<<(i%MALLOC_BITS);
1129 info->free++;
1130
1131 if (info->size != 0)
1132 mp = page_dir + info->shift;
1133 else
1134 mp = page_dir;
1135
1136 if (info->free == 1) {
1137
1138 /* Page became non-full */
1139
1140 /* Insert in address order */
1141 while (*mp && (*mp)->next && (*mp)->next->page < info->page)
1142 mp = &(*mp)->next;
1143 info->next = *mp;
1144 *mp = info;
1145 return;
1146 }
1147
1148 if (info->free != info->total)
1149 return;
1150
1151 /* Find & remove this page in the queue */
1152 while (*mp != info) {
1153 mp = &((*mp)->next);
1154#ifdef MALLOC_EXTRA_SANITY
1155 if (!*mp)
1156 wrterror("(ES): Not on queue\n");
1157#endif /* MALLOC_EXTRA_SANITY */
1158 }
1159 *mp = info->next;
1160
1161 /* Free the page & the info structure if need be */
1162 page_dir[ptr2index(info->page)] = MALLOC_FIRST;
1163
1164 /* If the page was mprotected, unprotect it before releasing it */
1165 if (info->size == 0) {
1166 mprotect(info->page, malloc_pagesize, PROT_READ|PROT_WRITE);
1167 /* Do we have to care if mprotect succeeds here ? */
1168 }
1169
1170 vp = info->page; /* Order is important ! */
1171 if(vp != (void*)info)
1172 ifree(info);
1173 ifree(vp);
1174}
1175
1176static void
1177ifree(ptr)
1178 void *ptr;
1179{
1180 struct pginfo *info;
1181 int index;
1182
1183 /* This is legal */
1184 if (!ptr)
1185 return;
1186
1187 if (!malloc_started) {
1188 wrtwarning("malloc() has never been called.\n");
1189 return;
1190 }
1191
1192 /* If we're already sinking, don't make matters any worse. */
1193 if (suicide)
1194 return;
1195
1196 index = ptr2index(ptr);
1197
1198 if (index < malloc_pageshift) {
1199 wrtwarning("junk pointer, too low to make sense.\n");
1200 return;
1201 }
1202
1203 if (index > last_index) {
1204 wrtwarning("junk pointer, too high to make sense.\n");
1205 return;
1206 }
1207
1208 info = page_dir[index];
1209
1210 if (info < MALLOC_MAGIC)
1211 free_pages(ptr, index, info);
1212 else
1213 free_bytes(ptr, index, info);
1214 return;
1215}
1216
1217/*
1218 * These are the public exported interface routines.
1219 */
1220
1221static int malloc_active;
1222
1223void *
1224malloc(size_t size)
1225{
1226 register void *r;
1227
1228 malloc_func = " in malloc():";
1229 _MALLOC_LOCK();
1230 if (malloc_active++) {
1231 wrtwarning("recursive call.\n");
1232 malloc_active--;
1233 _MALLOC_UNLOCK();
1234 return (0);
1235 }
1236 r = imalloc(size);
1237 UTRACE(0, size, r);
1238 malloc_active--;
1239 _MALLOC_UNLOCK();
1240 if (malloc_xmalloc && !r)
1241 wrterror("out of memory.\n");
1242 return (r);
1243}
1244
1245void
1246free(void *ptr)
1247{
1248 malloc_func = " in free():";
1249 _MALLOC_LOCK();
1250 if (malloc_active++) {
1251 wrtwarning("recursive call.\n");
1252 malloc_active--;
1253 _MALLOC_UNLOCK();
1254 return;
1255 }
1256 ifree(ptr);
1257 UTRACE(ptr, 0, 0);
1258 malloc_active--;
1259 _MALLOC_UNLOCK();
1260 return;
1261}
1262
1263void *
1264realloc(void *ptr, size_t size)
1265{
1266 register void *r;
1267
1268 malloc_func = " in realloc():";
1269 _MALLOC_LOCK();
1270 if (malloc_active++) {
1271 wrtwarning("recursive call.\n");
1272 malloc_active--;
1273 _MALLOC_UNLOCK();
1274 return (0);
1275 }
1276 if (!ptr) {
1277 r = imalloc(size);
1278 } else {
1279 r = irealloc(ptr, size);
1280 }
1281 UTRACE(ptr, size, r);
1282 malloc_active--;
1283 _MALLOC_UNLOCK();
1284 if (malloc_xmalloc && !r)
1285 wrterror("out of memory.\n");
1286 return (r);
420} 1287}
421#endif
diff --git a/src/lib/libc/stdlib/memory.3 b/src/lib/libc/stdlib/memory.3
index 735252c837..959a173a03 100644
--- a/src/lib/libc/stdlib/memory.3
+++ b/src/lib/libc/stdlib/memory.3
@@ -29,12 +29,11 @@
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE. 30.\" SUCH DAMAGE.
31.\" 31.\"
32.\" from: @(#)memory.3 5.1 (Berkeley) 5/2/91 32.\" $OpenBSD: memory.3,v 1.5 2000/04/20 13:50:02 aaron Exp $
33.\" $Id: memory.3,v 1.1.1.1 1995/10/18 08:42:18 deraadt Exp $
34.\" 33.\"
35.Dd May 2, 1991 34.Dd May 2, 1991
36.Dt MEMORY 3 35.Dt MEMORY 3
37.Os BSD 4 36.Os
38.Sh NAME 37.Sh NAME
39.Nm malloc , 38.Nm malloc ,
40.Nm free , 39.Nm free ,
@@ -56,16 +55,15 @@
56.Fn alloca "size_t size" 55.Fn alloca "size_t size"
57.Sh DESCRIPTION 56.Sh DESCRIPTION
58These functions allocate and free memory for the calling process. 57These functions allocate and free memory for the calling process.
59They are described in the 58They are described in the individual man pages.
60individual manual pages.
61.Sh SEE ALSO 59.Sh SEE ALSO
60.Xr alloca 3 ,
62.Xr calloc 3 , 61.Xr calloc 3 ,
63.Xr free 3 , 62.Xr free 3 ,
64.Xr malloc 3 , 63.Xr malloc 3 ,
65.Xr realloc 3 , 64.Xr realloc 3
66.Xr alloca 3 ,
67.Sh STANDARDS 65.Sh STANDARDS
68These functions, with the exception of 66These functions, with the exception of
69.Fn alloca 67.Fn alloca ,
70conform to 68conform to
71.St -ansiC . 69.St -ansiC .
diff --git a/src/lib/libc/stdlib/merge.c b/src/lib/libc/stdlib/merge.c
index 381fdc0830..4ae6488af2 100644
--- a/src/lib/libc/stdlib/merge.c
+++ b/src/lib/libc/stdlib/merge.c
@@ -35,8 +35,7 @@
35 */ 35 */
36 36
37#if defined(LIBC_SCCS) && !defined(lint) 37#if defined(LIBC_SCCS) && !defined(lint)
38/*static char sccsid[] = "from: @(#)merge.c 8.2 (Berkeley) 2/14/94";*/ 38static char *rcsid = "$OpenBSD: merge.c,v 1.5 2002/02/17 19:42:24 millert Exp $";
39static char *rcsid = "$Id: merge.c,v 1.1.1.1 1995/10/18 08:42:18 deraadt Exp $";
40#endif /* LIBC_SCCS and not lint */ 39#endif /* LIBC_SCCS and not lint */
41 40
42/* 41/*
@@ -59,8 +58,8 @@ static char *rcsid = "$Id: merge.c,v 1.1.1.1 1995/10/18 08:42:18 deraadt Exp $";
59#include <stdlib.h> 58#include <stdlib.h>
60#include <string.h> 59#include <string.h>
61 60
62static void setup __P((u_char *, u_char *, size_t, size_t, int (*)())); 61static void setup(u_char *, u_char *, size_t, size_t, int (*)());
63static void insertionsort __P((u_char *, size_t, size_t, int (*)())); 62static void insertionsort(u_char *, size_t, size_t, int (*)());
64 63
65#define ISIZE sizeof(int) 64#define ISIZE sizeof(int)
66#define PSIZE sizeof(u_char *) 65#define PSIZE sizeof(u_char *)
@@ -100,7 +99,7 @@ mergesort(base, nmemb, size, cmp)
100 void *base; 99 void *base;
101 size_t nmemb; 100 size_t nmemb;
102 register size_t size; 101 register size_t size;
103 int (*cmp) __P((const void *, const void *)); 102 int (*cmp)(const void *, const void *);
104{ 103{
105 register int i, sense; 104 register int i, sense;
106 int big, iflag; 105 int big, iflag;
@@ -148,7 +147,7 @@ mergesort(base, nmemb, size, cmp)
148 sense = 0; 147 sense = 0;
149 } 148 }
150 if (!big) { /* here i = 0 */ 149 if (!big) { /* here i = 0 */
151LINEAR: while ((b += size) < t && cmp(q, b) >sense) 150 while ((b += size) < t && cmp(q, b) >sense)
152 if (++i == 6) { 151 if (++i == 6) {
153 big = 1; 152 big = 1;
154 goto EXPONENTIAL; 153 goto EXPONENTIAL;
@@ -169,7 +168,7 @@ EXPONENTIAL: for (i = size; ; i <<= 1)
169 goto FASTCASE; 168 goto FASTCASE;
170 } else 169 } else
171 b = p; 170 b = p;
172SLOWCASE: while (t > b+size) { 171 while (t > b+size) {
173 i = (((t - b) / size) >> 1) * size; 172 i = (((t - b) / size) >> 1) * size;
174 if ((*cmp)(q, p = b + i) <= sense) 173 if ((*cmp)(q, p = b + i) <= sense)
175 t = p; 174 t = p;
@@ -258,7 +257,7 @@ COPY: b = t;
258void 257void
259setup(list1, list2, n, size, cmp) 258setup(list1, list2, n, size, cmp)
260 size_t n, size; 259 size_t n, size;
261 int (*cmp) __P((const void *, const void *)); 260 int (*cmp)(const void *, const void *);
262 u_char *list1, *list2; 261 u_char *list1, *list2;
263{ 262{
264 int i, length, size2, tmp, sense; 263 int i, length, size2, tmp, sense;
@@ -333,7 +332,7 @@ static void
333insertionsort(a, n, size, cmp) 332insertionsort(a, n, size, cmp)
334 u_char *a; 333 u_char *a;
335 size_t n, size; 334 size_t n, size;
336 int (*cmp) __P((const void *, const void *)); 335 int (*cmp)(const void *, const void *);
337{ 336{
338 u_char *ai, *s, *t, *u, tmp; 337 u_char *ai, *s, *t, *u, tmp;
339 int i; 338 int i;
diff --git a/src/lib/libc/stdlib/mrand48.c b/src/lib/libc/stdlib/mrand48.c
index 43356e66b3..cd34260b5c 100644
--- a/src/lib/libc/stdlib/mrand48.c
+++ b/src/lib/libc/stdlib/mrand48.c
@@ -11,6 +11,10 @@
11 * to anyone/anything when using this software. 11 * to anyone/anything when using this software.
12 */ 12 */
13 13
14#if defined(LIBC_SCCS) && !defined(lint)
15static char rcsid[] = "$OpenBSD: mrand48.c,v 1.2 1996/08/19 08:33:39 tholo Exp $";
16#endif /* LIBC_SCCS and not lint */
17
14#include "rand48.h" 18#include "rand48.h"
15 19
16extern unsigned short __rand48_seed[3]; 20extern unsigned short __rand48_seed[3];
diff --git a/src/lib/libc/stdlib/multibyte.c b/src/lib/libc/stdlib/multibyte.c
index fe1cd5781b..6f08bbe342 100644
--- a/src/lib/libc/stdlib/multibyte.c
+++ b/src/lib/libc/stdlib/multibyte.c
@@ -32,8 +32,7 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)multibyte.c 5.1 (Berkeley) 2/18/91";*/ 35static char *rcsid = "$OpenBSD: multibyte.c,v 1.3 2002/02/19 19:39:37 millert Exp $";
36static char *rcsid = "$Id: multibyte.c,v 1.1.1.1 1995/10/18 08:42:18 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
38 37
39#include <stdlib.h> 38#include <stdlib.h>
@@ -74,13 +73,7 @@ mbtowc(pwc, s, n)
74 73
75/*ARGSUSED*/ 74/*ARGSUSED*/
76int 75int
77#ifdef __STDC__
78wctomb(char *s, wchar_t wchar) 76wctomb(char *s, wchar_t wchar)
79#else
80wctomb(s, wchar)
81 char *s;
82 wchar_t wchar;
83#endif
84{ 77{
85 if (s == NULL) 78 if (s == NULL)
86 return 0; 79 return 0;
diff --git a/src/lib/libc/stdlib/nrand48.c b/src/lib/libc/stdlib/nrand48.c
index 63f839cb05..b1ec2cebb1 100644
--- a/src/lib/libc/stdlib/nrand48.c
+++ b/src/lib/libc/stdlib/nrand48.c
@@ -11,6 +11,10 @@
11 * to anyone/anything when using this software. 11 * to anyone/anything when using this software.
12 */ 12 */
13 13
14#if defined(LIBC_SCCS) && !defined(lint)
15static char rcsid[] = "$OpenBSD: nrand48.c,v 1.2 1996/08/19 08:33:40 tholo Exp $";
16#endif /* LIBC_SCCS and not lint */
17
14#include "rand48.h" 18#include "rand48.h"
15 19
16long 20long
diff --git a/src/lib/libc/stdlib/putenv.c b/src/lib/libc/stdlib/putenv.c
index 2194c2c608..d8c4886d4b 100644
--- a/src/lib/libc/stdlib/putenv.c
+++ b/src/lib/libc/stdlib/putenv.c
@@ -1,6 +1,6 @@
1/*- 1/*-
2 * Copyright (c) 1988 The Regents of the University of California. 2 * Copyright (c) 1988, 1993
3 * All rights reserved. 3 * The Regents of the University of California. All rights reserved.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions 6 * modification, are permitted provided that the following conditions
@@ -32,8 +32,7 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)putenv.c 5.4 (Berkeley) 2/23/91";*/ 35static char *rcsid = "$OpenBSD: putenv.c,v 1.2 1996/08/10 05:03:00 tholo Exp $";
36static char *rcsid = "$Id: putenv.c,v 1.1.1.1 1995/10/18 08:42:18 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
38 37
39#include <stdlib.h> 38#include <stdlib.h>
@@ -43,17 +42,17 @@ int
43putenv(str) 42putenv(str)
44 const char *str; 43 const char *str;
45{ 44{
46 register char *p, *equal; 45 char *p, *equal;
47 int rval; 46 int rval;
48 47
49 if (!(p = strdup(str))) 48 if ((p = strdup(str)) == NULL)
50 return(1); 49 return (-1);
51 if (!(equal = strchr(p, '='))) { 50 if ((equal = strchr(p, '=')) == NULL) {
52 (void)free(p); 51 (void)free(p);
53 return(1); 52 return (-1);
54 } 53 }
55 *equal = '\0'; 54 *equal = '\0';
56 rval = setenv(p, equal + 1, 1); 55 rval = setenv(p, equal + 1, 1);
57 (void)free(p); 56 (void)free(p);
58 return(rval); 57 return (rval);
59} 58}
diff --git a/src/lib/libc/stdlib/qabs.3 b/src/lib/libc/stdlib/qabs.3
index cb1e052191..ef0307ab25 100644
--- a/src/lib/libc/stdlib/qabs.3
+++ b/src/lib/libc/stdlib/qabs.3
@@ -33,8 +33,7 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)labs.3 5.3 (Berkeley) 6/29/91 36.\" $OpenBSD: qabs.3,v 1.5 2000/04/20 13:50:02 aaron Exp $
37.\" $Id: qabs.3,v 1.1.1.1 1995/10/18 08:42:18 deraadt Exp $
38.\" 37.\"
39.Dd June 29, 1991 38.Dd June 29, 1991
40.Dt QABS 3 39.Dt QABS 3
@@ -49,14 +48,13 @@
49.Sh DESCRIPTION 48.Sh DESCRIPTION
50The 49The
51.Fn qabs 50.Fn qabs
52function 51function returns the absolute value of the quad integer
53returns the absolute value of the quad integer 52.Fa j .
54.Ar j .
55.Sh SEE ALSO 53.Sh SEE ALSO
56.Xr abs 3 , 54.Xr abs 3 ,
57.Xr labs 3 ,
58.Xr floor 3 ,
59.Xr cabs 3 , 55.Xr cabs 3 ,
56.Xr floor 3 ,
57.Xr labs 3 ,
60.Xr math 3 58.Xr math 3
61.Sh BUGS 59.Sh BUGS
62The absolute value of the most negative integer remains negative. 60The absolute value of the most negative integer remains negative.
diff --git a/src/lib/libc/stdlib/qabs.c b/src/lib/libc/stdlib/qabs.c
index 9c51a8baa9..ccc42cbec6 100644
--- a/src/lib/libc/stdlib/qabs.c
+++ b/src/lib/libc/stdlib/qabs.c
@@ -32,8 +32,7 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)labs.c 5.2 (Berkeley) 5/17/90";*/ 35static char *rcsid = "$OpenBSD: qabs.c,v 1.2 1996/08/19 08:33:40 tholo Exp $";
36static char *rcsid = "$Id: qabs.c,v 1.1.1.1 1995/10/18 08:42:18 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
38 37
39#include <stdlib.h> 38#include <stdlib.h>
diff --git a/src/lib/libc/stdlib/qdiv.3 b/src/lib/libc/stdlib/qdiv.3
index 0efcfc96ef..4db47d9b4a 100644
--- a/src/lib/libc/stdlib/qdiv.3
+++ b/src/lib/libc/stdlib/qdiv.3
@@ -33,8 +33,7 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)qdiv.3 5.3 (Berkeley) 6/29/91 36.\" $OpenBSD: qdiv.3,v 1.4 2000/12/24 00:31:00 aaron Exp $
37.\" $Id: qdiv.3,v 1.1.1.1 1995/10/18 08:42:18 deraadt Exp $
38.\" 37.\"
39.Dd June 29, 1991 38.Dd June 29, 1991
40.Dt QDIV 3 39.Dt QDIV 3
@@ -49,17 +48,16 @@
49.Sh DESCRIPTION 48.Sh DESCRIPTION
50The 49The
51.Fn qdiv 50.Fn qdiv
52function 51function computes the value
53computes the value 52.Fa num Ns No / Ns Fa denom
54.Ar num/denom
55and returns the quotient and remainder in a structure named 53and returns the quotient and remainder in a structure named
56.Ar qdiv_t 54.Li qdiv_t
57that contains two 55that contains two
58.Em quad integer 56.Li quad integer
59members named 57members named
60.Ar quot 58.Fa quot
61and 59and
62.Ar rem . 60.Fa rem .
63.Sh SEE ALSO 61.Sh SEE ALSO
64.Xr div 3 , 62.Xr div 3 ,
65.Xr ldiv 3 , 63.Xr ldiv 3 ,
diff --git a/src/lib/libc/stdlib/qdiv.c b/src/lib/libc/stdlib/qdiv.c
index 8f8e3f89c4..07e84cd649 100644
--- a/src/lib/libc/stdlib/qdiv.c
+++ b/src/lib/libc/stdlib/qdiv.c
@@ -35,8 +35,7 @@
35 */ 35 */
36 36
37#if defined(LIBC_SCCS) && !defined(lint) 37#if defined(LIBC_SCCS) && !defined(lint)
38/*static char *sccsid = "from: @(#)ldiv.c 5.2 (Berkeley) 4/16/91";*/ 38static char *rcsid = "$OpenBSD: qdiv.c,v 1.2 1996/08/19 08:33:41 tholo Exp $";
39static char *rcsid = "$Id: qdiv.c,v 1.1.1.1 1995/10/18 08:42:18 deraadt Exp $";
40#endif /* LIBC_SCCS and not lint */ 39#endif /* LIBC_SCCS and not lint */
41 40
42#include <stdlib.h> /* qdiv_t */ 41#include <stdlib.h> /* qdiv_t */
diff --git a/src/lib/libc/stdlib/qsort.3 b/src/lib/libc/stdlib/qsort.3
index eb122cde12..a0561cadbe 100644
--- a/src/lib/libc/stdlib/qsort.3
+++ b/src/lib/libc/stdlib/qsort.3
@@ -33,14 +33,15 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)qsort.3 8.1 (Berkeley) 6/4/93 36.\" $OpenBSD: qsort.3,v 1.10 2003/05/10 06:48:30 jmc Exp $
37.\" $Id: qsort.3,v 1.1.1.1 1995/10/18 08:42:18 deraadt Exp $
38.\" 37.\"
39.Dd June 4, 1993 38.Dd June 4, 1993
40.Dt QSORT 3 39.Dt QSORT 3
41.Os 40.Os
42.Sh NAME 41.Sh NAME
43.Nm qsort, heapsort, mergesort 42.Nm qsort ,
43.Nm heapsort ,
44.Nm mergesort
44.Nd sort functions 45.Nd sort functions
45.Sh SYNOPSIS 46.Sh SYNOPSIS
46.Fd #include <stdlib.h> 47.Fd #include <stdlib.h>
@@ -72,7 +73,7 @@ objects, the initial member of which is pointed to by
72.Fa base . 73.Fa base .
73The size of each object is specified by 74The size of each object is specified by
74.Fa size . 75.Fa size .
75.Fn Mergesort 76.Fn mergesort
76behaves similarly, but 77behaves similarly, but
77.Em requires 78.Em requires
78that 79that
@@ -106,51 +107,49 @@ is stable.
106.Pp 107.Pp
107The 108The
108.Fn qsort 109.Fn qsort
109function is an implementation of C.A.R. Hoare's ``quicksort'' algorithm, 110function is an implementation of C.A.R. Hoare's
111.Dq quicksort
112algorithm,
110a variant of partition-exchange sorting; in particular, see D.E. Knuth's 113a variant of partition-exchange sorting; in particular, see D.E. Knuth's
111Algorithm Q. 114Algorithm Q.
112.Fn Qsort 115.Fn qsort
113takes O N lg N average time. 116takes O N lg N average time.
114This implementation uses median selection to avoid its 117This implementation uses median selection to avoid its
115O N**2 worst-case behavior. 118O N**2 worst-case behavior.
116.Pp 119.Pp
117The 120The
118.Fn heapsort 121.Fn heapsort
119function is an implementation of J.W.J. William's ``heapsort'' algorithm, 122function is an implementation of J.W.J. William's
123.Dq heapsort
124algorithm,
120a variant of selection sorting; in particular, see D.E. Knuth's Algorithm H. 125a variant of selection sorting; in particular, see D.E. Knuth's Algorithm H.
121.Fn Heapsort 126.Fn heapsort
122takes O N lg N worst-case time. 127takes O N lg N worst-case time.
123Its 128This implementation of
124.Em only
125advantage over
126.Fn qsort 129.Fn qsort
127is that it uses almost no additional memory; while 130is implemented without recursive function calls.
128.Fn qsort
129does not allocate memory, it is implemented using recursion.
130.Pp 131.Pp
131The function 132The function
132.Fn mergesort 133.Fn mergesort
133requires additional memory of size 134requires additional memory of size
134.Fa nmemb * 135.Fa nmemb *
135.Fa size 136.Fa size
136bytes; it should be used only when space is not at a premium. 137bytes; it should be used only when space is not at a premium.
137.Fn Mergesort 138.Fn mergesort
138is optimized for data with pre-existing order; its worst case 139is optimized for data with pre-existing order; its worst case
139time is O N lg N; its best case is O N. 140time is O N lg N; its best case is O N.
140.Pp 141.Pp
141Normally, 142Normally,
142.Fn qsort 143.Fn qsort
143is faster than 144is faster than
144.Fn mergesort 145.Fn mergesort ,
145is faster than 146which is faster than
146.Fn heapsort . 147.Fn heapsort .
147Memory availability and pre-existing order in the data can make this 148Memory availability and pre-existing order in the data can make this untrue.
148untrue.
149.Sh RETURN VALUES 149.Sh RETURN VALUES
150The 150The
151.Fn qsort 151.Fn qsort
152function 152function returns no value.
153returns no value.
154.Pp 153.Pp
155Upon successful completion, 154Upon successful completion,
156.Fn heapsort 155.Fn heapsort
@@ -163,20 +162,21 @@ is set to indicate the error.
163.Sh ERRORS 162.Sh ERRORS
164The 163The
165.Fn heapsort 164.Fn heapsort
166function succeeds unless: 165and
166.Fn mergesort
167functions succeed unless:
167.Bl -tag -width Er 168.Bl -tag -width Er
168.It Bq Er EINVAL 169.It Bq Er EINVAL
169The 170The
170.Fa size 171.Fa size
171argument is zero, or, 172argument is zero, or the
172the
173.Fa size 173.Fa size
174argument to 174argument to
175.Fn mergesort 175.Fn mergesort
176is less than 176is less than
177.Dq "sizeof(void *) / 2" . 177.Dq "sizeof(void *) / 2" .
178.It Bq Er ENOMEM 178.It Bq Er ENOMEM
179.Fn Heapsort 179.Fn heapsort
180or 180or
181.Fn mergesort 181.Fn mergesort
182were unable to allocate memory. 182were unable to allocate memory.
@@ -185,7 +185,7 @@ were unable to allocate memory.
185Previous versions of 185Previous versions of
186.Fn qsort 186.Fn qsort
187did not permit the comparison routine itself to call 187did not permit the comparison routine itself to call
188.Fn qsort 3 . 188.Fn qsort .
189This is no longer true. 189This is no longer true.
190.Sh SEE ALSO 190.Sh SEE ALSO
191.Xr sort 1 , 191.Xr sort 1 ,
@@ -229,6 +229,5 @@ This is no longer true.
229.Sh STANDARDS 229.Sh STANDARDS
230The 230The
231.Fn qsort 231.Fn qsort
232function 232function conforms to
233conforms to
234.St -ansiC . 233.St -ansiC .
diff --git a/src/lib/libc/stdlib/qsort.c b/src/lib/libc/stdlib/qsort.c
index c06bd54054..9b8bb5801b 100644
--- a/src/lib/libc/stdlib/qsort.c
+++ b/src/lib/libc/stdlib/qsort.c
@@ -32,15 +32,14 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char sccsid[] = "from: @(#)qsort.c 8.1 (Berkeley) 6/4/93";*/ 35static char *rcsid = "$OpenBSD: qsort.c,v 1.7 2002/02/17 19:42:24 millert Exp $";
36static char *rcsid = "$Id: qsort.c,v 1.1.1.1 1995/10/18 08:42:18 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
38 37
39#include <sys/types.h> 38#include <sys/types.h>
40#include <stdlib.h> 39#include <stdlib.h>
41 40
42static inline char *med3 __P((char *, char *, char *, int (*)())); 41static __inline char *med3(char *, char *, char *, int (*)());
43static inline void swapfunc __P((char *, char *, int, int)); 42static __inline void swapfunc(char *, char *, int, int);
44 43
45#define min(a, b) (a) < (b) ? a : b 44#define min(a, b) (a) < (b) ? a : b
46 45
@@ -61,12 +60,12 @@ static inline void swapfunc __P((char *, char *, int, int));
61#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \ 60#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \
62 es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1; 61 es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1;
63 62
64static inline void 63static __inline void
65swapfunc(a, b, n, swaptype) 64swapfunc(a, b, n, swaptype)
66 char *a, *b; 65 char *a, *b;
67 int n, swaptype; 66 int n, swaptype;
68{ 67{
69 if(swaptype <= 1) 68 if (swaptype <= 1)
70 swapcode(long, a, b, n) 69 swapcode(long, a, b, n)
71 else 70 else
72 swapcode(char, a, b, n) 71 swapcode(char, a, b, n)
@@ -82,7 +81,7 @@ swapfunc(a, b, n, swaptype)
82 81
83#define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype) 82#define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype)
84 83
85static inline char * 84static __inline char *
86med3(a, b, c, cmp) 85med3(a, b, c, cmp)
87 char *a, *b, *c; 86 char *a, *b, *c;
88 int (*cmp)(); 87 int (*cmp)();
@@ -93,27 +92,28 @@ med3(a, b, c, cmp)
93} 92}
94 93
95void 94void
96qsort(a, n, es, cmp) 95qsort(aa, n, es, cmp)
97 void *a; 96 void *aa;
98 size_t n, es; 97 size_t n, es;
99 int (*cmp)(); 98 int (*cmp)();
100{ 99{
101 char *pa, *pb, *pc, *pd, *pl, *pm, *pn; 100 char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
102 int d, r, swaptype, swap_cnt; 101 int d, r, swaptype, swap_cnt;
102 register char *a = aa;
103 103
104loop: SWAPINIT(a, es); 104loop: SWAPINIT(a, es);
105 swap_cnt = 0; 105 swap_cnt = 0;
106 if (n < 7) { 106 if (n < 7) {
107 for (pm = a + es; pm < (char *) a + n * es; pm += es) 107 for (pm = (char *)a + es; pm < (char *) a + n * es; pm += es)
108 for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0; 108 for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0;
109 pl -= es) 109 pl -= es)
110 swap(pl, pl - es); 110 swap(pl, pl - es);
111 return; 111 return;
112 } 112 }
113 pm = a + (n / 2) * es; 113 pm = (char *)a + (n / 2) * es;
114 if (n > 7) { 114 if (n > 7) {
115 pl = a; 115 pl = (char *)a;
116 pn = a + (n - 1) * es; 116 pn = (char *)a + (n - 1) * es;
117 if (n > 40) { 117 if (n > 40) {
118 d = (n / 8) * es; 118 d = (n / 8) * es;
119 pl = med3(pl, pl + d, pl + 2 * d, cmp); 119 pl = med3(pl, pl + d, pl + 2 * d, cmp);
@@ -123,9 +123,9 @@ loop: SWAPINIT(a, es);
123 pm = med3(pl, pm, pn, cmp); 123 pm = med3(pl, pm, pn, cmp);
124 } 124 }
125 swap(a, pm); 125 swap(a, pm);
126 pa = pb = a + es; 126 pa = pb = (char *)a + es;
127 127
128 pc = pd = a + (n - 1) * es; 128 pc = pd = (char *)a + (n - 1) * es;
129 for (;;) { 129 for (;;) {
130 while (pb <= pc && (r = cmp(pb, a)) <= 0) { 130 while (pb <= pc && (r = cmp(pb, a)) <= 0) {
131 if (r == 0) { 131 if (r == 0) {
@@ -151,14 +151,14 @@ loop: SWAPINIT(a, es);
151 pc -= es; 151 pc -= es;
152 } 152 }
153 if (swap_cnt == 0) { /* Switch to insertion sort */ 153 if (swap_cnt == 0) { /* Switch to insertion sort */
154 for (pm = a + es; pm < (char *) a + n * es; pm += es) 154 for (pm = (char *) a + es; pm < (char *) a + n * es; pm += es)
155 for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0; 155 for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0;
156 pl -= es) 156 pl -= es)
157 swap(pl, pl - es); 157 swap(pl, pl - es);
158 return; 158 return;
159 } 159 }
160 160
161 pn = a + n * es; 161 pn = (char *)a + n * es;
162 r = min(pa - (char *)a, pb - pa); 162 r = min(pa - (char *)a, pb - pa);
163 vecswap(a, pb - r, r); 163 vecswap(a, pb - r, r);
164 r = min(pd - pc, pn - pd - es); 164 r = min(pd - pc, pn - pd - es);
diff --git a/src/lib/libc/stdlib/radixsort.3 b/src/lib/libc/stdlib/radixsort.3
index a2af9f17a4..f70990fa8e 100644
--- a/src/lib/libc/stdlib/radixsort.3
+++ b/src/lib/libc/stdlib/radixsort.3
@@ -29,8 +29,7 @@
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE. 30.\" SUCH DAMAGE.
31.\" 31.\"
32.\" from: @(#)radixsort.3 8.2 (Berkeley) 1/27/94 32.\" $OpenBSD: radixsort.3,v 1.7 2001/08/06 10:42:26 mpech Exp $
33.\" $Id: radixsort.3,v 1.1.1.1 1995/10/18 08:42:18 deraadt Exp $
34.\" 33.\"
35.Dd January 27, 1994 34.Dd January 27, 1994
36.Dt RADIXSORT 3 35.Dt RADIXSORT 3
@@ -42,16 +41,15 @@
42.Fd #include <limits.h> 41.Fd #include <limits.h>
43.Fd #include <stdlib.h> 42.Fd #include <stdlib.h>
44.Ft int 43.Ft int
45.Fn radixsort "u_char **base" "int nmemb" "u_char *table" "u_int endbyte" 44.Fn radixsort "const u_char **base" "int nmemb" "const u_char *table" "u_int endbyte"
46.Ft int 45.Ft int
47.Fn sradixsort "u_char **base" "int nmemb" "u_char *table" "u_int endbyte" 46.Fn sradixsort "const u_char **base" "int nmemb" "const u_char *table" "u_int endbyte"
48.Sh DESCRIPTION 47.Sh DESCRIPTION
49The 48The
50.Fn radixsort 49.Fn radixsort
51and 50and
52.Fn sradixsort 51.Fn sradixsort
53functions 52functions are implementations of radix sort.
54are implementations of radix sort.
55.Pp 53.Pp
56These functions sort an array of pointers to byte strings, the initial 54These functions sort an array of pointers to byte strings, the initial
57member of which is referenced by 55member of which is referenced by
@@ -63,26 +61,24 @@ is denoted by the user-specified value
63Applications may specify a sort order by providing the 61Applications may specify a sort order by providing the
64.Fa table 62.Fa table
65argument. 63argument.
66If 64If non-null,
67.Pf non- Dv NULL ,
68.Fa table 65.Fa table
69must reference an array of 66must reference an array of
70.Dv UCHAR_MAX 67.Dv UCHAR_MAX
71+ 1 bytes which contains the sort 68+ 1 bytes which contains the sort weight of each possible byte value.
72weight of each possible byte value.
73The end-of-string byte must have a sort weight of 0 or 255 69The end-of-string byte must have a sort weight of 0 or 255
74(for sorting in reverse order). 70(for sorting in reverse order).
75More than one byte may have the same sort weight. 71More than one byte may have the same sort weight.
76The 72The
77.Fa table 73.Fa table
78argument 74argument is useful for applications which wish to sort different characters
79is useful for applications which wish to sort different characters
80equally, for example, providing a table with the same weights 75equally, for example, providing a table with the same weights
81for A-Z as for a-z will result in a case-insensitive sort. 76for A-Z as for a-z will result in a case-insensitive sort.
82If 77If
83.Fa table 78.Fa table
84is NULL, the contents of the array are sorted in ascending order 79is
85according to the 80.Dv NULL ,
81the contents of the array are sorted in ascending order according to the
86.Tn ASCII 82.Tn ASCII
87order of the byte strings they reference and 83order of the byte strings they reference and
88.Fa endbyte 84.Fa endbyte
@@ -107,7 +103,7 @@ particular, see D.E. Knuth's Algorithm R and section 5.2.5, exercise 10.
107They take linear time relative to the number of bytes in the strings. 103They take linear time relative to the number of bytes in the strings.
108.Sh RETURN VALUES 104.Sh RETURN VALUES
109Upon successful completion 0 is returned. 105Upon successful completion 0 is returned.
110Otherwise, \-1 is returned and the global variable 106Otherwise, \-1 is returned and the global variable
111.Va errno 107.Va errno
112is set to indicate the error. 108is set to indicate the error.
113.Sh ERRORS 109.Sh ERRORS
@@ -122,15 +118,13 @@ is not 0 or 255.
122.Pp 118.Pp
123Additionally, the 119Additionally, the
124.Fn sradixsort 120.Fn sradixsort
125function 121function may fail and set
126may fail and set
127.Va errno 122.Va errno
128for any of the errors specified for the library routine 123for any of the errors specified for the library routine
129.Xr malloc 3 . 124.Xr malloc 3 .
130.Sh SEE ALSO 125.Sh SEE ALSO
131.Xr sort 1 , 126.Xr sort 1 ,
132.Xr qsort 3 127.Xr qsort 3
133.Pp
134.Rs 128.Rs
135.%A Knuth, D.E. 129.%A Knuth, D.E.
136.%D 1968 130.%D 1968
@@ -158,4 +152,5 @@ for any of the errors specified for the library routine
158.Sh HISTORY 152.Sh HISTORY
159The 153The
160.Fn radixsort 154.Fn radixsort
161function first appeared in 4.4BSD. 155function first appeared in
156.Bx 4.4 .
diff --git a/src/lib/libc/stdlib/radixsort.c b/src/lib/libc/stdlib/radixsort.c
index dd51013c94..e03b479715 100644
--- a/src/lib/libc/stdlib/radixsort.c
+++ b/src/lib/libc/stdlib/radixsort.c
@@ -35,8 +35,7 @@
35 */ 35 */
36 36
37#if defined(LIBC_SCCS) && !defined(lint) 37#if defined(LIBC_SCCS) && !defined(lint)
38/*static char sccsid[] = "from: @(#)radixsort.c 8.1 (Berkeley) 6/4/93";*/ 38static char *rcsid = "$OpenBSD: radixsort.c,v 1.5 2002/02/17 19:42:24 millert Exp $";
39static char *rcsid = "$Id: radixsort.c,v 1.1.1.1 1995/10/18 08:42:19 deraadt Exp $";
40#endif /* LIBC_SCCS and not lint */ 39#endif /* LIBC_SCCS and not lint */
41 40
42/* 41/*
@@ -61,11 +60,11 @@ typedef struct {
61 int sn, si; 60 int sn, si;
62} stack; 61} stack;
63 62
64static inline void simplesort 63static __inline void simplesort
65 __P((const u_char **, int, int, const u_char *, u_int)); 64(const u_char **, int, int, const u_char *, u_int);
66static void r_sort_a __P((const u_char **, int, int, const u_char *, u_int)); 65static void r_sort_a(const u_char **, int, int, const u_char *, u_int);
67static void r_sort_b __P((const u_char **, 66static void r_sort_b(const u_char **,
68 const u_char **, int, int, const u_char *, u_int)); 67 const u_char **, int, int, const u_char *, u_int);
69 68
70#define THRESHOLD 20 /* Divert to simplesort(). */ 69#define THRESHOLD 20 /* Divert to simplesort(). */
71#define SIZE 512 /* Default stack size. */ 70#define SIZE 512 /* Default stack size. */
@@ -295,7 +294,7 @@ r_sort_b(a, ta, n, i, tr, endch)
295 } 294 }
296} 295}
297 296
298static inline void 297static __inline void
299simplesort(a, n, b, tr, endch) /* insertion sort */ 298simplesort(a, n, b, tr, endch) /* insertion sort */
300 register const u_char **a; 299 register const u_char **a;
301 int n, b; 300 int n, b;
diff --git a/src/lib/libc/stdlib/rand.3 b/src/lib/libc/stdlib/rand.3
index a0e7740e66..8899c2e104 100644
--- a/src/lib/libc/stdlib/rand.3
+++ b/src/lib/libc/stdlib/rand.3
@@ -33,8 +33,7 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)rand.3 6.7 (Berkeley) 6/29/91 36.\" $OpenBSD: rand.3,v 1.8 2001/05/13 23:38:02 millert Exp $
37.\" $Id: rand.3,v 1.1.1.1 1995/10/18 08:42:19 deraadt Exp $
38.\" 37.\"
39.Dd June 29, 1991 38.Dd June 29, 1991
40.Dt RAND 3 39.Dt RAND 3
@@ -46,12 +45,15 @@
46.Sh SYNOPSIS 45.Sh SYNOPSIS
47.Fd #include <stdlib.h> 46.Fd #include <stdlib.h>
48.Ft void 47.Ft void
49.Fn srand "unsigned seed" 48.Fn srand "unsigned int seed"
50.Ft int 49.Ft int
51.Fn rand void 50.Fn rand void
51.Ft int
52.Fn rand_r "unsigned int *seed"
52.Sh DESCRIPTION 53.Sh DESCRIPTION
53.Bf -symbolic 54.Bf -symbolic
54These interfaces are obsoleted by random(3). 55These interfaces are obsoleted by
56.Xr random 3 .
55.Ef 57.Ef
56.Pp 58.Pp
57The 59The
@@ -73,13 +75,28 @@ with the same seed value.
73.Pp 75.Pp
74If no seed value is provided, the functions are automatically 76If no seed value is provided, the functions are automatically
75seeded with a value of 1. 77seeded with a value of 1.
78.Pp
79The
80.Fn rand_r
81is a thread-safe version of
82.Fn rand .
83Storage for the seed must be provided through the
84.Fa seed
85argument, and needs to have been initialized by the caller.
76.Sh SEE ALSO 86.Sh SEE ALSO
87.Xr arc4random 3 ,
88.Xr rand48 3 ,
77.Xr random 3 89.Xr random 3
78.Sh STANDARDS 90.Sh STANDARDS
79The 91The
80.Fn rand 92.Fn rand
81and 93and
82.Fn srand 94.Fn srand
83functions 95functions conform to
84conform to
85.St -ansiC . 96.St -ansiC .
97.Pp
98The
99.Fn rand_r
100function conforms to ISO/IEC 9945-1 ANSI/IEEE
101.Pq Dq Tn POSIX
102Std 1003.1c Draft 10.
diff --git a/src/lib/libc/stdlib/rand.c b/src/lib/libc/stdlib/rand.c
index 361d473448..bb180886c0 100644
--- a/src/lib/libc/stdlib/rand.c
+++ b/src/lib/libc/stdlib/rand.c
@@ -32,24 +32,34 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)rand.c 5.6 (Berkeley) 6/24/91";*/ 35static char *rcsid = "$OpenBSD: rand.c,v 1.6 1998/12/07 21:47:22 millert Exp $";
36static char *rcsid = "$Id: rand.c,v 1.1.1.1 1995/10/18 08:42:19 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
38 37
39#include <sys/types.h> 38#include <sys/types.h>
40#include <stdlib.h> 39#include <stdlib.h>
41 40
42static u_long next = 1; 41static u_int next = 1;
42
43int
44rand_r(seed)
45u_int *seed;
46{
47
48 *seed = *seed * 1103515245 + 12345;
49 return (*seed % ((u_int)RAND_MAX + 1));
50}
43 51
44int 52int
45rand() 53rand()
46{ 54{
47 return ((next = next * 1103515245 + 12345) % ((u_int)RAND_MAX + 1)); 55
56 return (rand_r(&next));
48} 57}
49 58
50void 59void
51srand(seed) 60srand(seed)
52u_int seed; 61u_int seed;
53{ 62{
63
54 next = seed; 64 next = seed;
55} 65}
diff --git a/src/lib/libc/stdlib/rand48.3 b/src/lib/libc/stdlib/rand48.3
index 5a772c9a8c..6b0831ead7 100644
--- a/src/lib/libc/stdlib/rand48.3
+++ b/src/lib/libc/stdlib/rand48.3
@@ -1,4 +1,4 @@
1\" Copyright (c) 1993 Martin Birgmeier 1.\" Copyright (c) 1993 Martin Birgmeier
2.\" All rights reserved. 2.\" All rights reserved.
3.\" 3.\"
4.\" You may redistribute unmodified or modified versions of this source 4.\" You may redistribute unmodified or modified versions of this source
@@ -9,7 +9,7 @@
9.\" of any kind. I shall in no event be liable for anything that happens 9.\" of any kind. I shall in no event be liable for anything that happens
10.\" to anyone/anything when using this software. 10.\" to anyone/anything when using this software.
11.\" 11.\"
12.\" $Id: rand48.3,v 1.1.1.1 1995/10/18 08:42:19 deraadt Exp $ 12.\" $OpenBSD: rand48.3,v 1.9 2003/05/10 06:48:30 jmc Exp $
13.\" 13.\"
14.Dd October 8, 1993 14.Dd October 8, 1993
15.Dt RAND48 3 15.Dt RAND48 3
@@ -24,10 +24,10 @@
24.Nm srand48 , 24.Nm srand48 ,
25.Nm seed48 , 25.Nm seed48 ,
26.Nm lcong48 26.Nm lcong48
27.Nd pseudo random number generators and initialization routines 27.Nd pseudo-random number generators and initialization routines
28.Sh SYNOPSIS 28.Sh SYNOPSIS
29.Fd #include <stdlib.h> 29.Fd #include <stdlib.h>
30.Ft double 30.Ft double
31.Fn drand48 void 31.Fn drand48 void
32.Ft double 32.Ft double
33.Fn erand48 "unsigned short xseed[3]" 33.Fn erand48 "unsigned short xseed[3]"
@@ -49,12 +49,13 @@
49The 49The
50.Fn rand48 50.Fn rand48
51family of functions generates pseudo-random numbers using a linear 51family of functions generates pseudo-random numbers using a linear
52congruential algorithm working on integers 48 bits in size. The 52congruential algorithm working on integers 48 bits in size.
53particular formula employed is 53The particular formula employed is
54r(n+1) = (a * r(n) + c) mod m 54r(n+1) = (a * r(n) + c) mod m
55where the default values are 55where the default values are
56for the multiplicand a = 0xfdeece66d = 25214903917 and 56for the multiplicand a = 0xfdeece66d = 25214903917 and
57the addend c = 0xb = 11. The modulus is always fixed at m = 2 ** 48. 57the addend c = 0xb = 11.
58The modulus is always fixed at m = 2 ** 48.
58r(n) is called the seed of the random number generator. 59r(n) is called the seed of the random number generator.
59.Pp 60.Pp
60For all the six generator routines described next, the first 61For all the six generator routines described next, the first
@@ -63,15 +64,17 @@ computational step is to perform a single iteration of the algorithm.
63.Fn drand48 64.Fn drand48
64and 65and
65.Fn erand48 66.Fn erand48
66return values of type double. The full 48 bits of r(n+1) are 67return values of type double.
68The full 48 bits of r(n+1) are
67loaded into the mantissa of the returned value, with the exponent set 69loaded into the mantissa of the returned value, with the exponent set
68such that the values produced lie in the interval [0.0, 1.0). 70such that the values produced lie in the interval [0.0, 1.0].
69.Pp 71.Pp
70.Fn lrand48 72.Fn lrand48
71and 73and
72.Fn nrand48 74.Fn nrand48
73return values of type long in the range 75return values of type long in the range
74[0, 2**31-1]. The high-order (31) bits of 76[0, 2**31-1].
77The high-order (31) bits of
75r(n+1) are loaded into the lower bits of the returned value, with 78r(n+1) are loaded into the lower bits of the returned value, with
76the topmost (sign) bit set to zero. 79the topmost (sign) bit set to zero.
77.Pp 80.Pp
@@ -79,14 +82,15 @@ the topmost (sign) bit set to zero.
79and 82and
80.Fn jrand48 83.Fn jrand48
81return values of type long in the range 84return values of type long in the range
82[-2**31, 2**31-1]. The high-order (32) bits of 85[-2**31, 2**31-1].
83r(n+1) are loaded into the returned value. 86The high-order (32) bits of r(n+1) are loaded into the returned value.
84.Pp 87.Pp
85.Fn drand48 , 88.Fn drand48 ,
86.Fn lrand48 , 89.Fn lrand48 ,
87and 90and
88.Fn mrand48 91.Fn mrand48
89use an internal buffer to store r(n). For these functions 92use an internal buffer to store r(n).
93For these functions
90the initial value of r(0) = 0x1234abcd330e = 20017429951246. 94the initial value of r(0) = 0x1234abcd330e = 20017429951246.
91.Pp 95.Pp
92On the other hand, 96On the other hand,
@@ -118,12 +122,12 @@ also initializes the internal buffer r(n) of
118and 122and
119.Fn mrand48 , 123.Fn mrand48 ,
120but here all 48 bits of the seed can be specified in an array of 3 shorts, 124but here all 48 bits of the seed can be specified in an array of 3 shorts,
121where the zeroth member specifies the lowest bits. Again, 125where the zeroth member specifies the lowest bits.
122the constant multiplicand and addend of the algorithm are 126Again, the constant multiplicand and addend of the algorithm are
123reset to the default values given above. 127reset to the default values given above.
124.Fn seed48 128.Fn seed48
125returns a pointer to an array of 3 shorts which contains the old seed. 129returns a pointer to an array of 3 shorts which contains the old seed.
126This array is statically allocated, thus its contents are lost after 130This array is statically allocated, so its contents are lost after
127each new call to 131each new call to
128.Fn seed48 . 132.Fn seed48 .
129.Pp 133.Pp
@@ -152,9 +156,10 @@ always also set the multiplicand and addend for any of the six
152generator calls. 156generator calls.
153.Pp 157.Pp
154For a more powerful random number generator, see 158For a more powerful random number generator, see
155.Xr random 3 159.Xr random 3 .
156.Sh AUTHOR 160.Sh AUTHORS
157Martin Birgmeier 161Martin Birgmeier
158.Sh SEE ALSO 162.Sh SEE ALSO
163.Xr arc4random 3 ,
159.Xr rand 3 , 164.Xr rand 3 ,
160.Xr random 3 . 165.Xr random 3
diff --git a/src/lib/libc/stdlib/rand48.h b/src/lib/libc/stdlib/rand48.h
index 12496d1c8c..afa49f65f3 100644
--- a/src/lib/libc/stdlib/rand48.h
+++ b/src/lib/libc/stdlib/rand48.h
@@ -9,6 +9,8 @@
9 * This software is provided ``as is'', and comes with no warranties 9 * This software is provided ``as is'', and comes with no warranties
10 * of any kind. I shall in no event be liable for anything that happens 10 * of any kind. I shall in no event be liable for anything that happens
11 * to anyone/anything when using this software. 11 * to anyone/anything when using this software.
12 *
13 * $OpenBSD: rand48.h,v 1.3 2002/02/16 21:27:24 millert Exp $
12 */ 14 */
13 15
14#ifndef _RAND48_H_ 16#ifndef _RAND48_H_
@@ -17,7 +19,7 @@
17#include <math.h> 19#include <math.h>
18#include <stdlib.h> 20#include <stdlib.h>
19 21
20void __dorand48 __P((unsigned short[3])); 22void __dorand48(unsigned short[3]);
21 23
22#define RAND48_SEED_0 (0x330e) 24#define RAND48_SEED_0 (0x330e)
23#define RAND48_SEED_1 (0xabcd) 25#define RAND48_SEED_1 (0xabcd)
diff --git a/src/lib/libc/stdlib/random.3 b/src/lib/libc/stdlib/random.3
index 38c15a9803..b98917a442 100644
--- a/src/lib/libc/stdlib/random.3
+++ b/src/lib/libc/stdlib/random.3
@@ -29,97 +29,106 @@
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE. 30.\" SUCH DAMAGE.
31.\" 31.\"
32.\" from: @(#)random.3 6.5 (Berkeley) 4/19/91 32.\" $OpenBSD: random.3,v 1.15 2003/05/10 06:48:30 jmc Exp $
33.\" $Id: random.3,v 1.1.1.1 1995/10/18 08:42:19 deraadt Exp $
34.\" 33.\"
35.Dd April 19, 1991 34.Dd April 19, 1991
36.Dt RANDOM 3 35.Dt RANDOM 3
37.Os BSD 4.2 36.Os
38.Sh NAME 37.Sh NAME
39.Nm random , 38.Nm random ,
40.Nm srandom , 39.Nm srandom ,
40.Nm srandomdev ,
41.Nm initstate , 41.Nm initstate ,
42.Nm setstate 42.Nm setstate
43.Nd better random number generator; routines for changing generators 43.Nd better random number generator; routines for changing generators
44.Sh SYNOPSIS 44.Sh SYNOPSIS
45.Fd #include <stdlib.h> 45.Fd #include <stdlib.h>
46.Ft long 46.Ft long
47.Fn random void 47.Fn random void
48.Ft void 48.Ft void
49.Fn srandom "unsigned seed" 49.Fn srandom "unsigned int seed"
50.Ft void
51.Fn srandomdev void
50.Ft char * 52.Ft char *
51.Fn initstate "unsigned seed" "char *state" "int n" 53.Fn initstate "unsigned int seed" "char *state" "size_t n"
52.Ft char * 54.Ft char *
53.Fn setstate "char *state" 55.Fn setstate "const char *state"
54.Sh DESCRIPTION 56.Sh DESCRIPTION
55The 57The
56.Fn random 58.Fn random
57function 59function uses a non-linear additive feedback random number generator employing
58uses a non-linear additive feedback random number generator employing a 60a default table of size 31 long integers to return successive pseudo-random
59default table of size 31 long integers to return successive pseudo-random 61numbers in the range from 0 to (2**31)\-1.
60numbers in the range from 0 to
61.if t 2\u\s731\s10\d\(mi1.
62.if n (2**31)\(mi1.
63The period of this random number generator is very large, approximately 62The period of this random number generator is very large, approximately
64.if t 16\(mu(2\u\s731\s10\d\(mi1). 6316*((2**31)\-1).
65.if n 16*((2**31)\(mi1).
66.Pp 64.Pp
67The 65The
68.Fn random Ns / Fn srandom 66.Fn random
69have (almost) the same calling sequence and initialization properties as 67and
70.Xr rand 3 Ns / Xr srand 3 . 68.Fn srandom
69functions have (almost) the same calling sequence and initialization
70properties as
71.Xr rand 3 Ns / Ns Xr srand 3 .
71The difference is that 72The difference is that
72.Xr rand 73.Xr rand
73produces a much less random sequence \(em in fact, the low dozen bits 74produces a much less random sequence \(em in fact, the low dozen bits
74generated by rand go through a cyclic pattern. All the bits generated by 75generated by rand go through a cyclic pattern.
76All the bits generated by
75.Fn random 77.Fn random
76are usable. For example, 78are usable.
79For example,
77.Sq Li random()&01 80.Sq Li random()&01
78will produce a random binary 81will produce a random binary
79value. 82value.
80.Pp 83.Pp
81Unlike 84Like
82.Xr srand ,
83.Fn srandom
84does not return the old seed; the reason for this is that the amount of
85state information used is much more than a single word. (Two other
86routines are provided to deal with restarting/changing random
87number generators). Like
88.Xr rand 3 , 85.Xr rand 3 ,
89however,
90.Fn random 86.Fn random
91will by default produce a sequence of numbers that can be duplicated 87will by default produce a sequence of numbers that can be duplicated
92by calling 88by calling
93.Fn srandom 89.Fn srandom
94with 90with
95.Ql 1 91.Ql 1
96as the seed. 92as the seed.
97.Pp 93.Pp
98The 94The
95.Fn srandomdev
96routine initializes a state array using the
97.Xr arandom 4
98random number device which returns good random numbers,
99suitable for cryptographic use.
100Note that this particular seeding procedure can generate
101states which are impossible to reproduce by calling
102.Fn srandom
103with any value, since the succeeding terms in the
104state buffer are no longer derived from the LC algorithm applied to
105a fixed seed.
106.Pp
107The
99.Fn initstate 108.Fn initstate
100routine allows a state array, passed in as an argument, to be initialized 109routine allows a state array, passed in as an argument, to be initialized
101for future use. The size of the state array (in bytes) is used by 110for future use.
111The size of the state array (in bytes) is used by
102.Fn initstate 112.Fn initstate
103to decide how sophisticated a random number generator it should use \(em the 113to decide how sophisticated a random number generator it should use \(em the
104more state, the better the random numbers will be. 114more state, the better the random numbers will be.
105(Current "optimal" values for the amount of state information are 115(Current "optimal" values for the amount of state information are
1068, 32, 64, 128, and 256 bytes; other amounts will be rounded down to 1168, 32, 64, 128, and 256 bytes; other amounts will be rounded down to
107the nearest known amount. Using less than 8 bytes will cause an error.) 117the nearest known amount.
118Using less than 8 bytes will cause an error.)
108The seed for the initialization (which specifies a starting point for 119The seed for the initialization (which specifies a starting point for
109the random number sequence, and provides for restarting at the same 120the random number sequence, and provides for restarting at the same
110point) is also an argument. 121point) is also an argument.
111The 122The
112.Fn initstate 123.Fn initstate
113function 124function returns a pointer to the previous state information array.
114returns a pointer to the previous state information array.
115.Pp 125.Pp
116Once a state has been initialized, the 126Once a state has been initialized, the
117.Fn setstate 127.Fn setstate
118routine provides for rapid switching between states. 128routine provides for rapid switching between states.
119The 129The
120.Fn setstate 130.Fn setstate
121function 131function returns a pointer to the previous state array; its
122returns a pointer to the previous state array; its
123argument state array is used for further random number generation 132argument state array is used for further random number generation
124until the next call to 133until the next call to
125.Fn initstate 134.Fn initstate
@@ -143,12 +152,10 @@ is that the size of the state array does not have to be remembered after
143it is initialized. 152it is initialized.
144.Pp 153.Pp
145With 256 bytes of state information, the period of the random number 154With 256 bytes of state information, the period of the random number
146generator is greater than 155generator is greater than 2**69
147.if t 2\u\s769\s10\d,
148.if n 2**69
149which should be sufficient for most purposes. 156which should be sufficient for most purposes.
150.Sh AUTHOR 157.Sh AUTHORS
151Earl T. Cohen 158.An Earl T. Cohen
152.Sh DIAGNOSTICS 159.Sh DIAGNOSTICS
153If 160If
154.Fn initstate 161.Fn initstate
@@ -157,10 +164,26 @@ is called with less than 8 bytes of state information, or if
157detects that the state information has been garbled, error 164detects that the state information has been garbled, error
158messages are printed on the standard error output. 165messages are printed on the standard error output.
159.Sh SEE ALSO 166.Sh SEE ALSO
160.Xr rand 3 167.Xr arc4random 3 ,
168.Xr drand48 3 ,
169.Xr rand 3 ,
170.Xr random 4
171.Sh STANDARDS
172The
173.Fn random ,
174.Fn srandom ,
175.Fn initstate ,
176and
177.Fn setstate
178functions conform to
179.St -xpg4.2 .
180.Pp
181The
182.Fn srandomdev
183function is an extension.
161.Sh HISTORY 184.Sh HISTORY
162These 185These
163functions appeared in 186functions appeared in
164.Bx 4.2 . 187.Bx 4.2 .
165.Sh BUGS 188.Sh BUGS
166About 2/3 the speed of 189About 2/3 the speed of
diff --git a/src/lib/libc/stdlib/random.c b/src/lib/libc/stdlib/random.c
index 469b6d976a..49a5ed1c3e 100644
--- a/src/lib/libc/stdlib/random.c
+++ b/src/lib/libc/stdlib/random.c
@@ -32,12 +32,16 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)random.c 5.9 (Berkeley) 2/23/91";*/ 35static char *rcsid = "$OpenBSD: random.c,v 1.11 2003/02/28 21:27:44 millert Exp $";
36static char *rcsid = "$Id: random.c,v 1.1.1.1 1995/10/18 08:42:19 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
38 37
38#include <sys/param.h>
39#include <sys/sysctl.h>
40#include <sys/time.h>
41#include <fcntl.h>
39#include <stdio.h> 42#include <stdio.h>
40#include <stdlib.h> 43#include <stdlib.h>
44#include <unistd.h>
41 45
42/* 46/*
43 * random.c: 47 * random.c:
@@ -55,10 +59,10 @@ static char *rcsid = "$Id: random.c,v 1.1.1.1 1995/10/18 08:42:19 deraadt Exp $"
55 * congruential generator. If the amount of state information is less than 59 * congruential generator. If the amount of state information is less than
56 * 32 bytes, a simple linear congruential R.N.G. is used. 60 * 32 bytes, a simple linear congruential R.N.G. is used.
57 * 61 *
58 * Internally, the state information is treated as an array of longs; the 62 * Internally, the state information is treated as an array of int32_t; the
59 * zeroeth element of the array is the type of R.N.G. being used (small 63 * zeroeth element of the array is the type of R.N.G. being used (small
60 * integer); the remainder of the array is the state information for the 64 * integer); the remainder of the array is the state information for the
61 * R.N.G. Thus, 32 bytes of state information will give 7 longs worth of 65 * R.N.G. Thus, 32 bytes of state information will give 7 int32_ts worth of
62 * state information, which will allow a degree seven polynomial. (Note: 66 * state information, which will allow a degree seven polynomial. (Note:
63 * the zeroeth word of state information also has some other information 67 * the zeroeth word of state information also has some other information
64 * stored in it -- see setstate() for details). 68 * stored in it -- see setstate() for details).
@@ -134,14 +138,14 @@ static int seps [MAX_TYPES] = { SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 };
134 * MAX_TYPES * (rptr - state) + TYPE_3 == TYPE_3. 138 * MAX_TYPES * (rptr - state) + TYPE_3 == TYPE_3.
135 */ 139 */
136 140
137static long randtbl[DEG_3 + 1] = { 141static int32_t randtbl[DEG_3 + 1] = {
138 TYPE_3, 142 TYPE_3,
139 0x9a319039, 0x32d9c024, 0x9b663182, 0x5da1f342, 0xde3b81e0, 0xdf0a6fb5, 143 0x991539b1, 0x16a5bce3, 0x6774a4cd, 0x3e01511e, 0x4e508aaa, 0x61048c05,
140 0xf103bc02, 0x48f340fb, 0x7449e56b, 0xbeb1dbb0, 0xab5c5918, 0x946554fd, 144 0xf5500617, 0x846b7115, 0x6a19892c, 0x896a97af, 0xdb48f936, 0x14898454,
141 0x8c2e680f, 0xeb3d799f, 0xb11ee0b7, 0x2d436b86, 0xda672e2a, 0x1588ca88, 145 0x37ffd106, 0xb58bff9c, 0x59e17104, 0xcf918a49, 0x09378c83, 0x52c7a471,
142 0xe369735d, 0x904f35f7, 0xd7158fd6, 0x6fa6f051, 0x616e6b96, 0xac94efdc, 146 0x8d293ea9, 0x1f4fc301, 0xc3db71be, 0x39b44e1c, 0xf8a44ef9, 0x4c8b80b1,
143 0x36413f93, 0xc622c298, 0xf5a42ab8, 0x8a88d77b, 0xf5ad9d0e, 0x8999220b, 147 0x19edc328, 0x87bf4bdd, 0xc9b240e5, 0xe9ee4b1b, 0x4382aee7, 0x535b6b41,
144 0x27fb47b9, 148 0xf3bec5da,
145}; 149};
146 150
147/* 151/*
@@ -158,8 +162,8 @@ static long randtbl[DEG_3 + 1] = {
158 * in the initialization of randtbl) because the state table pointer is set 162 * in the initialization of randtbl) because the state table pointer is set
159 * to point to randtbl[1] (as explained below). 163 * to point to randtbl[1] (as explained below).
160 */ 164 */
161static long *fptr = &randtbl[SEP_3 + 1]; 165static int32_t *fptr = &randtbl[SEP_3 + 1];
162static long *rptr = &randtbl[1]; 166static int32_t *rptr = &randtbl[1];
163 167
164/* 168/*
165 * The following things are the pointer to the state information table, the 169 * The following things are the pointer to the state information table, the
@@ -171,11 +175,11 @@ static long *rptr = &randtbl[1];
171 * this is more efficient than indexing every time to find the address of 175 * this is more efficient than indexing every time to find the address of
172 * the last element to see if the front and rear pointers have wrapped. 176 * the last element to see if the front and rear pointers have wrapped.
173 */ 177 */
174static long *state = &randtbl[1]; 178static int32_t *state = &randtbl[1];
179static int32_t *end_ptr = &randtbl[DEG_3 + 1];
175static int rand_type = TYPE_3; 180static int rand_type = TYPE_3;
176static int rand_deg = DEG_3; 181static int rand_deg = DEG_3;
177static int rand_sep = SEP_3; 182static int rand_sep = SEP_3;
178static long *end_ptr = &randtbl[DEG_3 + 1];
179 183
180/* 184/*
181 * srandom: 185 * srandom:
@@ -191,17 +195,28 @@ static long *end_ptr = &randtbl[DEG_3 + 1];
191 */ 195 */
192void 196void
193srandom(x) 197srandom(x)
194 u_int x; 198 unsigned int x;
195{ 199{
196 register int i, j; 200 int i;
201 int32_t test;
202 div_t val;
197 203
198 if (rand_type == TYPE_0) 204 if (rand_type == TYPE_0)
199 state[0] = x; 205 state[0] = x;
200 else { 206 else {
201 j = 1;
202 state[0] = x; 207 state[0] = x;
203 for (i = 1; i < rand_deg; i++) 208 for (i = 1; i < rand_deg; i++) {
204 state[i] = 1103515245 * state[i - 1] + 12345; 209 /*
210 * Implement the following, without overflowing 31 bits:
211 *
212 * state[i] = (16807 * state[i - 1]) % 2147483647;
213 *
214 * 2^31-1 (prime) = 2147483647 = 127773*16807+2836
215 */
216 val = div(state[i-1], 127773);
217 test = 16807 * val.rem - 2836 * val.quot;
218 state[i] = test + (test < 0 ? 2147483647 : 0);
219 }
205 fptr = &state[rand_sep]; 220 fptr = &state[rand_sep];
206 rptr = &state[0]; 221 rptr = &state[0];
207 for (i = 0; i < 10 * rand_deg; i++) 222 for (i = 0; i < 10 * rand_deg; i++)
@@ -210,6 +225,65 @@ srandom(x)
210} 225}
211 226
212/* 227/*
228 * srandomdev:
229 *
230 * Many programs choose the seed value in a totally predictable manner.
231 * This often causes problems. We seed the generator using the much more
232 * secure arandom(4) interface. Note that this particular seeding
233 * procedure can generate states which are impossible to reproduce by
234 * calling srandom() with any value, since the succeeding terms in the
235 * state buffer are no longer derived from the LC algorithm applied to
236 * a fixed seed.
237 */
238void
239srandomdev()
240{
241 int fd, i, mib[2], n;
242 size_t len;
243
244 if (rand_type == TYPE_0)
245 len = sizeof(state[0]);
246 else
247 len = rand_deg * sizeof(state[0]);
248
249 /*
250 * To get seed data, first try reading from /dev/arandom.
251 * If that fails, try the KERN_ARND sysctl() (one int at a time).
252 * As a last resort, call srandom().
253 */
254 if ((fd = open("/dev/arandom", O_RDONLY, 0)) != -1 &&
255 read(fd, (void *) state, len) == (ssize_t) len) {
256 close(fd);
257 } else {
258 if (fd != -1)
259 close(fd);
260 mib[0] = CTL_KERN;
261 mib[1] = KERN_ARND;
262 n = len / sizeof(int);
263 len = sizeof(int);
264 for (i = 0; i < n; i++) {
265 if (sysctl(mib, 2, (char *)((int *)state + i), &len,
266 NULL, 0) == -1)
267 break;
268 }
269 if (i != n) {
270 struct timeval tv;
271 u_int junk;
272
273 /* XXX - this could be better */
274 gettimeofday(&tv, NULL);
275 srandom(getpid() ^ tv.tv_sec ^ tv.tv_usec ^ junk);
276 return;
277 }
278 }
279
280 if (rand_type != TYPE_0) {
281 fptr = &state[rand_sep];
282 rptr = &state[0];
283 }
284}
285
286/*
213 * initstate: 287 * initstate:
214 * 288 *
215 * Initialize the state information in the given array of n bytes for future 289 * Initialize the state information in the given array of n bytes for future
@@ -232,19 +306,16 @@ char *
232initstate(seed, arg_state, n) 306initstate(seed, arg_state, n)
233 u_int seed; /* seed for R.N.G. */ 307 u_int seed; /* seed for R.N.G. */
234 char *arg_state; /* pointer to state array */ 308 char *arg_state; /* pointer to state array */
235 int n; /* # bytes of state info */ 309 size_t n; /* # bytes of state info */
236{ 310{
237 register char *ostate = (char *)(&state[-1]); 311 char *ostate = (char *)(&state[-1]);
238 312
239 if (rand_type == TYPE_0) 313 if (rand_type == TYPE_0)
240 state[-1] = rand_type; 314 state[-1] = rand_type;
241 else 315 else
242 state[-1] = MAX_TYPES * (rptr - state) + rand_type; 316 state[-1] = MAX_TYPES * (rptr - state) + rand_type;
243 if (n < BREAK_0) { 317 if (n < BREAK_0)
244 (void)fprintf(stderr, 318 return(NULL);
245 "random: not enough state (%d bytes); ignored.\n", n);
246 return(0);
247 }
248 if (n < BREAK_1) { 319 if (n < BREAK_1) {
249 rand_type = TYPE_0; 320 rand_type = TYPE_0;
250 rand_deg = DEG_0; 321 rand_deg = DEG_0;
@@ -266,7 +337,7 @@ initstate(seed, arg_state, n)
266 rand_deg = DEG_4; 337 rand_deg = DEG_4;
267 rand_sep = SEP_4; 338 rand_sep = SEP_4;
268 } 339 }
269 state = &(((long *)arg_state)[1]); /* first location */ 340 state = &(((int32_t *)arg_state)[1]); /* first location */
270 end_ptr = &state[rand_deg]; /* must set end_ptr before srandom */ 341 end_ptr = &state[rand_deg]; /* must set end_ptr before srandom */
271 srandom(seed); 342 srandom(seed);
272 if (rand_type == TYPE_0) 343 if (rand_type == TYPE_0)
@@ -293,11 +364,11 @@ initstate(seed, arg_state, n)
293 */ 364 */
294char * 365char *
295setstate(arg_state) 366setstate(arg_state)
296 char *arg_state; 367 const char *arg_state;
297{ 368{
298 register long *new_state = (long *)arg_state; 369 int32_t *new_state = (int32_t *)arg_state;
299 register int type = new_state[0] % MAX_TYPES; 370 int32_t type = new_state[0] % MAX_TYPES;
300 register int rear = new_state[0] / MAX_TYPES; 371 int32_t rear = new_state[0] / MAX_TYPES;
301 char *ostate = (char *)(&state[-1]); 372 char *ostate = (char *)(&state[-1]);
302 373
303 if (rand_type == TYPE_0) 374 if (rand_type == TYPE_0)
@@ -315,8 +386,7 @@ setstate(arg_state)
315 rand_sep = seps[type]; 386 rand_sep = seps[type];
316 break; 387 break;
317 default: 388 default:
318 (void)fprintf(stderr, 389 return(NULL);
319 "random: state info corrupted; not changed.\n");
320 } 390 }
321 state = &new_state[1]; 391 state = &new_state[1];
322 if (rand_type != TYPE_0) { 392 if (rand_type != TYPE_0) {
@@ -347,7 +417,7 @@ setstate(arg_state)
347long 417long
348random() 418random()
349{ 419{
350 long i; 420 int32_t i;
351 421
352 if (rand_type == TYPE_0) 422 if (rand_type == TYPE_0)
353 i = state[0] = (state[0] * 1103515245 + 12345) & 0x7fffffff; 423 i = state[0] = (state[0] * 1103515245 + 12345) & 0x7fffffff;
@@ -360,5 +430,5 @@ random()
360 } else if (++rptr >= end_ptr) 430 } else if (++rptr >= end_ptr)
361 rptr = state; 431 rptr = state;
362 } 432 }
363 return(i); 433 return((long)i);
364} 434}
diff --git a/src/lib/libc/stdlib/realpath.3 b/src/lib/libc/stdlib/realpath.3
index 9d8b1ff2ce..56fbea9ede 100644
--- a/src/lib/libc/stdlib/realpath.3
+++ b/src/lib/libc/stdlib/realpath.3
@@ -32,10 +32,9 @@
32.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33.\" SUCH DAMAGE. 33.\" SUCH DAMAGE.
34.\" 34.\"
35.\" from: @(#)realpath.3 8.2 (Berkeley) 2/16/94 35.\" $OpenBSD: realpath.3,v 1.8 2001/04/23 15:30:25 aaron Exp $
36.\" $Id: realpath.3,v 1.1.1.1 1995/10/18 08:42:19 deraadt Exp $
37.\" 36.\"
38.Dd "February 16, 1994" 37.Dd February 16, 1994
39.Dt REALPATH 3 38.Dt REALPATH 3
40.Os 39.Os
41.Sh NAME 40.Sh NAME
@@ -57,8 +56,7 @@ and
57.Pa /../ 56.Pa /../
58in 57in
59.Fa pathname , 58.Fa pathname ,
60and copies the resulting absolute pathname into 59and copies the resulting absolute pathname into the memory referenced by
61the memory referenced by
62.Fa resolvedname . 60.Fa resolvedname .
63The 61The
64.Fa resolvedname 62.Fa resolvedname
@@ -68,7 +66,7 @@ refer to a buffer capable of storing at least
68.Dv MAXPATHLEN 66.Dv MAXPATHLEN
69characters. 67characters.
70.Pp 68.Pp
71The 69The
72.Fn realpath 70.Fn realpath
73function will resolve both absolute and relative paths 71function will resolve both absolute and relative paths
74and return the absolute pathname corresponding to 72and return the absolute pathname corresponding to
@@ -82,14 +80,14 @@ is called.
82The 80The
83.Fn realpath 81.Fn realpath
84function returns 82function returns
85.Fa resolved_name 83.Fa resolvedname
86on success. 84on success.
87If an error occurs, 85If an error occurs,
88.Fn realpath 86.Fn realpath
89returns 87returns
90.Dv NULL , 88.Dv NULL ,
91and 89and
92.Fa resolved_name 90.Fa resolvedname
93contains the pathname which caused the problem. 91contains the pathname which caused the problem.
94.Sh ERRORS 92.Sh ERRORS
95The function 93The function
@@ -102,7 +100,7 @@ for any of the errors specified for the library functions
102.Xr fchdir 2 , 100.Xr fchdir 2 ,
103.Xr lstat 2 , 101.Xr lstat 2 ,
104.Xr open 2 , 102.Xr open 2 ,
105.Xr readlink 2 103.Xr readlink 2 ,
106and 104and
107.Xr getcwd 3 . 105.Xr getcwd 3 .
108.Sh CAVEATS 106.Sh CAVEATS
@@ -114,10 +112,10 @@ The
114version always returns absolute pathnames, 112version always returns absolute pathnames,
115whereas the Solaris implementation will, 113whereas the Solaris implementation will,
116under certain circumstances, return a relative 114under certain circumstances, return a relative
117.Fa resolved_path 115.Fa resolvedname
118when given a relative 116when given a relative
119.Fa pathname . 117.Fa pathname .
120.Sh "SEE ALSO" 118.Sh SEE ALSO
121.Xr getcwd 3 119.Xr getcwd 3
122.Sh HISTORY 120.Sh HISTORY
123The 121The
diff --git a/src/lib/libc/stdlib/realpath.c b/src/lib/libc/stdlib/realpath.c
index e349b7e068..71063394d1 100644
--- a/src/lib/libc/stdlib/realpath.c
+++ b/src/lib/libc/stdlib/realpath.c
@@ -35,8 +35,7 @@
35 */ 35 */
36 36
37#if defined(LIBC_SCCS) && !defined(lint) 37#if defined(LIBC_SCCS) && !defined(lint)
38/*static char sccsid[] = "from: @(#)realpath.c 8.1 (Berkeley) 2/16/94";*/ 38static char *rcsid = "$OpenBSD: realpath.c,v 1.8 2003/04/04 22:47:43 hin Exp $";
39static char *rcsid = "$Id: realpath.c,v 1.1.1.1 1995/10/18 08:42:19 deraadt Exp $";
40#endif /* LIBC_SCCS and not lint */ 39#endif /* LIBC_SCCS and not lint */
41 40
42#include <sys/param.h> 41#include <sys/param.h>
@@ -63,13 +62,18 @@ realpath(path, resolved)
63 struct stat sb; 62 struct stat sb;
64 int fd, n, rootd, serrno; 63 int fd, n, rootd, serrno;
65 char *p, *q, wbuf[MAXPATHLEN]; 64 char *p, *q, wbuf[MAXPATHLEN];
65 int symlinks = 0;
66 66
67 /* Save the starting point. */ 67 /* Save the starting point. */
68 if ((fd = open(".", O_RDONLY)) < 0) { 68 if ((fd = open(".", O_RDONLY)) < 0) {
69 (void)strcpy(resolved, "."); 69 (void)strlcpy(resolved, ".", MAXPATHLEN);
70 return (NULL); 70 return (NULL);
71 } 71 }
72 72
73 /* Convert "." -> "" to optimize away a needless lstat() and chdir() */
74 if (path[0] == '.' && path[1] == '\0')
75 path = "";
76
73 /* 77 /*
74 * Find the dirname and basename from the path to be resolved. 78 * Find the dirname and basename from the path to be resolved.
75 * Change directory to the dirname component. 79 * Change directory to the dirname component.
@@ -78,8 +82,7 @@ realpath(path, resolved)
78 * if it is a directory, then change to that directory. 82 * if it is a directory, then change to that directory.
79 * get the current directory name and append the basename. 83 * get the current directory name and append the basename.
80 */ 84 */
81 (void)strncpy(resolved, path, MAXPATHLEN - 1); 85 strlcpy(resolved, path, MAXPATHLEN);
82 resolved[MAXPATHLEN - 1] = '\0';
83loop: 86loop:
84 q = strrchr(resolved, '/'); 87 q = strrchr(resolved, '/');
85 if (q != NULL) { 88 if (q != NULL) {
@@ -99,9 +102,13 @@ loop:
99 p = resolved; 102 p = resolved;
100 103
101 /* Deal with the last component. */ 104 /* Deal with the last component. */
102 if (lstat(p, &sb) == 0) { 105 if (*p != '\0' && lstat(p, &sb) == 0) {
103 if (S_ISLNK(sb.st_mode)) { 106 if (S_ISLNK(sb.st_mode)) {
104 n = readlink(p, resolved, MAXPATHLEN); 107 if (++symlinks > MAXSYMLINKS) {
108 errno = ELOOP;
109 goto err1;
110 }
111 n = readlink(p, resolved, MAXPATHLEN-1);
105 if (n < 0) 112 if (n < 0)
106 goto err1; 113 goto err1;
107 resolved[n] = '\0'; 114 resolved[n] = '\0';
@@ -118,7 +125,7 @@ loop:
118 * Save the last component name and get the full pathname of 125 * Save the last component name and get the full pathname of
119 * the current directory. 126 * the current directory.
120 */ 127 */
121 (void)strcpy(wbuf, p); 128 (void)strlcpy(wbuf, p, sizeof wbuf);
122 if (getcwd(resolved, MAXPATHLEN) == 0) 129 if (getcwd(resolved, MAXPATHLEN) == 0)
123 goto err1; 130 goto err1;
124 131
@@ -137,8 +144,8 @@ loop:
137 goto err1; 144 goto err1;
138 } 145 }
139 if (rootd == 0) 146 if (rootd == 0)
140 (void)strcat(resolved, "/"); 147 strlcat(resolved, "/", MAXPATHLEN);
141 (void)strcat(resolved, wbuf); 148 strlcat(resolved, wbuf, MAXPATHLEN);
142 } 149 }
143 150
144 /* Go back to where we came from. */ 151 /* Go back to where we came from. */
diff --git a/src/lib/libc/stdlib/remque.c b/src/lib/libc/stdlib/remque.c
new file mode 100644
index 0000000000..f4c5769a8c
--- /dev/null
+++ b/src/lib/libc/stdlib/remque.c
@@ -0,0 +1,48 @@
1/* $OpenBSD: remque.c,v 1.1 2003/05/08 23:26:30 millert Exp $ */
2
3/*
4 * Copyright (c) 1993 John Brezak
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#if defined(LIBC_SCCS) && !defined(lint)
32static char *rcsid = "$OpenBSD: remque.c,v 1.1 2003/05/08 23:26:30 millert Exp $";
33#endif /* LIBC_SCCS and not lint */
34
35#include <search.h>
36
37struct qelem {
38 struct qelem *q_forw;
39 struct qelem *q_back;
40};
41
42void
43remque(void *element)
44{
45 struct qelem *e = (struct qelem *) element;
46 e->q_forw->q_back = e->q_back;
47 e->q_back->q_forw = e->q_forw;
48}
diff --git a/src/lib/libc/stdlib/seed48.c b/src/lib/libc/stdlib/seed48.c
index e3d31901dd..c4dcd0ead8 100644
--- a/src/lib/libc/stdlib/seed48.c
+++ b/src/lib/libc/stdlib/seed48.c
@@ -11,6 +11,10 @@
11 * to anyone/anything when using this software. 11 * to anyone/anything when using this software.
12 */ 12 */
13 13
14#if defined(LIBC_SCCS) && !defined(lint)
15static char rcsid[] = "$OpenBSD: seed48.c,v 1.2 1996/08/19 08:33:48 tholo Exp $";
16#endif /* LIBC_SCCS and not lint */
17
14#include "rand48.h" 18#include "rand48.h"
15 19
16extern unsigned short __rand48_seed[3]; 20extern unsigned short __rand48_seed[3];
diff --git a/src/lib/libc/stdlib/setenv.c b/src/lib/libc/stdlib/setenv.c
index a36669888d..044f01b1c9 100644
--- a/src/lib/libc/stdlib/setenv.c
+++ b/src/lib/libc/stdlib/setenv.c
@@ -32,13 +32,14 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)setenv.c 5.6 (Berkeley) 6/4/91";*/ 35static char *rcsid = "$OpenBSD: setenv.c,v 1.5 2002/12/10 22:44:13 mickey Exp $";
36static char *rcsid = "$Id: setenv.c,v 1.1.1.1 1995/10/18 08:42:19 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
38 37
39#include <stdlib.h> 38#include <stdlib.h>
40#include <string.h> 39#include <string.h>
41 40
41char *__findenv(const char *name, int *offset);
42
42/* 43/*
43 * setenv -- 44 * setenv --
44 * Set the value of the environmental variable "name" to be 45 * Set the value of the environmental variable "name" to be
@@ -54,7 +55,6 @@ setenv(name, value, rewrite)
54 static int alloced; /* if allocated space before */ 55 static int alloced; /* if allocated space before */
55 register char *C; 56 register char *C;
56 int l_value, offset; 57 int l_value, offset;
57 char *__findenv();
58 58
59 if (*value == '=') /* no `=' in value */ 59 if (*value == '=') /* no `=' in value */
60 ++value; 60 ++value;
@@ -63,7 +63,8 @@ setenv(name, value, rewrite)
63 if (!rewrite) 63 if (!rewrite)
64 return (0); 64 return (0);
65 if (strlen(C) >= l_value) { /* old larger; copy over */ 65 if (strlen(C) >= l_value) { /* old larger; copy over */
66 while (*C++ = *value++); 66 while ((*C++ = *value++))
67 ;
67 return (0); 68 return (0);
68 } 69 }
69 } else { /* create new slot */ 70 } else { /* create new slot */
@@ -72,10 +73,11 @@ setenv(name, value, rewrite)
72 73
73 for (P = environ, cnt = 0; *P; ++P, ++cnt); 74 for (P = environ, cnt = 0; *P; ++P, ++cnt);
74 if (alloced) { /* just increase size */ 75 if (alloced) { /* just increase size */
75 environ = (char **)realloc((char *)environ, 76 P = (char **)realloc((void *)environ,
76 (size_t)(sizeof(char *) * (cnt + 2))); 77 (size_t)(sizeof(char *) * (cnt + 2)));
77 if (!environ) 78 if (!P)
78 return (-1); 79 return (-1);
80 environ = P;
79 } 81 }
80 else { /* get new space */ 82 else { /* get new space */
81 alloced = 1; /* copy old entries into it */ 83 alloced = 1; /* copy old entries into it */
@@ -95,7 +97,7 @@ setenv(name, value, rewrite)
95 return (-1); 97 return (-1);
96 for (C = environ[offset]; (*C = *name++) && *C != '='; ++C) 98 for (C = environ[offset]; (*C = *name++) && *C != '='; ++C)
97 ; 99 ;
98 for (*C++ = '='; *C++ = *value++; ) 100 for (*C++ = '='; (*C++ = *value++); )
99 ; 101 ;
100 return (0); 102 return (0);
101} 103}
diff --git a/src/lib/libc/stdlib/srand48.c b/src/lib/libc/stdlib/srand48.c
index daf733f93e..fcff8a172e 100644
--- a/src/lib/libc/stdlib/srand48.c
+++ b/src/lib/libc/stdlib/srand48.c
@@ -11,6 +11,10 @@
11 * to anyone/anything when using this software. 11 * to anyone/anything when using this software.
12 */ 12 */
13 13
14#if defined(LIBC_SCCS) && !defined(lint)
15static char rcsid[] = "$OpenBSD: srand48.c,v 1.2 1996/08/19 08:33:49 tholo Exp $";
16#endif /* LIBC_SCCS and not lint */
17
14#include "rand48.h" 18#include "rand48.h"
15 19
16extern unsigned short __rand48_seed[3]; 20extern unsigned short __rand48_seed[3];
diff --git a/src/lib/libc/stdlib/strtod.3 b/src/lib/libc/stdlib/strtod.3
index 0b7f973857..4e04f6738e 100644
--- a/src/lib/libc/stdlib/strtod.3
+++ b/src/lib/libc/stdlib/strtod.3
@@ -33,8 +33,7 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)strtod.3 5.3 (Berkeley) 6/29/91 36.\" $OpenBSD: strtod.3,v 1.7 2000/04/20 13:50:03 aaron Exp $
37.\" $Id: strtod.3,v 1.1.1.1 1995/10/18 08:42:19 deraadt Exp $
38.\" 37.\"
39.Dd June 29, 1991 38.Dd June 29, 1991
40.Dt STRTOD 3 39.Dt STRTOD 3
@@ -51,20 +50,25 @@ string to double
51.Sh DESCRIPTION 50.Sh DESCRIPTION
52The 51The
53.Fn strtod 52.Fn strtod
54function converts the initial portion of the string 53function converts the initial portion of the string pointed to by
55pointed to by
56.Fa nptr 54.Fa nptr
57to 55to
58.Em double 56.Li double
59representation. 57representation.
60.Pp 58.Pp
61The expected form of the string is an optional plus (``+'') or minus 59The expected form of the string is an optional plus
62sign (``-'') followed by a sequence of digits optionally containing 60.Pq Ql +
61or minus sign
62.Pq Ql -
63followed by a sequence of digits optionally containing
63a decimal-point character, optionally followed by an exponent. 64a decimal-point character, optionally followed by an exponent.
64An exponent consists of an ``E'' or ``e'', followed by an optional plus 65An exponent consists of an
65or minus sign, followed by a sequence of digits. 66.Sq E
67or
68.Sq e ,
69followed by an optional plus or minus sign, followed by a sequence of digits.
66.Pp 70.Pp
67Leading white-space characters in the string (as defined by the 71Leading whitespace characters in the string (as defined by the
68.Xr isspace 3 72.Xr isspace 3
69function) are skipped. 73function) are skipped.
70.Sh RETURN VALUES 74.Sh RETURN VALUES
@@ -88,18 +92,18 @@ is stored in the location referenced by
88If the correct value would cause overflow, plus or minus 92If the correct value would cause overflow, plus or minus
89.Dv HUGE_VAL 93.Dv HUGE_VAL
90is returned (according to the sign of the value), and 94is returned (according to the sign of the value), and
91.Dv ERANGE 95.Er ERANGE
92is stored in 96is stored in
93.Va errno . 97.Va errno .
94If the correct value would cause underflow, zero is 98If the correct value would cause underflow, zero is returned and
95returned and 99.Er ERANGE
96.Dv ERANGE 100is stored in
97is stored in
98.Va errno . 101.Va errno .
99.Sh ERRORS 102.Sh ERRORS
100.Bl -tag -width Er 103.Bl -tag -width Er
101.It Bq Er ERANGE 104.It Bq Er ERANGE
102Overflow or underflow occurred. 105Overflow or underflow occurred.
106.El
103.Sh SEE ALSO 107.Sh SEE ALSO
104.Xr atof 3 , 108.Xr atof 3 ,
105.Xr atoi 3 , 109.Xr atoi 3 ,
@@ -109,6 +113,5 @@ Overflow or underflow occurred.
109.Sh STANDARDS 113.Sh STANDARDS
110The 114The
111.Fn strtod 115.Fn strtod
112function 116function conforms to
113conforms to
114.St -ansiC . 117.St -ansiC .
diff --git a/src/lib/libc/stdlib/strtod.c b/src/lib/libc/stdlib/strtod.c
index b13fa128f5..17d26a1dc3 100644
--- a/src/lib/libc/stdlib/strtod.c
+++ b/src/lib/libc/stdlib/strtod.c
@@ -90,12 +90,13 @@
90 */ 90 */
91 91
92#if defined(LIBC_SCCS) && !defined(lint) 92#if defined(LIBC_SCCS) && !defined(lint)
93static char *rcsid = "$Id: strtod.c,v 1.1.1.1 1995/10/18 08:42:19 deraadt Exp $"; 93static char *rcsid = "$OpenBSD: strtod.c,v 1.16 2002/12/02 15:38:54 millert Exp $";
94#endif /* LIBC_SCCS and not lint */ 94#endif /* LIBC_SCCS and not lint */
95 95
96#if defined(__m68k__) || defined(__sparc__) || defined(__i386__) || \ 96#if defined(__m68k__) || defined(__sparc__) || defined(__i386__) || \
97 defined(__mips__) || defined(__ns32k__) || defined(__alpha__) 97 defined(__mips__) || defined(__ns32k__) || defined(__alpha__) || \
98#include <machine/endian.h> 98 defined(__powerpc__) || defined(__m88k__) || defined(__hppa__)
99#include <sys/types.h>
99#if BYTE_ORDER == BIG_ENDIAN 100#if BYTE_ORDER == BIG_ENDIAN
100#define IEEE_BIG_ENDIAN 101#define IEEE_BIG_ENDIAN
101#else 102#else
@@ -103,7 +104,16 @@ static char *rcsid = "$Id: strtod.c,v 1.1.1.1 1995/10/18 08:42:19 deraadt Exp $"
103#endif 104#endif
104#endif 105#endif
105 106
106#ifdef vax 107#ifdef __arm32__
108/*
109 * Although the CPU is little endian the FP has different
110 * byte and word endianness. The byte order is still little endian
111 * but the word order is big endian.
112 */
113#define IEEE_BIG_ENDIAN
114#endif
115
116#ifdef __vax__
107#define VAX 117#define VAX
108#endif 118#endif
109 119
@@ -143,7 +153,6 @@ extern void *MALLOC(size_t);
143#include "errno.h" 153#include "errno.h"
144 154
145#ifdef Bad_float_h 155#ifdef Bad_float_h
146#undef __STDC__
147#ifdef IEEE_BIG_ENDIAN 156#ifdef IEEE_BIG_ENDIAN
148#define IEEE_ARITHMETIC 157#define IEEE_ARITHMETIC
149#endif 158#endif
@@ -212,19 +221,24 @@ Exactly one of IEEE_LITTLE_ENDIAN IEEE_BIG_ENDIAN, VAX, or
212IBM should be defined. 221IBM should be defined.
213#endif 222#endif
214 223
224typedef union {
225 double d;
226 ULong ul[2];
227} _double;
228#define value(x) ((x).d)
215#ifdef IEEE_LITTLE_ENDIAN 229#ifdef IEEE_LITTLE_ENDIAN
216#define word0(x) ((ULong *)&x)[1] 230#define word0(x) ((x).ul[1])
217#define word1(x) ((ULong *)&x)[0] 231#define word1(x) ((x).ul[0])
218#else 232#else
219#define word0(x) ((ULong *)&x)[0] 233#define word0(x) ((x).ul[0])
220#define word1(x) ((ULong *)&x)[1] 234#define word1(x) ((x).ul[1])
221#endif 235#endif
222 236
223/* The following definition of Storeinc is appropriate for MIPS processors. 237/* The following definition of Storeinc is appropriate for MIPS processors.
224 * An alternative that might be better on some machines is 238 * An alternative that might be better on some machines is
225 * #define Storeinc(a,b,c) (*a++ = b << 16 | c & 0xffff) 239 * #define Storeinc(a,b,c) (*a++ = b << 16 | c & 0xffff)
226 */ 240 */
227#if defined(IEEE_LITTLE_ENDIAN) + defined(VAX) 241#if defined(IEEE_LITTLE_ENDIAN) + defined(VAX) + defined(__arm32__)
228#define Storeinc(a,b,c) (((unsigned short *)a)[1] = (unsigned short)b, \ 242#define Storeinc(a,b,c) (((unsigned short *)a)[1] = (unsigned short)b, \
229((unsigned short *)a)[0] = (unsigned short)c, a++) 243((unsigned short *)a)[0] = (unsigned short)c, a++)
230#else 244#else
@@ -380,7 +394,7 @@ Balloc
380 int x; 394 int x;
381 Bigint *rv; 395 Bigint *rv;
382 396
383 if (rv = freelist[k]) { 397 if ((rv = freelist[k])) {
384 freelist[k] = rv->next; 398 freelist[k] = rv->next;
385 } 399 }
386 else { 400 else {
@@ -628,7 +642,7 @@ mult
628 xc0 = c->x; 642 xc0 = c->x;
629#ifdef Pack_32 643#ifdef Pack_32
630 for(; xb < xbe; xb++, xc0++) { 644 for(; xb < xbe; xb++, xc0++) {
631 if (y = *xb & 0xffff) { 645 if ((y = *xb & 0xffff)) {
632 x = xa; 646 x = xa;
633 xc = xc0; 647 xc = xc0;
634 carry = 0; 648 carry = 0;
@@ -642,7 +656,7 @@ mult
642 while(x < xae); 656 while(x < xae);
643 *xc = carry; 657 *xc = carry;
644 } 658 }
645 if (y = *xb >> 16) { 659 if ((y = *xb >> 16)) {
646 x = xa; 660 x = xa;
647 xc = xc0; 661 xc = xc0;
648 carry = 0; 662 carry = 0;
@@ -693,7 +707,7 @@ pow5mult
693 int i; 707 int i;
694 static int p05[3] = { 5, 25, 125 }; 708 static int p05[3] = { 5, 25, 125 };
695 709
696 if (i = k & 3) 710 if ((i = k & 3))
697 b = multadd(b, p05[i-1], 0); 711 b = multadd(b, p05[i-1], 0);
698 712
699 if (!(k >>= 2)) 713 if (!(k >>= 2))
@@ -756,7 +770,7 @@ lshift
756 z = *x++ >> k1; 770 z = *x++ >> k1;
757 } 771 }
758 while(x < xe); 772 while(x < xe);
759 if (*x1 = z) 773 if ((*x1 = z))
760 ++n1; 774 ++n1;
761 } 775 }
762#else 776#else
@@ -899,14 +913,16 @@ diff
899 static double 913 static double
900ulp 914ulp
901#ifdef KR_headers 915#ifdef KR_headers
902 (x) double x; 916 (_x) double _x;
903#else 917#else
904 (double x) 918 (double _x)
905#endif 919#endif
906{ 920{
921 _double x;
907 register Long L; 922 register Long L;
908 double a; 923 _double a;
909 924
925 value(x) = _x;
910 L = (word0(x) & Exp_mask) - (P-1)*Exp_msk1; 926 L = (word0(x) & Exp_mask) - (P-1)*Exp_msk1;
911#ifndef Sudden_Underflow 927#ifndef Sudden_Underflow
912 if (L > 0) { 928 if (L > 0) {
@@ -931,7 +947,7 @@ ulp
931 } 947 }
932 } 948 }
933#endif 949#endif
934 return a; 950 return value(a);
935 } 951 }
936 952
937 static double 953 static double
@@ -944,7 +960,7 @@ b2d
944{ 960{
945 ULong *xa, *xa0, w, y, z; 961 ULong *xa, *xa0, w, y, z;
946 int k; 962 int k;
947 double d; 963 _double d;
948#ifdef VAX 964#ifdef VAX
949 ULong d0, d1; 965 ULong d0, d1;
950#else 966#else
@@ -1001,22 +1017,27 @@ b2d
1001#undef d0 1017#undef d0
1002#undef d1 1018#undef d1
1003#endif 1019#endif
1004 return d; 1020 return value(d);
1005 } 1021 }
1006 1022
1007 static Bigint * 1023 static Bigint *
1008d2b 1024d2b
1009#ifdef KR_headers 1025#ifdef KR_headers
1010 (d, e, bits) double d; int *e, *bits; 1026 (_d, e, bits) double d; int *e, *bits;
1011#else 1027#else
1012 (double d, int *e, int *bits) 1028 (double _d, int *e, int *bits)
1013#endif 1029#endif
1014{ 1030{
1015 Bigint *b; 1031 Bigint *b;
1016 int de, i, k; 1032 int de, i, k;
1017 ULong *x, y, z; 1033 ULong *x, y, z;
1034 _double d;
1018#ifdef VAX 1035#ifdef VAX
1019 ULong d0, d1; 1036 ULong d0, d1;
1037#endif
1038
1039 value(d) = _d;
1040#ifdef VAX
1020 d0 = word0(d) >> 16 | word0(d) << 16; 1041 d0 = word0(d) >> 16 | word0(d) << 16;
1021 d1 = word1(d) >> 16 | word1(d) << 16; 1042 d1 = word1(d) >> 16 | word1(d) << 16;
1022#else 1043#else
@@ -1141,11 +1162,11 @@ ratio
1141 (Bigint *a, Bigint *b) 1162 (Bigint *a, Bigint *b)
1142#endif 1163#endif
1143{ 1164{
1144 double da, db; 1165 _double da, db;
1145 int k, ka, kb; 1166 int k, ka, kb;
1146 1167
1147 da = b2d(a, &ka); 1168 value(da) = b2d(a, &ka);
1148 db = b2d(b, &kb); 1169 value(db) = b2d(b, &kb);
1149#ifdef Pack_32 1170#ifdef Pack_32
1150 k = ka - kb + 32*(a->wds - b->wds); 1171 k = ka - kb + 32*(a->wds - b->wds);
1151#else 1172#else
@@ -1171,7 +1192,7 @@ ratio
1171 word0(db) += k*Exp_msk1; 1192 word0(db) += k*Exp_msk1;
1172 } 1193 }
1173#endif 1194#endif
1174 return da / db; 1195 return value(da) / value(db);
1175 } 1196 }
1176 1197
1177static CONST double 1198static CONST double
@@ -1211,7 +1232,8 @@ strtod
1211 int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dsign, 1232 int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dsign,
1212 e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign; 1233 e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign;
1213 CONST char *s, *s0, *s1; 1234 CONST char *s, *s0, *s1;
1214 double aadj, aadj1, adj, rv, rv0; 1235 double aadj, aadj1, adj;
1236 _double rv, rv0;
1215 Long L; 1237 Long L;
1216 ULong y, z; 1238 ULong y, z;
1217 Bigint *bb, *bb1, *bd, *bd0, *bs, *delta; 1239 Bigint *bb, *bb1, *bd, *bd0, *bs, *delta;
@@ -1223,10 +1245,10 @@ strtod
1223#endif 1245#endif
1224 1246
1225 sign = nz0 = nz = 0; 1247 sign = nz0 = nz = 0;
1226 rv = 0.; 1248 value(rv) = 0.;
1227 1249
1228 1250
1229 for(s = s00; isspace(*s); s++) 1251 for(s = s00; isspace((unsigned char) *s); s++)
1230 ; 1252 ;
1231 1253
1232 if (*s == '-') { 1254 if (*s == '-') {
@@ -1340,9 +1362,9 @@ strtod
1340 if (!nd0) 1362 if (!nd0)
1341 nd0 = nd; 1363 nd0 = nd;
1342 k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1; 1364 k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;
1343 rv = y; 1365 value(rv) = y;
1344 if (k > 9) 1366 if (k > 9)
1345 rv = tens[k - 9] * rv + z; 1367 value(rv) = tens[k - 9] * value(rv) + z;
1346 bd0 = 0; 1368 bd0 = 0;
1347 if (nd <= DBL_DIG 1369 if (nd <= DBL_DIG
1348#ifndef RND_PRODQUOT 1370#ifndef RND_PRODQUOT
@@ -1356,7 +1378,8 @@ strtod
1356#ifdef VAX 1378#ifdef VAX
1357 goto vax_ovfl_check; 1379 goto vax_ovfl_check;
1358#else 1380#else
1359 /* rv = */ rounded_product(rv, tens[e]); 1381 /* value(rv) = */ rounded_product(value(rv),
1382 tens[e]);
1360 goto ret; 1383 goto ret;
1361#endif 1384#endif
1362 } 1385 }
@@ -1366,27 +1389,30 @@ strtod
1366 * this for larger i values. 1389 * this for larger i values.
1367 */ 1390 */
1368 e -= i; 1391 e -= i;
1369 rv *= tens[i]; 1392 value(rv) *= tens[i];
1370#ifdef VAX 1393#ifdef VAX
1371 /* VAX exponent range is so narrow we must 1394 /* VAX exponent range is so narrow we must
1372 * worry about overflow here... 1395 * worry about overflow here...
1373 */ 1396 */
1374 vax_ovfl_check: 1397 vax_ovfl_check:
1375 word0(rv) -= P*Exp_msk1; 1398 word0(rv) -= P*Exp_msk1;
1376 /* rv = */ rounded_product(rv, tens[e]); 1399 /* value(rv) = */ rounded_product(value(rv),
1400 tens[e]);
1377 if ((word0(rv) & Exp_mask) 1401 if ((word0(rv) & Exp_mask)
1378 > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) 1402 > Exp_msk1*(DBL_MAX_EXP+Bias-1-P))
1379 goto ovfl; 1403 goto ovfl;
1380 word0(rv) += P*Exp_msk1; 1404 word0(rv) += P*Exp_msk1;
1381#else 1405#else
1382 /* rv = */ rounded_product(rv, tens[e]); 1406 /* value(rv) = */ rounded_product(value(rv),
1407 tens[e]);
1383#endif 1408#endif
1384 goto ret; 1409 goto ret;
1385 } 1410 }
1386 } 1411 }
1387#ifndef Inaccurate_Divide 1412#ifndef Inaccurate_Divide
1388 else if (e >= -Ten_pmax) { 1413 else if (e >= -Ten_pmax) {
1389 /* rv = */ rounded_quotient(rv, tens[-e]); 1414 /* value(rv) = */ rounded_quotient(value(rv),
1415 tens[-e]);
1390 goto ret; 1416 goto ret;
1391 } 1417 }
1392#endif 1418#endif
@@ -1397,13 +1423,13 @@ strtod
1397 1423
1398 if (e1 > 0) { 1424 if (e1 > 0) {
1399 if (i = e1 & 15) 1425 if (i = e1 & 15)
1400 rv *= tens[i]; 1426 value(rv) *= tens[i];
1401 if (e1 &= ~15) { 1427 if (e1 &= ~15) {
1402 if (e1 > DBL_MAX_10_EXP) { 1428 if (e1 > DBL_MAX_10_EXP) {
1403 ovfl: 1429 ovfl:
1404 errno = ERANGE; 1430 errno = ERANGE;
1405#ifdef __STDC__ 1431#ifndef Bad_float_h
1406 rv = HUGE_VAL; 1432 value(rv) = HUGE_VAL;
1407#else 1433#else
1408 /* Can't trust HUGE_VAL */ 1434 /* Can't trust HUGE_VAL */
1409#ifdef IEEE_Arith 1435#ifdef IEEE_Arith
@@ -1421,10 +1447,10 @@ strtod
1421 if (e1 >>= 4) { 1447 if (e1 >>= 4) {
1422 for(j = 0; e1 > 1; j++, e1 >>= 1) 1448 for(j = 0; e1 > 1; j++, e1 >>= 1)
1423 if (e1 & 1) 1449 if (e1 & 1)
1424 rv *= bigtens[j]; 1450 value(rv) *= bigtens[j];
1425 /* The last multiplication could overflow. */ 1451 /* The last multiplication could overflow. */
1426 word0(rv) -= P*Exp_msk1; 1452 word0(rv) -= P*Exp_msk1;
1427 rv *= bigtens[j]; 1453 value(rv) *= bigtens[j];
1428 if ((z = word0(rv) & Exp_mask) 1454 if ((z = word0(rv) & Exp_mask)
1429 > Exp_msk1*(DBL_MAX_EXP+Bias-P)) 1455 > Exp_msk1*(DBL_MAX_EXP+Bias-P))
1430 goto ovfl; 1456 goto ovfl;
@@ -1443,23 +1469,23 @@ strtod
1443 else if (e1 < 0) { 1469 else if (e1 < 0) {
1444 e1 = -e1; 1470 e1 = -e1;
1445 if (i = e1 & 15) 1471 if (i = e1 & 15)
1446 rv /= tens[i]; 1472 value(rv) /= tens[i];
1447 if (e1 &= ~15) { 1473 if (e1 &= ~15) {
1448 e1 >>= 4; 1474 e1 >>= 4;
1449 if (e1 >= 1 << n_bigtens) 1475 if (e1 >= 1 << n_bigtens)
1450 goto undfl; 1476 goto undfl;
1451 for(j = 0; e1 > 1; j++, e1 >>= 1) 1477 for(j = 0; e1 > 1; j++, e1 >>= 1)
1452 if (e1 & 1) 1478 if (e1 & 1)
1453 rv *= tinytens[j]; 1479 value(rv) *= tinytens[j];
1454 /* The last multiplication could underflow. */ 1480 /* The last multiplication could underflow. */
1455 rv0 = rv; 1481 value(rv0) = value(rv);
1456 rv *= tinytens[j]; 1482 value(rv) *= tinytens[j];
1457 if (!rv) { 1483 if (!value(rv)) {
1458 rv = 2.*rv0; 1484 value(rv) = 2.*value(rv0);
1459 rv *= tinytens[j]; 1485 value(rv) *= tinytens[j];
1460 if (!rv) { 1486 if (!value(rv)) {
1461 undfl: 1487 undfl:
1462 rv = 0.; 1488 value(rv) = 0.;
1463 errno = ERANGE; 1489 errno = ERANGE;
1464 if (bd0) 1490 if (bd0)
1465 goto retfree; 1491 goto retfree;
@@ -1483,7 +1509,7 @@ strtod
1483 for(;;) { 1509 for(;;) {
1484 bd = Balloc(bd0->k); 1510 bd = Balloc(bd0->k);
1485 Bcopy(bd, bd0); 1511 Bcopy(bd, bd0);
1486 bb = d2b(rv, &bbe, &bbbits); /* rv = bb * 2^bbe */ 1512 bb = d2b(value(rv), &bbe, &bbbits); /* rv = bb * 2^bbe */
1487 bs = i2b(1); 1513 bs = i2b(1);
1488 1514
1489 if (e >= 0) { 1515 if (e >= 0) {
@@ -1595,12 +1621,12 @@ strtod
1595 break; 1621 break;
1596#endif 1622#endif
1597 if (dsign) 1623 if (dsign)
1598 rv += ulp(rv); 1624 value(rv) += ulp(value(rv));
1599#ifndef ROUND_BIASED 1625#ifndef ROUND_BIASED
1600 else { 1626 else {
1601 rv -= ulp(rv); 1627 value(rv) -= ulp(value(rv));
1602#ifndef Sudden_Underflow 1628#ifndef Sudden_Underflow
1603 if (!rv) 1629 if (!value(rv))
1604 goto undfl; 1630 goto undfl;
1605#endif 1631#endif
1606 } 1632 }
@@ -1651,10 +1677,10 @@ strtod
1651 /* Check for overflow */ 1677 /* Check for overflow */
1652 1678
1653 if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) { 1679 if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) {
1654 rv0 = rv; 1680 value(rv0) = value(rv);
1655 word0(rv) -= P*Exp_msk1; 1681 word0(rv) -= P*Exp_msk1;
1656 adj = aadj1 * ulp(rv); 1682 adj = aadj1 * ulp(value(rv));
1657 rv += adj; 1683 value(rv) += adj;
1658 if ((word0(rv) & Exp_mask) >= 1684 if ((word0(rv) & Exp_mask) >=
1659 Exp_msk1*(DBL_MAX_EXP+Bias-P)) { 1685 Exp_msk1*(DBL_MAX_EXP+Bias-P)) {
1660 if (word0(rv0) == Big0 && word1(rv0) == Big1) 1686 if (word0(rv0) == Big0 && word1(rv0) == Big1)
@@ -1669,10 +1695,10 @@ strtod
1669 else { 1695 else {
1670#ifdef Sudden_Underflow 1696#ifdef Sudden_Underflow
1671 if ((word0(rv) & Exp_mask) <= P*Exp_msk1) { 1697 if ((word0(rv) & Exp_mask) <= P*Exp_msk1) {
1672 rv0 = rv; 1698 value(rv0) = value(rv);
1673 word0(rv) += P*Exp_msk1; 1699 word0(rv) += P*Exp_msk1;
1674 adj = aadj1 * ulp(rv); 1700 adj = aadj1 * ulp(value(rv));
1675 rv += adj; 1701 value(rv) += adj;
1676#ifdef IBM 1702#ifdef IBM
1677 if ((word0(rv) & Exp_mask) < P*Exp_msk1) 1703 if ((word0(rv) & Exp_mask) < P*Exp_msk1)
1678#else 1704#else
@@ -1690,8 +1716,8 @@ strtod
1690 word0(rv) -= P*Exp_msk1; 1716 word0(rv) -= P*Exp_msk1;
1691 } 1717 }
1692 else { 1718 else {
1693 adj = aadj1 * ulp(rv); 1719 adj = aadj1 * ulp(value(rv));
1694 rv += adj; 1720 value(rv) += adj;
1695 } 1721 }
1696#else 1722#else
1697 /* Compute adj so that the IEEE rounding rules will 1723 /* Compute adj so that the IEEE rounding rules will
@@ -1706,8 +1732,8 @@ strtod
1706 if (!dsign) 1732 if (!dsign)
1707 aadj1 = -aadj1; 1733 aadj1 = -aadj1;
1708 } 1734 }
1709 adj = aadj1 * ulp(rv); 1735 adj = aadj1 * ulp(value(rv));
1710 rv += adj; 1736 value(rv) += adj;
1711#endif 1737#endif
1712 } 1738 }
1713 z = word0(rv) & Exp_mask; 1739 z = word0(rv) & Exp_mask;
@@ -1738,7 +1764,7 @@ strtod
1738 ret: 1764 ret:
1739 if (se) 1765 if (se)
1740 *se = (char *)s; 1766 *se = (char *)s;
1741 return sign ? -rv : rv; 1767 return sign ? -value(rv) : value(rv);
1742 } 1768 }
1743 1769
1744 static int 1770 static int
@@ -1884,10 +1910,10 @@ quorem
1884 char * 1910 char *
1885__dtoa 1911__dtoa
1886#ifdef KR_headers 1912#ifdef KR_headers
1887 (d, mode, ndigits, decpt, sign, rve) 1913 (_d, mode, ndigits, decpt, sign, rve)
1888 double d; int mode, ndigits, *decpt, *sign; char **rve; 1914 double _d; int mode, ndigits, *decpt, *sign; char **rve;
1889#else 1915#else
1890 (double d, int mode, int ndigits, int *decpt, int *sign, char **rve) 1916 (double _d, int mode, int ndigits, int *decpt, int *sign, char **rve)
1891#endif 1917#endif
1892{ 1918{
1893 /* Arguments ndigits, decpt, sign are similar to those 1919 /* Arguments ndigits, decpt, sign are similar to those
@@ -1933,11 +1959,13 @@ __dtoa
1933 ULong x; 1959 ULong x;
1934#endif 1960#endif
1935 Bigint *b, *b1, *delta, *mlo, *mhi, *S; 1961 Bigint *b, *b1, *delta, *mlo, *mhi, *S;
1936 double d2, ds, eps; 1962 double ds;
1937 char *s, *s0; 1963 char *s, *s0;
1938 static Bigint *result; 1964 static Bigint *result;
1939 static int result_k; 1965 static int result_k;
1966 _double d, d2, eps;
1940 1967
1968 value(d) = _d;
1941 if (result) { 1969 if (result) {
1942 result->k = result_k; 1970 result->k = result_k;
1943 result->maxwds = 1 << result_k; 1971 result->maxwds = 1 << result_k;
@@ -1964,7 +1992,7 @@ __dtoa
1964 *decpt = 9999; 1992 *decpt = 9999;
1965 s = 1993 s =
1966#ifdef IEEE_Arith 1994#ifdef IEEE_Arith
1967 !word1(d) && !(word0(d) & 0xfffff) ? "Infinity" : 1995 !word1(d) && !(word0(d) & 0xfffff) ? ndigits < 8 ? "Inf" : "Infinity" :
1968#endif 1996#endif
1969 "NaN"; 1997 "NaN";
1970 if (rve) 1998 if (rve)
@@ -1977,9 +2005,9 @@ __dtoa
1977 } 2005 }
1978#endif 2006#endif
1979#ifdef IBM 2007#ifdef IBM
1980 d += 0; /* normalize */ 2008 value(d) += 0; /* normalize */
1981#endif 2009#endif
1982 if (!d) { 2010 if (!value(d)) {
1983 *decpt = 1; 2011 *decpt = 1;
1984 s = "0"; 2012 s = "0";
1985 if (rve) 2013 if (rve)
@@ -1987,18 +2015,18 @@ __dtoa
1987 return s; 2015 return s;
1988 } 2016 }
1989 2017
1990 b = d2b(d, &be, &bbits); 2018 b = d2b(value(d), &be, &bbits);
1991#ifdef Sudden_Underflow 2019#ifdef Sudden_Underflow
1992 i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1)); 2020 i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1));
1993#else 2021#else
1994 if (i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1))) { 2022 if (i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1))) {
1995#endif 2023#endif
1996 d2 = d; 2024 value(d2) = value(d);
1997 word0(d2) &= Frac_mask1; 2025 word0(d2) &= Frac_mask1;
1998 word0(d2) |= Exp_11; 2026 word0(d2) |= Exp_11;
1999#ifdef IBM 2027#ifdef IBM
2000 if (j = 11 - hi0bits(word0(d2) & Frac_mask)) 2028 if (j = 11 - hi0bits(word0(d2) & Frac_mask))
2001 d2 /= 1 << j; 2029 value(d2) /= 1 << j;
2002#endif 2030#endif
2003 2031
2004 /* log(x) ~=~ log(1.5) + (x-1.5)/1.5 2032 /* log(x) ~=~ log(1.5) + (x-1.5)/1.5
@@ -2037,19 +2065,20 @@ __dtoa
2037 i = bbits + be + (Bias + (P-1) - 1); 2065 i = bbits + be + (Bias + (P-1) - 1);
2038 x = i > 32 ? word0(d) << 64 - i | word1(d) >> i - 32 2066 x = i > 32 ? word0(d) << 64 - i | word1(d) >> i - 32
2039 : word1(d) << 32 - i; 2067 : word1(d) << 32 - i;
2040 d2 = x; 2068 value(d2) = x;
2041 word0(d2) -= 31*Exp_msk1; /* adjust exponent */ 2069 word0(d2) -= 31*Exp_msk1; /* adjust exponent */
2042 i -= (Bias + (P-1) - 1) + 1; 2070 i -= (Bias + (P-1) - 1) + 1;
2043 denorm = 1; 2071 denorm = 1;
2044 } 2072 }
2045#endif 2073#endif
2046 ds = (d2-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981; 2074 ds = (value(d2)-1.5)*0.289529654602168 + 0.1760912590558 +
2075 i*0.301029995663981;
2047 k = (int)ds; 2076 k = (int)ds;
2048 if (ds < 0. && ds != k) 2077 if (ds < 0. && ds != k)
2049 k--; /* want k = floor(ds) */ 2078 k--; /* want k = floor(ds) */
2050 k_check = 1; 2079 k_check = 1;
2051 if (k >= 0 && k <= Ten_pmax) { 2080 if (k >= 0 && k <= Ten_pmax) {
2052 if (d < tens[k]) 2081 if (value(d) < tens[k])
2053 k--; 2082 k--;
2054 k_check = 0; 2083 k_check = 0;
2055 } 2084 }
@@ -2116,7 +2145,7 @@ __dtoa
2116 /* Try to get by with floating-point arithmetic. */ 2145 /* Try to get by with floating-point arithmetic. */
2117 2146
2118 i = 0; 2147 i = 0;
2119 d2 = d; 2148 value(d2) = value(d);
2120 k0 = k; 2149 k0 = k;
2121 ilim0 = ilim; 2150 ilim0 = ilim;
2122 ieps = 2; /* conservative */ 2151 ieps = 2; /* conservative */
@@ -2126,7 +2155,7 @@ __dtoa
2126 if (j & Bletch) { 2155 if (j & Bletch) {
2127 /* prevent overflows */ 2156 /* prevent overflows */
2128 j &= Bletch - 1; 2157 j &= Bletch - 1;
2129 d /= bigtens[n_bigtens-1]; 2158 value(d) /= bigtens[n_bigtens-1];
2130 ieps++; 2159 ieps++;
2131 } 2160 }
2132 for(; j; j >>= 1, i++) 2161 for(; j; j >>= 1, i++)
@@ -2134,32 +2163,32 @@ __dtoa
2134 ieps++; 2163 ieps++;
2135 ds *= bigtens[i]; 2164 ds *= bigtens[i];
2136 } 2165 }
2137 d /= ds; 2166 value(d) /= ds;
2138 } 2167 }
2139 else if (j1 = -k) { 2168 else if (j1 = -k) {
2140 d *= tens[j1 & 0xf]; 2169 value(d) *= tens[j1 & 0xf];
2141 for(j = j1 >> 4; j; j >>= 1, i++) 2170 for(j = j1 >> 4; j; j >>= 1, i++)
2142 if (j & 1) { 2171 if (j & 1) {
2143 ieps++; 2172 ieps++;
2144 d *= bigtens[i]; 2173 value(d) *= bigtens[i];
2145 } 2174 }
2146 } 2175 }
2147 if (k_check && d < 1. && ilim > 0) { 2176 if (k_check && value(d) < 1. && ilim > 0) {
2148 if (ilim1 <= 0) 2177 if (ilim1 <= 0)
2149 goto fast_failed; 2178 goto fast_failed;
2150 ilim = ilim1; 2179 ilim = ilim1;
2151 k--; 2180 k--;
2152 d *= 10.; 2181 value(d) *= 10.;
2153 ieps++; 2182 ieps++;
2154 } 2183 }
2155 eps = ieps*d + 7.; 2184 value(eps) = ieps*value(d) + 7.;
2156 word0(eps) -= (P-1)*Exp_msk1; 2185 word0(eps) -= (P-1)*Exp_msk1;
2157 if (ilim == 0) { 2186 if (ilim == 0) {
2158 S = mhi = 0; 2187 S = mhi = 0;
2159 d -= 5.; 2188 value(d) -= 5.;
2160 if (d > eps) 2189 if (value(d) > value(eps))
2161 goto one_digit; 2190 goto one_digit;
2162 if (d < -eps) 2191 if (value(d) < -value(eps))
2163 goto no_digits; 2192 goto no_digits;
2164 goto fast_failed; 2193 goto fast_failed;
2165 } 2194 }
@@ -2168,33 +2197,33 @@ __dtoa
2168 /* Use Steele & White method of only 2197 /* Use Steele & White method of only
2169 * generating digits needed. 2198 * generating digits needed.
2170 */ 2199 */
2171 eps = 0.5/tens[ilim-1] - eps; 2200 value(eps) = 0.5/tens[ilim-1] - value(eps);
2172 for(i = 0;;) { 2201 for(i = 0;;) {
2173 L = d; 2202 L = value(d);
2174 d -= L; 2203 value(d) -= L;
2175 *s++ = '0' + (int)L; 2204 *s++ = '0' + (int)L;
2176 if (d < eps) 2205 if (value(d) < value(eps))
2177 goto ret1; 2206 goto ret1;
2178 if (1. - d < eps) 2207 if (1. - value(d) < value(eps))
2179 goto bump_up; 2208 goto bump_up;
2180 if (++i >= ilim) 2209 if (++i >= ilim)
2181 break; 2210 break;
2182 eps *= 10.; 2211 value(eps) *= 10.;
2183 d *= 10.; 2212 value(d) *= 10.;
2184 } 2213 }
2185 } 2214 }
2186 else { 2215 else {
2187#endif 2216#endif
2188 /* Generate ilim digits, then fix them up. */ 2217 /* Generate ilim digits, then fix them up. */
2189 eps *= tens[ilim-1]; 2218 value(eps) *= tens[ilim-1];
2190 for(i = 1;; i++, d *= 10.) { 2219 for(i = 1;; i++, value(d) *= 10.) {
2191 L = d; 2220 L = value(d);
2192 d -= L; 2221 value(d) -= L;
2193 *s++ = '0' + (int)L; 2222 *s++ = '0' + (int)L;
2194 if (i == ilim) { 2223 if (i == ilim) {
2195 if (d > 0.5 + eps) 2224 if (value(d) > 0.5 + value(eps))
2196 goto bump_up; 2225 goto bump_up;
2197 else if (d < 0.5 - eps) { 2226 else if (value(d) < 0.5 - value(eps)) {
2198 while(*--s == '0'); 2227 while(*--s == '0');
2199 s++; 2228 s++;
2200 goto ret1; 2229 goto ret1;
@@ -2207,7 +2236,7 @@ __dtoa
2207#endif 2236#endif
2208 fast_failed: 2237 fast_failed:
2209 s = s0; 2238 s = s0;
2210 d = d2; 2239 value(d) = value(d2);
2211 k = k0; 2240 k = k0;
2212 ilim = ilim0; 2241 ilim = ilim0;
2213 } 2242 }
@@ -2219,24 +2248,24 @@ __dtoa
2219 ds = tens[k]; 2248 ds = tens[k];
2220 if (ndigits < 0 && ilim <= 0) { 2249 if (ndigits < 0 && ilim <= 0) {
2221 S = mhi = 0; 2250 S = mhi = 0;
2222 if (ilim < 0 || d <= 5*ds) 2251 if (ilim < 0 || value(d) <= 5*ds)
2223 goto no_digits; 2252 goto no_digits;
2224 goto one_digit; 2253 goto one_digit;
2225 } 2254 }
2226 for(i = 1;; i++) { 2255 for(i = 1;; i++) {
2227 L = d / ds; 2256 L = value(d) / ds;
2228 d -= L*ds; 2257 value(d) -= L*ds;
2229#ifdef Check_FLT_ROUNDS 2258#ifdef Check_FLT_ROUNDS
2230 /* If FLT_ROUNDS == 2, L will usually be high by 1 */ 2259 /* If FLT_ROUNDS == 2, L will usually be high by 1 */
2231 if (d < 0) { 2260 if (value(d) < 0) {
2232 L--; 2261 L--;
2233 d += ds; 2262 value(d) += ds;
2234 } 2263 }
2235#endif 2264#endif
2236 *s++ = '0' + (int)L; 2265 *s++ = '0' + (int)L;
2237 if (i == ilim) { 2266 if (i == ilim) {
2238 d += d; 2267 value(d) += value(d);
2239 if (d > ds || d == ds && L & 1) { 2268 if (value(d) > ds || value(d) == ds && L & 1) {
2240 bump_up: 2269 bump_up:
2241 while(*--s == '9') 2270 while(*--s == '9')
2242 if (s == s0) { 2271 if (s == s0) {
@@ -2248,7 +2277,7 @@ __dtoa
2248 } 2277 }
2249 break; 2278 break;
2250 } 2279 }
2251 if (!(d *= 10.)) 2280 if (!(value(d) *= 10.))
2252 break; 2281 break;
2253 } 2282 }
2254 goto ret1; 2283 goto ret1;
diff --git a/src/lib/libc/stdlib/strtol.3 b/src/lib/libc/stdlib/strtol.3
index 808ba90165..b37f2cd725 100644
--- a/src/lib/libc/stdlib/strtol.3
+++ b/src/lib/libc/stdlib/strtol.3
@@ -33,49 +33,57 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)strtol.3 5.4 (Berkeley) 6/25/92 36.\" $OpenBSD: strtol.3,v 1.12 2003/05/10 06:48:30 jmc Exp $
37.\" $Id: strtol.3,v 1.1.1.1 1995/10/18 08:42:19 deraadt Exp $
38.\" 37.\"
39.Dd June 25, 1992 38.Dd June 25, 1992
40.Dt STRTOL 3 39.Dt STRTOL 3
41.Os 40.Os
42.Sh NAME 41.Sh NAME
43.Nm strtol, strtoq 42.Nm strtol ,
44.Nd convert string value to a long or quad_t integer 43.Nm strtoll ,
44.Nm strtoq
45.Nd "convert string value to a long or long long integer"
45.Sh SYNOPSIS 46.Sh SYNOPSIS
46.Fd #include <stdlib.h> 47.Fd #include <stdlib.h>
47.Fd #include <limits.h> 48.Fd #include <limits.h>
48.Ft long 49.Ft long
49.Fn strtol "char *nptr" "char **endptr" "int base" 50.Fn strtol "const char *nptr" "char **endptr" "int base"
50 51.Pp
52.Fd #include <stdlib.h>
53.Fd #include <limits.h>
54.Ft long long
55.Fn strtoll "const char *nptr" "char **endptr" "int base"
56.Pp
51.Fd #include <sys/types.h> 57.Fd #include <sys/types.h>
52.Fd #include <stdlib.h> 58.Fd #include <stdlib.h>
53.Fd #include <limits.h> 59.Fd #include <limits.h>
54.Ft quad_t 60.Ft quad_t
55.Fn strtoq "char *nptr" "char **endptr" "int base" 61.Fn strtoq "const char *nptr" "char **endptr" "int base"
56.Sh DESCRIPTION 62.Sh DESCRIPTION
57The 63The
58.Fn strtol 64.Fn strtol
59function 65function converts the string in
60converts the string in
61.Fa nptr 66.Fa nptr
62to a 67to a
63.Em long 68.Li long
64value. 69value.
65The 70The
66.Fn strtoq 71.Fn strtoll
67function 72function converts the string in
68converts the string in
69.Fa nptr 73.Fa nptr
70to a 74to a
71.Em quad_t 75.Li long long
72value. 76value.
77The
78.Fn strtoq
79function is a deprecated equivalent of
80.Fn strtoll
81and is provided for backwards compatibility with legacy programs.
73The conversion is done according to the given 82The conversion is done according to the given
74.Fa base , 83.Fa base ,
75which must be between 2 and 36 inclusive, 84which must be a number between 2 and 36 inclusive or the special value 0.
76or be the special value 0.
77.Pp 85.Pp
78The string may begin with an arbitrary amount of white space 86The string may begin with an arbitrary amount of whitespace
79(as determined by 87(as determined by
80.Xr isspace 3 ) 88.Xr isspace 3 )
81followed by a single optional 89followed by a single optional
@@ -85,25 +93,22 @@ or
85sign. 93sign.
86If 94If
87.Fa base 95.Fa base
88is zero or 16, 96is zero or 16, the string may then include a
89the string may then include a
90.Ql 0x 97.Ql 0x
91prefix, 98prefix, and the number will be read in base 16; otherwise, a zero
92and the number will be read in base 16; otherwise, a zero
93.Fa base 99.Fa base
94is taken as 10 (decimal) unless the next character is 100is taken as 10 (decimal) unless the next character is
95.Ql 0 , 101.Ql 0 ,
96in which case it is taken as 8 (octal). 102in which case it is taken as 8 (octal).
97.Pp 103.Pp
98The remainder of the string is converted to a 104The remainder of the string is converted to a
99.Em long 105.Li long
100value in the obvious manner, 106value in the obvious manner,
101stopping at the first character which is not a valid digit 107stopping at the first character which is not a valid digit
102in the given base. 108in the given base.
103(In bases above 10, the letter 109(In bases above 10, the letter
104.Ql A 110.Ql A
105in either upper or lower case 111in either upper or lower case represents 10,
106represents 10,
107.Ql B 112.Ql B
108represents 11, and so forth, with 113represents 11, and so forth, with
109.Ql Z 114.Ql Z
@@ -111,7 +116,7 @@ representing 35.)
111.Pp 116.Pp
112If 117If
113.Fa endptr 118.Fa endptr
114is non nil, 119is non-null,
115.Fn strtol 120.Fn strtol
116stores the address of the first invalid character in 121stores the address of the first invalid character in
117.Fa *endptr . 122.Fa *endptr .
@@ -133,8 +138,7 @@ on return, the entire string was valid.)
133.Sh RETURN VALUES 138.Sh RETURN VALUES
134The 139The
135.Fn strtol 140.Fn strtol
136function 141function returns the result of the conversion,
137returns the result of the conversion,
138unless the value would underflow or overflow. 142unless the value would underflow or overflow.
139If an underflow occurs, 143If an underflow occurs,
140.Fn strtol 144.Fn strtol
@@ -148,6 +152,76 @@ In both cases,
148.Va errno 152.Va errno
149is set to 153is set to
150.Er ERANGE . 154.Er ERANGE .
155.Pp
156The
157.Fn strtoll
158function has identical return values except that
159.Dv LLONG_MIN
160and
161.Dv LLONG_MAX
162are used to indicate underflow and overflow respectively.
163.Sh EXAMPLES
164Ensuring that a string is a valid number (i.e., in range and containing no
165trailing characters) requires clearing
166.Va errno
167beforehand explicitly since
168.Va errno
169is not changed on a successful call to
170.Fn strtol ,
171and the return value of
172.Fn strtol
173cannot be used unambiguously to signal an error:
174.Bd -literal -offset indent
175char *ep;
176long lval;
177
178\&...
179
180errno = 0;
181lval = strtol(buf, &ep, 10);
182if (buf[0] == '\e0' || *ep != '\e0')
183 goto not_a_number;
184if (errno == ERANGE && (lval == LONG_MAX || lval == LONG_MIN))
185 goto out_of_range;
186.Ed
187.Pp
188This example will accept
189.Dq 12
190but not
191.Dq 12foo
192or
193.Dq 12\en .
194If trailing whitespace is acceptable, further checks must be done on
195.Va *ep ;
196alternately, use
197.Xr sscanf 3 .
198.Pp
199If
200.Fn strtol
201is being used instead of
202.Xr atoi 3 ,
203error checking is further complicated because the desired return value is an
204.Li int
205rather than a
206.Li long ;
207however, on some architectures integers and long integers are the same size.
208Thus the following is necessary:
209.Bd -literal -offset indent
210char *ep;
211int ival;
212long lval;
213
214\&...
215
216errno = 0;
217lval = strtol(buf, &ep, 10);
218if (buf[0] == '\e0' || *ep != '\e0')
219 goto not_a_number;
220if ((errno == ERANGE && (lval == LONG_MAX || lval == LONG_MIN)) ||
221 (lval > INT_MAX || lval < INT_MIN))
222 goto out_of_range;
223ival = lval;
224.Ed
151.Sh ERRORS 225.Sh ERRORS
152.Bl -tag -width Er 226.Bl -tag -width Er
153.It Bq Er ERANGE 227.It Bq Er ERANGE
@@ -157,13 +231,21 @@ The given string was out of range; the value converted has been clamped.
157.Xr atof 3 , 231.Xr atof 3 ,
158.Xr atoi 3 , 232.Xr atoi 3 ,
159.Xr atol 3 , 233.Xr atol 3 ,
234.Xr atoll 3 ,
235.Xr sscanf 3 ,
160.Xr strtod 3 , 236.Xr strtod 3 ,
161.Xr strtoul 3 237.Xr strtoul 3
162.Sh STANDARDS 238.Sh STANDARDS
163The 239The
164.Fn strtol 240.Fn strtol
165function 241and
166conforms to 242.Fn strtoll
167.St -ansiC . 243functions conform to
244.St -ansiC-99 .
245The
246.Fn strtoq
247function is a
248.Bx
249extension and is provided for backwards compatibility with legacy programs.
168.Sh BUGS 250.Sh BUGS
169Ignores the current locale. 251Ignores the current locale.
diff --git a/src/lib/libc/stdlib/strtol.c b/src/lib/libc/stdlib/strtol.c
index 6f374abd5f..e4ad557fd5 100644
--- a/src/lib/libc/stdlib/strtol.c
+++ b/src/lib/libc/stdlib/strtol.c
@@ -32,13 +32,12 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)strtol.c 5.4 (Berkeley) 2/23/91";*/ 35static char *rcsid = "$OpenBSD: strtol.c,v 1.4 1996/08/19 08:33:51 tholo Exp $";
36static char *rcsid = "$Id: strtol.c,v 1.1.1.1 1995/10/18 08:42:20 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
38 37
39#include <limits.h>
40#include <ctype.h> 38#include <ctype.h>
41#include <errno.h> 39#include <errno.h>
40#include <limits.h>
42#include <stdlib.h> 41#include <stdlib.h>
43 42
44 43
@@ -54,25 +53,28 @@ strtol(nptr, endptr, base)
54 char **endptr; 53 char **endptr;
55 register int base; 54 register int base;
56{ 55{
57 register const char *s = nptr; 56 register const char *s;
58 register unsigned long acc; 57 register long acc, cutoff;
59 register int c; 58 register int c;
60 register unsigned long cutoff; 59 register int neg, any, cutlim;
61 register int neg = 0, any, cutlim;
62 60
63 /* 61 /*
64 * Skip white space and pick up leading +/- sign if any. 62 * Skip white space and pick up leading +/- sign if any.
65 * If base is 0, allow 0x for hex and 0 for octal, else 63 * If base is 0, allow 0x for hex and 0 for octal, else
66 * assume decimal; if base is already 16, allow 0x. 64 * assume decimal; if base is already 16, allow 0x.
67 */ 65 */
66 s = nptr;
68 do { 67 do {
69 c = *s++; 68 c = (unsigned char) *s++;
70 } while (isspace(c)); 69 } while (isspace(c));
71 if (c == '-') { 70 if (c == '-') {
72 neg = 1; 71 neg = 1;
73 c = *s++; 72 c = *s++;
74 } else if (c == '+') 73 } else {
75 c = *s++; 74 neg = 0;
75 if (c == '+')
76 c = *s++;
77 }
76 if ((base == 0 || base == 16) && 78 if ((base == 0 || base == 16) &&
77 c == '0' && (*s == 'x' || *s == 'X')) { 79 c == '0' && (*s == 'x' || *s == 'X')) {
78 c = s[1]; 80 c = s[1];
@@ -99,10 +101,17 @@ strtol(nptr, endptr, base)
99 * Set any if any `digits' consumed; make it negative to indicate 101 * Set any if any `digits' consumed; make it negative to indicate
100 * overflow. 102 * overflow.
101 */ 103 */
102 cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX; 104 cutoff = neg ? LONG_MIN : LONG_MAX;
103 cutlim = cutoff % (unsigned long)base; 105 cutlim = cutoff % base;
104 cutoff /= (unsigned long)base; 106 cutoff /= base;
105 for (acc = 0, any = 0;; c = *s++) { 107 if (neg) {
108 if (cutlim > 0) {
109 cutlim -= base;
110 cutoff += 1;
111 }
112 cutlim = -cutlim;
113 }
114 for (acc = 0, any = 0;; c = (unsigned char) *s++) {
106 if (isdigit(c)) 115 if (isdigit(c))
107 c -= '0'; 116 c -= '0';
108 else if (isalpha(c)) 117 else if (isalpha(c))
@@ -111,19 +120,30 @@ strtol(nptr, endptr, base)
111 break; 120 break;
112 if (c >= base) 121 if (c >= base)
113 break; 122 break;
114 if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim) 123 if (any < 0)
115 any = -1; 124 continue;
116 else { 125 if (neg) {
117 any = 1; 126 if (acc < cutoff || acc == cutoff && c > cutlim) {
118 acc *= base; 127 any = -1;
119 acc += c; 128 acc = LONG_MIN;
129 errno = ERANGE;
130 } else {
131 any = 1;
132 acc *= base;
133 acc -= c;
134 }
135 } else {
136 if (acc > cutoff || acc == cutoff && c > cutlim) {
137 any = -1;
138 acc = LONG_MAX;
139 errno = ERANGE;
140 } else {
141 any = 1;
142 acc *= base;
143 acc += c;
144 }
120 } 145 }
121 } 146 }
122 if (any < 0) {
123 acc = neg ? LONG_MIN : LONG_MAX;
124 errno = ERANGE;
125 } else if (neg)
126 acc = -acc;
127 if (endptr != 0) 147 if (endptr != 0)
128 *endptr = (char *) (any ? s - 1 : nptr); 148 *endptr = (char *) (any ? s - 1 : nptr);
129 return (acc); 149 return (acc);
diff --git a/src/lib/libc/stdlib/strtoq.c b/src/lib/libc/stdlib/strtoll.c
index fc559e9d7f..b0eb6d198c 100644
--- a/src/lib/libc/stdlib/strtoq.c
+++ b/src/lib/libc/stdlib/strtoll.c
@@ -32,33 +32,32 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35static char sccsid[] = "@(#)strtoq.c 5.1 (Berkeley) 6/26/92"; 35static const char rcsid[] = "$OpenBSD: strtoll.c,v 1.1 2002/06/29 00:20:11 millert Exp $";
36#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
37 37
38#include <sys/types.h> 38#include <sys/types.h>
39 39
40#include <limits.h>
41#include <errno.h>
42#include <ctype.h> 40#include <ctype.h>
41#include <errno.h>
42#include <limits.h>
43#include <stdlib.h> 43#include <stdlib.h>
44 44
45/* 45/*
46 * Convert a string to a quad integer. 46 * Convert a string to a long long.
47 * 47 *
48 * Ignores `locale' stuff. Assumes that the upper and lower case 48 * Ignores `locale' stuff. Assumes that the upper and lower case
49 * alphabets and digits are each contiguous. 49 * alphabets and digits are each contiguous.
50 */ 50 */
51quad_t 51long long
52strtoq(nptr, endptr, base) 52strtoll(nptr, endptr, base)
53 const char *nptr; 53 const char *nptr;
54 char **endptr; 54 char **endptr;
55 register int base; 55 int base;
56{ 56{
57 register const char *s; 57 const char *s;
58 register u_quad_t acc; 58 long long acc, cutoff;
59 register int c; 59 int c;
60 register u_quad_t qbase, cutoff; 60 int neg, any, cutlim;
61 register int neg, any, cutlim;
62 61
63 /* 62 /*
64 * Skip white space and pick up leading +/- sign if any. 63 * Skip white space and pick up leading +/- sign if any.
@@ -67,7 +66,7 @@ strtoq(nptr, endptr, base)
67 */ 66 */
68 s = nptr; 67 s = nptr;
69 do { 68 do {
70 c = *s++; 69 c = (unsigned char) *s++;
71 } while (isspace(c)); 70 } while (isspace(c));
72 if (c == '-') { 71 if (c == '-') {
73 neg = 1; 72 neg = 1;
@@ -93,7 +92,7 @@ strtoq(nptr, endptr, base)
93 * followed by a legal input character, is too big. One that 92 * followed by a legal input character, is too big. One that
94 * is equal to this value may be valid or not; the limit 93 * is equal to this value may be valid or not; the limit
95 * between valid and invalid numbers is then based on the last 94 * between valid and invalid numbers is then based on the last
96 * digit. For instance, if the range for quads is 95 * digit. For instance, if the range for long longs is
97 * [-9223372036854775808..9223372036854775807] and the input base 96 * [-9223372036854775808..9223372036854775807] and the input base
98 * is 10, cutoff will be set to 922337203685477580 and cutlim to 97 * is 10, cutoff will be set to 922337203685477580 and cutlim to
99 * either 7 (neg==0) or 8 (neg==1), meaning that if we have 98 * either 7 (neg==0) or 8 (neg==1), meaning that if we have
@@ -104,11 +103,17 @@ strtoq(nptr, endptr, base)
104 * Set any if any `digits' consumed; make it negative to indicate 103 * Set any if any `digits' consumed; make it negative to indicate
105 * overflow. 104 * overflow.
106 */ 105 */
107 qbase = (unsigned)base; 106 cutoff = neg ? LLONG_MIN : LLONG_MAX;
108 cutoff = neg ? -(u_quad_t)QUAD_MIN : QUAD_MAX; 107 cutlim = cutoff % base;
109 cutlim = cutoff % qbase; 108 cutoff /= base;
110 cutoff /= qbase; 109 if (neg) {
111 for (acc = 0, any = 0;; c = *s++) { 110 if (cutlim > 0) {
111 cutlim -= base;
112 cutoff += 1;
113 }
114 cutlim = -cutlim;
115 }
116 for (acc = 0, any = 0;; c = (unsigned char) *s++) {
112 if (isdigit(c)) 117 if (isdigit(c))
113 c -= '0'; 118 c -= '0';
114 else if (isalpha(c)) 119 else if (isalpha(c))
@@ -117,20 +122,45 @@ strtoq(nptr, endptr, base)
117 break; 122 break;
118 if (c >= base) 123 if (c >= base)
119 break; 124 break;
120 if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim) 125 if (any < 0)
121 any = -1; 126 continue;
122 else { 127 if (neg) {
123 any = 1; 128 if (acc < cutoff || (acc == cutoff && c > cutlim)) {
124 acc *= qbase; 129 any = -1;
125 acc += c; 130 acc = LLONG_MIN;
131 errno = ERANGE;
132 } else {
133 any = 1;
134 acc *= base;
135 acc -= c;
136 }
137 } else {
138 if (acc > cutoff || (acc == cutoff && c > cutlim)) {
139 any = -1;
140 acc = LLONG_MAX;
141 errno = ERANGE;
142 } else {
143 any = 1;
144 acc *= base;
145 acc += c;
146 }
126 } 147 }
127 } 148 }
128 if (any < 0) {
129 acc = neg ? QUAD_MIN : QUAD_MAX;
130 errno = ERANGE;
131 } else if (neg)
132 acc = -acc;
133 if (endptr != 0) 149 if (endptr != 0)
134 *endptr = (char *) (any ? s - 1 : nptr); 150 *endptr = (char *) (any ? s - 1 : nptr);
135 return (acc); 151 return (acc);
136} 152}
153
154#ifdef __weak_alias
155__weak_alias(strtoq, strtoll);
156#else
157quad_t
158strtoq(nptr, endptr, base)
159 const char *nptr;
160 char **endptr;
161 int base;
162{
163
164 return ((quad_t)strtoll(nptr, endptr, base);
165}
166#endif
diff --git a/src/lib/libc/stdlib/strtoul.3 b/src/lib/libc/stdlib/strtoul.3
index db551b0141..39de7e0656 100644
--- a/src/lib/libc/stdlib/strtoul.3
+++ b/src/lib/libc/stdlib/strtoul.3
@@ -33,21 +33,27 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)strtoul.3 5.4 (Berkeley) 6/25/92 36.\" $OpenBSD: strtoul.3,v 1.14 2003/05/10 06:48:30 jmc Exp $
37.\" $Id: strtoul.3,v 1.1.1.1 1995/10/18 08:42:20 deraadt Exp $
38.\" 37.\"
39.Dd June 25, 1992 38.Dd June 25, 1992
40.Dt STRTOUL 3 39.Dt STRTOUL 3
41.Os 40.Os
42.Sh NAME 41.Sh NAME
43.Nm strtoul, strtouq 42.Nm strtoul ,
44.Nd convert a string to an unsigned long or uquad_t integer 43.Nm strtoull ,
44.Nm strtouq
45.Nd "convert a string to an unsigned long or unsigned long long integer"
45.Sh SYNOPSIS 46.Sh SYNOPSIS
46.Fd #include <stdlib.h> 47.Fd #include <stdlib.h>
47.Fd #include <limits.h> 48.Fd #include <limits.h>
48.Ft unsigned long 49.Ft unsigned long
49.Fn strtoul "const char *nptr" "char **endptr" "int base" 50.Fn strtoul "const char *nptr" "char **endptr" "int base"
50 51.Pp
52.Fd #include <stdlib.h>
53.Fd #include <limits.h>
54.Ft unsigned long long
55.Fn strtoull "const char *nptr" "char **endptr" "int base"
56.Pp
51.Fd #include <sys/types.h> 57.Fd #include <sys/types.h>
52.Fd #include <stdlib.h> 58.Fd #include <stdlib.h>
53.Fd #include <limits.h> 59.Fd #include <limits.h>
@@ -56,26 +62,34 @@
56.Sh DESCRIPTION 62.Sh DESCRIPTION
57The 63The
58.Fn strtoul 64.Fn strtoul
59function 65function converts the string in
60converts the string in
61.Fa nptr 66.Fa nptr
62to an 67to an
63.Em unsigned long 68.Li unsigned long
64value. 69value.
65The 70The
66.Fn strtouq 71.Fn strtoull
67function 72function converts the string in
68converts the string in
69.Fa nptr 73.Fa nptr
70to a 74to an
71.Em u_quad_t 75.Li unsigned long long
72value. 76value.
77The
78.Fn strtouq
79function is a deprecated equivalent of
80.Fn strtoull
81and is provided for backwards compatibility with legacy programs.
73The conversion is done according to the given 82The conversion is done according to the given
74.Fa base , 83.Fa base ,
75which must be between 2 and 36 inclusive, 84which must be a number between 2 and 36 inclusive
76or be the special value 0. 85or the special value 0.
86If the string in
87.Fa nptr
88represents a negative number, it will be converted to its unsigned equivalent.
89This behavior is consistent with what happens when a signed integer type is
90cast to its unsigned counterpart.
77.Pp 91.Pp
78The string may begin with an arbitrary amount of white space 92The string may begin with an arbitrary amount of whitespace
79(as determined by 93(as determined by
80.Xr isspace 3 ) 94.Xr isspace 3 )
81followed by a single optional 95followed by a single optional
@@ -85,26 +99,22 @@ or
85sign. 99sign.
86If 100If
87.Fa base 101.Fa base
88is zero or 16, 102is zero or 16, the string may then include a
89the string may then include a
90.Ql 0x 103.Ql 0x
91prefix, 104prefix, and the number will be read in base 16; otherwise, a zero
92and the number will be read in base 16; otherwise, a zero
93.Fa base 105.Fa base
94is taken as 10 (decimal) unless the next character is 106is taken as 10 (decimal) unless the next character is
95.Ql 0 , 107.Ql 0 ,
96in which case it is taken as 8 (octal). 108in which case it is taken as 8 (octal).
97.Pp 109.Pp
98The remainder of the string is converted to an 110The remainder of the string is converted to an
99.Em unsigned long 111.Li unsigned long
100value in the obvious manner, 112value in the obvious manner, stopping at the end of the string
101stopping at the end of the string
102or at the first character that does not produce a valid digit 113or at the first character that does not produce a valid digit
103in the given base. 114in the given base.
104(In bases above 10, the letter 115(In bases above 10, the letter
105.Ql A 116.Ql A
106in either upper or lower case 117in either upper or lower case represents 10,
107represents 10,
108.Ql B 118.Ql B
109represents 11, and so forth, with 119represents 11, and so forth, with
110.Ql Z 120.Ql Z
@@ -112,7 +122,7 @@ representing 35.)
112.Pp 122.Pp
113If 123If
114.Fa endptr 124.Fa endptr
115is non nil, 125is non-null,
116.Fn strtoul 126.Fn strtoul
117stores the address of the first invalid character in 127stores the address of the first invalid character in
118.Fa *endptr . 128.Fa *endptr .
@@ -134,12 +144,18 @@ on return, the entire string was valid.)
134.Sh RETURN VALUES 144.Sh RETURN VALUES
135The 145The
136.Fn strtoul 146.Fn strtoul
137function 147function returns the result of the conversion,
138returns either the result of the conversion 148unless the value would overflow, in which case
139or, if there was a leading minus sign, 149.Dv ULONG_MAX
140the negation of the result of the conversion, 150is returned and
141unless the original (non-negated) value would overflow; 151.Va errno
142in the latter case, 152is set to
153.Er ERANGE .
154If there was a leading minus sign,
155.Fn strtoul
156returns the (unsigned) negation of the absolute value of the number, unless
157the absolute value would overflow.
158In this case,
143.Fn strtoul 159.Fn strtoul
144returns 160returns
145.Dv ULONG_MAX 161.Dv ULONG_MAX
@@ -147,18 +163,73 @@ and sets the global variable
147.Va errno 163.Va errno
148to 164to
149.Er ERANGE . 165.Er ERANGE .
166.Pp
167The
168.Fn strtoull
169function has identical return values except that
170.Dv ULLONG_MAX
171is used to indicate overflow.
172.Pp
173There is no way to determine if
174.Fn strtoul
175has processed a negative number (and returned an unsigned value) short of
176examining the string in
177.Fa nptr
178directly.
179.Sh EXAMPLES
180Ensuring that a string is a valid number (i.e., in range and containing no
181trailing characters) requires clearing
182.Va errno
183beforehand explicitly since
184.Va errno
185is not changed on a successful call to
186.Fn strtoul ,
187and the return value of
188.Fn strtoul
189cannot be used unambiguously to signal an error:
190.Bd -literal -offset indent
191char *ep;
192unsigned long ulval;
193
194\&...
195
196errno = 0;
197ulval = strtoul(buf, &ep, 10);
198if (buf[0] == '\e0' || *ep != '\e0')
199 goto not_a_number;
200if (errno == ERANGE && ulval == ULONG_MAX)
201 goto out_of_range;
202.Ed
203.Pp
204This example will accept
205.Dq 12
206but not
207.Dq 12foo
208or
209.Dq 12\en .
210If trailing whitespace is acceptable, further checks must be done on
211.Va *ep ;
212alternately, use
213.Xr sscanf 3 .
150.Sh ERRORS 214.Sh ERRORS
151.Bl -tag -width Er 215.Bl -tag -width Er
152.It Bq Er ERANGE 216.It Bq Er ERANGE
153The given string was out of range; the value converted has been clamped. 217The given string was out of range; the value converted has been clamped.
154.El 218.El
155.Sh SEE ALSO 219.Sh SEE ALSO
220.Xr sscanf 3 ,
156.Xr strtol 3 221.Xr strtol 3
157.Sh STANDARDS 222.Sh STANDARDS
158The 223The
159.Fn strtoul 224.Fn strtoul
160function 225and
161conforms to 226.Fn strtoull
162.St -ansiC . 227functions conform to
228.St -ansiC-99 .
229The
230.Fn strtouq
231function is a
232.Bx
233extension and is provided for backwards compatibility with legacy programs.
163.Sh BUGS 234.Sh BUGS
164Ignores the current locale. 235Ignores the current locale.
diff --git a/src/lib/libc/stdlib/strtoul.c b/src/lib/libc/stdlib/strtoul.c
index 00f7210fa1..d3b363fa04 100644
--- a/src/lib/libc/stdlib/strtoul.c
+++ b/src/lib/libc/stdlib/strtoul.c
@@ -32,13 +32,12 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)strtoul.c 5.3 (Berkeley) 2/23/91";*/ 35static char *rcsid = "$OpenBSD: strtoul.c,v 1.4 1996/08/19 08:33:52 tholo Exp $";
36static char *rcsid = "$Id: strtoul.c,v 1.1.1.1 1995/10/18 08:42:20 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
38 37
39#include <limits.h>
40#include <ctype.h> 38#include <ctype.h>
41#include <errno.h> 39#include <errno.h>
40#include <limits.h>
42#include <stdlib.h> 41#include <stdlib.h>
43 42
44/* 43/*
@@ -53,23 +52,26 @@ strtoul(nptr, endptr, base)
53 char **endptr; 52 char **endptr;
54 register int base; 53 register int base;
55{ 54{
56 register const char *s = nptr; 55 register const char *s;
57 register unsigned long acc; 56 register unsigned long acc, cutoff;
58 register int c; 57 register int c;
59 register unsigned long cutoff; 58 register int neg, any, cutlim;
60 register int neg = 0, any, cutlim;
61 59
62 /* 60 /*
63 * See strtol for comments as to the logic used. 61 * See strtol for comments as to the logic used.
64 */ 62 */
63 s = nptr;
65 do { 64 do {
66 c = *s++; 65 c = (unsigned char) *s++;
67 } while (isspace(c)); 66 } while (isspace(c));
68 if (c == '-') { 67 if (c == '-') {
69 neg = 1; 68 neg = 1;
70 c = *s++; 69 c = *s++;
71 } else if (c == '+') 70 } else {
72 c = *s++; 71 neg = 0;
72 if (c == '+')
73 c = *s++;
74 }
73 if ((base == 0 || base == 16) && 75 if ((base == 0 || base == 16) &&
74 c == '0' && (*s == 'x' || *s == 'X')) { 76 c == '0' && (*s == 'x' || *s == 'X')) {
75 c = s[1]; 77 c = s[1];
@@ -78,9 +80,10 @@ strtoul(nptr, endptr, base)
78 } 80 }
79 if (base == 0) 81 if (base == 0)
80 base = c == '0' ? 8 : 10; 82 base = c == '0' ? 8 : 10;
81 cutoff = (unsigned long)ULONG_MAX / (unsigned long)base; 83
82 cutlim = (unsigned long)ULONG_MAX % (unsigned long)base; 84 cutoff = ULONG_MAX / (unsigned long)base;
83 for (acc = 0, any = 0;; c = *s++) { 85 cutlim = ULONG_MAX % (unsigned long)base;
86 for (acc = 0, any = 0;; c = (unsigned char) *s++) {
84 if (isdigit(c)) 87 if (isdigit(c))
85 c -= '0'; 88 c -= '0';
86 else if (isalpha(c)) 89 else if (isalpha(c))
@@ -89,18 +92,19 @@ strtoul(nptr, endptr, base)
89 break; 92 break;
90 if (c >= base) 93 if (c >= base)
91 break; 94 break;
92 if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim) 95 if (any < 0)
96 continue;
97 if (acc > cutoff || acc == cutoff && c > cutlim) {
93 any = -1; 98 any = -1;
94 else { 99 acc = ULONG_MAX;
100 errno = ERANGE;
101 } else {
95 any = 1; 102 any = 1;
96 acc *= base; 103 acc *= (unsigned long)base;
97 acc += c; 104 acc += c;
98 } 105 }
99 } 106 }
100 if (any < 0) { 107 if (neg && any > 0)
101 acc = ULONG_MAX;
102 errno = ERANGE;
103 } else if (neg)
104 acc = -acc; 108 acc = -acc;
105 if (endptr != 0) 109 if (endptr != 0)
106 *endptr = (char *) (any ? s - 1 : nptr); 110 *endptr = (char *) (any ? s - 1 : nptr);
diff --git a/src/lib/libc/stdlib/strtouq.c b/src/lib/libc/stdlib/strtoull.c
index cc647d8d28..7b4dd56c01 100644
--- a/src/lib/libc/stdlib/strtouq.c
+++ b/src/lib/libc/stdlib/strtoull.c
@@ -32,40 +32,39 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35static char sccsid[] = "@(#)strtouq.c 5.1 (Berkeley) 6/26/92"; 35static const char rcsid[] = "$OpenBSD: strtoull.c,v 1.1 2002/06/29 00:20:11 millert Exp $";
36#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
37 37
38#include <sys/types.h> 38#include <sys/types.h>
39 39
40#include <limits.h>
41#include <errno.h>
42#include <ctype.h> 40#include <ctype.h>
41#include <errno.h>
42#include <limits.h>
43#include <stdlib.h> 43#include <stdlib.h>
44 44
45/* 45/*
46 * Convert a string to an unsigned quad integer. 46 * Convert a string to an unsigned long long.
47 * 47 *
48 * Ignores `locale' stuff. Assumes that the upper and lower case 48 * Ignores `locale' stuff. Assumes that the upper and lower case
49 * alphabets and digits are each contiguous. 49 * alphabets and digits are each contiguous.
50 */ 50 */
51u_quad_t 51unsigned long long
52strtouq(nptr, endptr, base) 52strtoull(nptr, endptr, base)
53 const char *nptr; 53 const char *nptr;
54 char **endptr; 54 char **endptr;
55 register int base; 55 int base;
56{ 56{
57 register const char *s = nptr; 57 const char *s;
58 register u_quad_t acc; 58 unsigned long long acc, cutoff;
59 register int c; 59 int c;
60 register u_quad_t qbase, cutoff; 60 int neg, any, cutlim;
61 register int neg, any, cutlim;
62 61
63 /* 62 /*
64 * See strtoq for comments as to the logic used. 63 * See strtoq for comments as to the logic used.
65 */ 64 */
66 s = nptr; 65 s = nptr;
67 do { 66 do {
68 c = *s++; 67 c = (unsigned char) *s++;
69 } while (isspace(c)); 68 } while (isspace(c));
70 if (c == '-') { 69 if (c == '-') {
71 neg = 1; 70 neg = 1;
@@ -83,10 +82,10 @@ strtouq(nptr, endptr, base)
83 } 82 }
84 if (base == 0) 83 if (base == 0)
85 base = c == '0' ? 8 : 10; 84 base = c == '0' ? 8 : 10;
86 qbase = (unsigned)base; 85
87 cutoff = (u_quad_t)UQUAD_MAX / qbase; 86 cutoff = ULLONG_MAX / (unsigned long long)base;
88 cutlim = (u_quad_t)UQUAD_MAX % qbase; 87 cutlim = ULLONG_MAX % (unsigned long long)base;
89 for (acc = 0, any = 0;; c = *s++) { 88 for (acc = 0, any = 0;; c = (unsigned char) *s++) {
90 if (isdigit(c)) 89 if (isdigit(c))
91 c -= '0'; 90 c -= '0';
92 else if (isalpha(c)) 91 else if (isalpha(c))
@@ -95,20 +94,35 @@ strtouq(nptr, endptr, base)
95 break; 94 break;
96 if (c >= base) 95 if (c >= base)
97 break; 96 break;
98 if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim) 97 if (any < 0)
98 continue;
99 if (acc > cutoff || (acc == cutoff && c > cutlim)) {
99 any = -1; 100 any = -1;
100 else { 101 acc = ULLONG_MAX;
102 errno = ERANGE;
103 } else {
101 any = 1; 104 any = 1;
102 acc *= qbase; 105 acc *= (unsigned long long)base;
103 acc += c; 106 acc += c;
104 } 107 }
105 } 108 }
106 if (any < 0) { 109 if (neg && any > 0)
107 acc = UQUAD_MAX;
108 errno = ERANGE;
109 } else if (neg)
110 acc = -acc; 110 acc = -acc;
111 if (endptr != 0) 111 if (endptr != 0)
112 *endptr = (char *) (any ? s - 1 : nptr); 112 *endptr = (char *) (any ? s - 1 : nptr);
113 return (acc); 113 return (acc);
114} 114}
115
116#ifdef __weak_alias
117__weak_alias(strtouq, strtoull);
118#else
119u_quad_t
120strtouq(nptr, endptr, base)
121 const char *nptr;
122 char **endptr;
123 int base;
124{
125
126 return ((u_quad_t)strtoull(nptr, endptr, base);
127}
128#endif
diff --git a/src/lib/libc/stdlib/system.3 b/src/lib/libc/stdlib/system.3
index 520f51db0a..83c6de80e3 100644
--- a/src/lib/libc/stdlib/system.3
+++ b/src/lib/libc/stdlib/system.3
@@ -33,8 +33,7 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)system.3 6.5 (Berkeley) 6/29/91 36.\" $OpenBSD: system.3,v 1.8 2000/10/06 04:17:51 aaron Exp $
37.\" $Id: system.3,v 1.1.1.1 1995/10/18 08:42:20 deraadt Exp $
38.\" 37.\"
39.Dd June 29, 1991 38.Dd June 29, 1991
40.Dt SYSTEM 3 39.Dt SYSTEM 3
@@ -49,8 +48,7 @@
49.Sh DESCRIPTION 48.Sh DESCRIPTION
50The 49The
51.Fn system 50.Fn system
52function 51function hands the argument
53hands the argument
54.Fa string 52.Fa string
55to the command interpreter 53to the command interpreter
56.Xr sh 1 . 54.Xr sh 1 .
@@ -64,36 +62,42 @@ and blocking
64.Pp 62.Pp
65If 63If
66.Fa string 64.Fa string
67is a 65is
68.Dv NULL 66.Dv NULL ,
69pointer,
70.Fn system 67.Fn system
71will return non-zero. 68will return non-zero.
72Otherwise, 69Otherwise,
73.Fn system 70.Fn system
74returns the termination status of the shell in the format specified by 71returns the termination status of the shell in the format specified by
75.Xr waitpid 3 . 72.Xr waitpid 2 .
76.Sh RETURN VALUES 73.Sh RETURN VALUES
77If a child process cannot be created, or the termination status of 74If a child process cannot be created, or the termination status of
78the shell cannot be obtained, 75the shell cannot be obtained,
79.Fn system 76.Fn system
80returns -1 and sets 77returns \-1 and sets
81.Va errno 78.Va errno
82to indicate the error. 79to indicate the error.
83If execution of the shell fails, 80If execution of the shell fails,
84.Fn system 81.Fn system
85returns the termination status for a program that terminates with a call of 82returns the termination status for a program that terminates with a call of
86.Fn exit 127 . 83.Fn exit 127 .
87.Sh SEE ALSO 84.Sh SEE ALSO
88.Xr sh 1 , 85.Xr sh 1 ,
89.Xr execve 2 , 86.Xr execve 2 ,
90.Xr popen 3 , 87.Xr waitpid 2 ,
91.Xr waitpid 3 , 88.Xr popen 3
92.Sh STANDARDS 89.Sh STANDARDS
93The 90The
94.Fn system 91.Fn system
95function 92function conforms to
96conforms to 93.St -ansiC
97.St -ansiC
98and 94and
99.St -1003.2-92 . 95.St -p1003.2-92 .
96.Sh CAVEATS
97Never supply the
98.Fn system
99function with a command containing any part of an unsanitized user-supplied
100string.
101Shell meta-characters present will be honored by the
102.Xr sh 1
103command interpreter.
diff --git a/src/lib/libc/stdlib/system.c b/src/lib/libc/stdlib/system.c
index c2f39325f6..636a9ebdff 100644
--- a/src/lib/libc/stdlib/system.c
+++ b/src/lib/libc/stdlib/system.c
@@ -32,8 +32,7 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)system.c 5.10 (Berkeley) 2/23/91";*/ 35static char *rcsid = "$OpenBSD: system.c,v 1.5 2002/05/26 09:29:02 deraadt Exp $";
36static char *rcsid = "$Id: system.c,v 1.1.1.1 1995/10/18 08:42:20 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
38 37
39#include <sys/types.h> 38#include <sys/types.h>
@@ -51,20 +50,24 @@ system(command)
51{ 50{
52 pid_t pid; 51 pid_t pid;
53 sig_t intsave, quitsave; 52 sig_t intsave, quitsave;
54 int omask; 53 sigset_t mask, omask;
55 int pstat; 54 int pstat;
56 char *argp[] = {"sh", "-c", (char *) command, NULL}; 55 char *argp[] = {"sh", "-c", NULL, NULL};
57 56
58 if (!command) /* just checking... */ 57 if (!command) /* just checking... */
59 return(1); 58 return(1);
60 59
61 omask = sigblock(sigmask(SIGCHLD)); 60 argp[2] = (char *)command;
62 switch(pid = vfork()) { 61
62 sigemptyset(&mask);
63 sigaddset(&mask, SIGCHLD);
64 sigprocmask(SIG_BLOCK, &mask, &omask);
65 switch (pid = vfork()) {
63 case -1: /* error */ 66 case -1: /* error */
64 (void)sigsetmask(omask); 67 sigprocmask(SIG_SETMASK, &omask, NULL);
65 return(-1); 68 return(-1);
66 case 0: /* child */ 69 case 0: /* child */
67 (void)sigsetmask(omask); 70 sigprocmask(SIG_SETMASK, &omask, NULL);
68 execve(_PATH_BSHELL, argp, environ); 71 execve(_PATH_BSHELL, argp, environ);
69 _exit(127); 72 _exit(127);
70 } 73 }
@@ -72,8 +75,8 @@ system(command)
72 intsave = signal(SIGINT, SIG_IGN); 75 intsave = signal(SIGINT, SIG_IGN);
73 quitsave = signal(SIGQUIT, SIG_IGN); 76 quitsave = signal(SIGQUIT, SIG_IGN);
74 pid = waitpid(pid, (int *)&pstat, 0); 77 pid = waitpid(pid, (int *)&pstat, 0);
75 (void)sigsetmask(omask); 78 sigprocmask(SIG_SETMASK, &omask, NULL);
76 (void)signal(SIGINT, intsave); 79 (void)signal(SIGINT, intsave);
77 (void)signal(SIGQUIT, quitsave); 80 (void)signal(SIGQUIT, quitsave);
78 return(pid == -1 ? -1 : pstat); 81 return (pid == -1 ? -1 : pstat);
79} 82}
diff --git a/src/lib/libc/stdlib/tfind.c b/src/lib/libc/stdlib/tfind.c
new file mode 100644
index 0000000000..5c3b8c17f5
--- /dev/null
+++ b/src/lib/libc/stdlib/tfind.c
@@ -0,0 +1,41 @@
1/*
2 * Tree search generalized from Knuth (6.2.2) Algorithm T just like
3 * the AT&T man page says.
4 *
5 * The node_t structure is for internal use only, lint doesn't grok it.
6 *
7 * Written by reading the System V Interface Definition, not the code.
8 *
9 * Totally public domain.
10 */
11/*LINTLIBRARY*/
12#include <search.h>
13
14typedef struct node_t
15{
16 char *key;
17 struct node_t *llink, *rlink;
18} node;
19
20/* find a node, or return 0 */
21void *
22tfind(vkey, vrootp, compar)
23 const void *vkey; /* key to be found */
24 void *const *vrootp; /* address of the tree root */
25 int (*compar)(const void *, const void *);
26{
27 char *key = (char *)vkey;
28 node **rootp = (node **)vrootp;
29
30 if (rootp == (struct node_t **)0)
31 return ((struct node_t *)0);
32 while (*rootp != (struct node_t *)0) { /* T1: */
33 int r;
34 if ((r = (*compar)(key, (*rootp)->key)) == 0) /* T2: */
35 return (*rootp); /* key found */
36 rootp = (r < 0) ?
37 &(*rootp)->llink : /* T3: follow left branch */
38 &(*rootp)->rlink; /* T4: follow right branch */
39 }
40 return (node *)0;
41}
diff --git a/src/lib/libc/stdlib/tsearch.3 b/src/lib/libc/stdlib/tsearch.3
new file mode 100644
index 0000000000..b000a0a8b1
--- /dev/null
+++ b/src/lib/libc/stdlib/tsearch.3
@@ -0,0 +1,127 @@
1.\" Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
2.\" All rights reserved.
3.\"
4.\" Redistribution and use in source and binary forms, with or without
5.\" modification, are permitted provided that the following conditions
6.\" are met:
7.\" 1. Redistributions of source code must retain the above copyright
8.\" notice, this list of conditions and the following disclaimer.
9.\" 2. Redistributions in binary form must reproduce the above copyright
10.\" notice, this list of conditions and the following disclaimer in the
11.\" documentation and/or other materials provided with the distribution.
12.\" 3. The name of the author may not be used to endorse or promote products
13.\" derived from this software without specific prior written permission.
14.\"
15.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
16.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
17.\" AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
18.\" THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19.\" EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20.\" PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21.\" OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22.\" WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
24.\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25.\"
26.\" $OpenBSD: tsearch.3,v 1.9 2000/08/09 15:51:21 aaron Exp $
27.\"
28.Dd June 15, 1997
29.Dt TSEARCH 3
30.Os
31.Sh NAME
32.Nm tsearch ,
33.Nm tfind ,
34.Nm tdelete ,
35.Nm twalk
36.Nd manipulate binary search trees
37.Sh SYNOPSIS
38.Fd #include <search.h>
39.Ft void *
40.Fn tdelete "const void *key" "void **rootp" "int (*compar) (const void *, const void *)"
41.Ft void *
42.Fn tfind "const void *key" "void * const *rootp" "int (*compar) (const void *, const void *)"
43.Ft void *
44.Fn tsearch "const void *key" "void **rootp" "int (*compar) (const void *, const void *)"
45.Ft void
46.Fn twalk "const void *root" "void (*action) (const void *, VISIT, int)"
47.Sh DESCRIPTION
48The
49.Fn tdelete ,
50.Fn tfind ,
51.Fn tsearch ,
52and
53.Fn twalk
54functions manage binary search trees based on algorithms T and D
55from Knuth (6.2.2).
56The comparison function passed in by
57the user has the same style of return values as
58.Xr strcmp 3 .
59.Pp
60.Fn tfind
61searches for the datum matched by the argument
62.Fa key
63in the binary tree rooted at
64.Fa rootp ,
65returning a pointer to the datum if it is found and
66.Dv NULL
67if it is not.
68.Pp
69.Fn tsearch
70is identical to
71.Fn tfind
72except that if no match is found,
73.Fa key
74is inserted into the tree and a pointer to it is returned.
75If
76.Fa rootp
77points to a null value a new binary search tree is created.
78.Pp
79.Fn tdelete
80deletes a node from the specified binary search tree and returns
81a pointer to the parent of the node to be deleted.
82It takes the same arguments as
83.Fn tfind
84and
85.Fn tsearch .
86If the node to be deleted is the root of the binary search tree,
87.Fa rootp
88will be adjusted.
89.Pp
90.Fn twalk
91walks the binary search tree rooted in
92.Fa root
93and calls the function
94.Fa action
95on each node.
96.Fa action
97is called with three arguments: a pointer to the current node,
98a value from the enum
99.Sy "typedef enum { preorder, postorder, endorder, leaf } VISIT;"
100specifying the traversal type, and a node level (where level
101zero is the root of the tree).
102.Sh SEE ALSO
103.Xr bsearch 3 ,
104.Xr lsearch 3
105.Sh RETURN VALUES
106The
107.Fn tsearch
108function returns
109.Dv NULL
110if allocation of a new node fails (usually
111due to a lack of free memory).
112.Pp
113.Fn tfind ,
114.Fn tsearch ,
115and
116.Fn tdelete
117return
118.Dv NULL
119if
120.Fa rootp
121is
122.Dv NULL
123or the datum cannot be found.
124.Pp
125The
126.Fn twalk
127function returns no value.
diff --git a/src/lib/libc/stdlib/tsearch.c b/src/lib/libc/stdlib/tsearch.c
new file mode 100644
index 0000000000..0ad5866172
--- /dev/null
+++ b/src/lib/libc/stdlib/tsearch.c
@@ -0,0 +1,126 @@
1/*
2 * Tree search generalized from Knuth (6.2.2) Algorithm T just like
3 * the AT&T man page says.
4 *
5 * The node_t structure is for internal use only, lint doesn't grok it.
6 *
7 * Written by reading the System V Interface Definition, not the code.
8 *
9 * Totally public domain.
10 */
11/*LINTLIBRARY*/
12
13#include <search.h>
14#include <stdlib.h>
15
16typedef struct node_t {
17 char *key;
18 struct node_t *left, *right;
19} node;
20
21/* find or insert datum into search tree */
22void *
23tsearch(vkey, vrootp, compar)
24 const void *vkey; /* key to be located */
25 void **vrootp; /* address of tree root */
26 int (*compar)(const void *, const void *);
27{
28 register node *q;
29 char *key = (char *)vkey;
30 node **rootp = (node **)vrootp;
31
32 if (rootp == (struct node_t **)0)
33 return ((void *)0);
34 while (*rootp != (struct node_t *)0) { /* Knuth's T1: */
35 int r;
36
37 if ((r = (*compar)(key, (*rootp)->key)) == 0) /* T2: */
38 return ((void *)*rootp); /* we found it! */
39 rootp = (r < 0) ?
40 &(*rootp)->left : /* T3: follow left branch */
41 &(*rootp)->right; /* T4: follow right branch */
42 }
43 q = (node *) malloc(sizeof(node)); /* T5: key not found */
44 if (q != (struct node_t *)0) { /* make new node */
45 *rootp = q; /* link new node to old */
46 q->key = key; /* initialize new node */
47 q->left = q->right = (struct node_t *)0;
48 }
49 return ((void *)q);
50}
51
52/* delete node with given key */
53void *
54tdelete(vkey, vrootp, compar)
55 const void *vkey; /* key to be deleted */
56 void **vrootp; /* address of the root of tree */
57 int (*compar)(const void *, const void *);
58{
59 node **rootp = (node **)vrootp;
60 char *key = (char *)vkey;
61 node *p;
62 register node *q;
63 register node *r;
64 int cmp;
65
66 if (rootp == (struct node_t **)0 || (p = *rootp) == (struct node_t *)0)
67 return ((struct node_t *)0);
68 while ((cmp = (*compar)(key, (*rootp)->key)) != 0) {
69 p = *rootp;
70 rootp = (cmp < 0) ?
71 &(*rootp)->left : /* follow left branch */
72 &(*rootp)->right; /* follow right branch */
73 if (*rootp == (struct node_t *)0)
74 return ((void *)0); /* key not found */
75 }
76 r = (*rootp)->right; /* D1: */
77 if ((q = (*rootp)->left) == (struct node_t *)0) /* Left (struct node_t *)0? */
78 q = r;
79 else if (r != (struct node_t *)0) { /* Right link is null? */
80 if (r->left == (struct node_t *)0) { /* D2: Find successor */
81 r->left = q;
82 q = r;
83 } else { /* D3: Find (struct node_t *)0 link */
84 for (q = r->left; q->left != (struct node_t *)0; q = r->left)
85 r = q;
86 r->left = q->right;
87 q->left = (*rootp)->left;
88 q->right = (*rootp)->right;
89 }
90 }
91 free((struct node_t *) *rootp); /* D4: Free node */
92 *rootp = q; /* link parent to new node */
93 return(p);
94}
95
96/* Walk the nodes of a tree */
97static void
98trecurse(root, action, level)
99 register node *root; /* Root of the tree to be walked */
100 register void (*action)(); /* Function to be called at each node */
101 register int level;
102{
103 if (root->left == (struct node_t *)0 && root->right == (struct node_t *)0)
104 (*action)(root, leaf, level);
105 else {
106 (*action)(root, preorder, level);
107 if (root->left != (struct node_t *)0)
108 trecurse(root->left, action, level + 1);
109 (*action)(root, postorder, level);
110 if (root->right != (struct node_t *)0)
111 trecurse(root->right, action, level + 1);
112 (*action)(root, endorder, level);
113 }
114}
115
116/* Walk the nodes of a tree */
117void
118twalk(vroot, action)
119 const void *vroot; /* Root of the tree to be walked */
120 void (*action)(const void *, VISIT, int);
121{
122 node *root = (node *)vroot;
123
124 if (root != (node *)0 && action != (void(*)())0)
125 trecurse(root, action, 0);
126}
diff --git a/src/lib/libc/string/Makefile.inc b/src/lib/libc/string/Makefile.inc
index 2b7ce63a63..26e2bc10f2 100644
--- a/src/lib/libc/string/Makefile.inc
+++ b/src/lib/libc/string/Makefile.inc
@@ -1,23 +1,22 @@
1# from: @(#)Makefile.inc 5.6 (Berkeley) 3/5/91 1# $OpenBSD: Makefile.inc,v 1.12 2003/02/20 03:20:09 deraadt Exp $
2# $Id: Makefile.inc,v 1.1.1.1 1995/10/18 08:42:20 deraadt Exp $
3 2
4# string sources 3# string sources
5.PATH: ${.CURDIR}/arch/${MACHINE_ARCH}/string ${.CURDIR}/string 4.PATH: ${LIBCSRCDIR}/arch/${MACHINE_ARCH}/string ${LIBCSRCDIR}/string
6 5
7SRCS+= bm.c memccpy.c strcasecmp.c strcoll.c strdup.c strerror.c \ 6SRCS+= bm.c memccpy.c strcasecmp.c strcoll.c strdup.c strerror.c \
8 strftime.c strmode.c strsignal.c strtok.c strxfrm.c \ 7 strerror_r.c strlcat.c strmode.c strsignal.c strtok.c strxfrm.c \
9 __strerror.c __strsignal.c 8 __strerror.c __strsignal.c
10 9
11# machine-dependent net sources 10# machine-dependent net sources
12# m-d Makefile.inc must include sources for: 11# m-d Makefile.inc must include sources for:
13# bcmp() bcopy() bzero() ffs() index() memchr() memcmp() memset() 12# bcmp() bcopy() bzero() ffs() index() memchr() memcmp() memset()
14# rindex() strcat() strcmp() strcpy() strcspn() strlen() 13# rindex() strcat() strcmp() strcpy() strcspn() strlen() strlcpy()
15# strncat() strncmp() strncpy() strpbrk() strsep() 14# strncat() strncmp() strncpy() strpbrk() strsep()
16# strspn() strstr() swav() 15# strspn() strstr() swav()
17# m-d Makefile.inc may include sources for: 16# m-d Makefile.inc may include sources for:
18# memcpy() memmove() strchr() strrchr() 17# memcpy() memmove() strchr() strrchr()
19 18
20.include "${.CURDIR}/arch/${MACHINE_ARCH}/string/Makefile.inc" 19.include "${LIBCSRCDIR}/arch/${MACHINE_ARCH}/string/Makefile.inc"
21 20
22# if no machine specific memmove(3), build one out of bcopy(3). 21# if no machine specific memmove(3), build one out of bcopy(3).
23.if empty(SRCS:Mmemmove.S) 22.if empty(SRCS:Mmemmove.S)
@@ -27,6 +26,11 @@ memmove.o: bcopy.c
27 @${LD} -x -r ${.TARGET} 26 @${LD} -x -r ${.TARGET}
28 @mv a.out ${.TARGET} 27 @mv a.out ${.TARGET}
29 28
29memmove.go: bcopy.c
30 ${CC} -g -DMEMMOVE ${CFLAGS} ${CPPFLAGS} -c ${.ALLSRC} -o ${.TARGET}
31 @${LD} -x -r ${.TARGET}
32 @mv a.out ${.TARGET}
33
30memmove.po: bcopy.c 34memmove.po: bcopy.c
31 ${CC} -DMEMMOVE ${CFLAGS} ${CPPFLAGS} -c -p ${.ALLSRC} -o ${.TARGET} 35 ${CC} -DMEMMOVE ${CFLAGS} ${CPPFLAGS} -c -p ${.ALLSRC} -o ${.TARGET}
32 @${LD} -X -r ${.TARGET} 36 @${LD} -X -r ${.TARGET}
@@ -48,6 +52,11 @@ memcpy.o: bcopy.c
48 @${LD} -x -r ${.TARGET} 52 @${LD} -x -r ${.TARGET}
49 @mv a.out ${.TARGET} 53 @mv a.out ${.TARGET}
50 54
55memcpy.go: bcopy.c
56 ${CC} -g -DMEMCOPY ${CFLAGS} ${CPPFLAGS} -c ${.ALLSRC} -o ${.TARGET}
57 @${LD} -x -r ${.TARGET}
58 @mv a.out ${.TARGET}
59
51memcpy.po: bcopy.c 60memcpy.po: bcopy.c
52 ${CC} -DMEMCOPY ${CFLAGS} ${CPPFLAGS} -c -p ${.ALLSRC} -o ${.TARGET} 61 ${CC} -DMEMCOPY ${CFLAGS} ${CPPFLAGS} -c -p ${.ALLSRC} -o ${.TARGET}
53 @${LD} -X -r ${.TARGET} 62 @${LD} -X -r ${.TARGET}
@@ -67,6 +76,11 @@ strchr.o: index.c
67 @${LD} -x -r ${.TARGET} 76 @${LD} -x -r ${.TARGET}
68 @mv a.out ${.TARGET} 77 @mv a.out ${.TARGET}
69 78
79strchr.go: index.c
80 ${CC} -g -DSTRCHR ${CFLAGS} ${CPPFLAGS} -c ${.ALLSRC} -o ${.TARGET}
81 @${LD} -x -r ${.TARGET}
82 @mv a.out ${.TARGET}
83
70strchr.po: index.c 84strchr.po: index.c
71 ${CC} -DSTRCHR ${CFLAGS} ${CPPFLAGS} -c -p ${.ALLSRC} -o ${.TARGET} 85 ${CC} -DSTRCHR ${CFLAGS} ${CPPFLAGS} -c -p ${.ALLSRC} -o ${.TARGET}
72 @${LD} -X -r ${.TARGET} 86 @${LD} -X -r ${.TARGET}
@@ -85,6 +99,11 @@ strrchr.o: rindex.c
85 @${LD} -x -r ${.TARGET} 99 @${LD} -x -r ${.TARGET}
86 @mv a.out ${.TARGET} 100 @mv a.out ${.TARGET}
87 101
102strrchr.go: rindex.c
103 ${CC} -g -DSTRRCHR ${CFLAGS} ${CPPFLAGS} -c ${.ALLSRC} -o ${.TARGET}
104 @${LD} -x -r ${.TARGET}
105 @mv a.out ${.TARGET}
106
88strrchr.po: rindex.c 107strrchr.po: rindex.c
89 ${CC} -DSTRRCHR ${CFLAGS} ${CPPFLAGS} -c -p ${.ALLSRC} -o ${.TARGET} 108 ${CC} -DSTRRCHR ${CFLAGS} ${CPPFLAGS} -c -p ${.ALLSRC} -o ${.TARGET}
90 @${LD} -X -r ${.TARGET} 109 @${LD} -X -r ${.TARGET}
@@ -95,14 +114,39 @@ strrchr.so: rindex.c
95 -o ${.TARGET} 114 -o ${.TARGET}
96.endif 115.endif
97 116
98MAN+= bm.3 bcmp.3 bcopy.3 bstring.3 bzero.3 ffs.3 index.3 memccpy.3 memchr.3 \ 117# build .ln files for memmove, memcpy, strchr and strrchr always from
99 memcmp.3 memcpy.3 memmove.3 memset.3 rindex.3 strcasecmp.3 strcat.3 \ 118# bcopy, index, and rindex
100 strchr.3 strcmp.3 strcoll.3 strcpy.3 strcspn.3 strerror.3 strftime.3 \ 119LOBJS+= memmove.ln memcpy.ln strchr.ln strrchr.ln
120
121memmove.ln: bcopy.c
122 lint ${LINTFLAGS} -DMEMMOVE ${CFLAGS:M-[IDU]*} -i -o ${.TARGET} \
123 ${LIBCSRCDIR}/string/bcopy.c
124
125memcpy.ln: bcopy.c
126 lint ${LINTFLAGS} -DMEMCOPY ${CFLAGS:M-[IDU]*} -i -o ${.TARGET} \
127 ${LIBCSRCDIR}/string/bcopy.c
128
129strchr.ln: index.c
130 lint ${LINTFLAGS} -DSTRCHR ${CFLAGS:M-[IDU]*} -i -o ${.TARGET} \
131 ${LIBCSRCDIR}/string/index.c
132
133strrchr.ln: rindex.c
134 lint ${LINTFLAGS} -DSTRRCHR ${CFLAGS:M-[IDU]*} -i -o ${.TARGET} \
135 ${LIBCSRCDIR}/string/rindex.c
136
137MAN+= bm.3 bcmp.3 bcopy.3 bstring.3 bzero.3 ffs.3 memccpy.3 memchr.3 \
138 memcmp.3 memcpy.3 memmove.3 memset.3 strcasecmp.3 strcat.3 \
139 strchr.3 strcmp.3 strcoll.3 strcpy.3 strcspn.3 strerror.3 \
101 string.3 strlen.3 strmode.3 strdup.3 strpbrk.3 strrchr.3 strsep.3 \ 140 string.3 strlen.3 strmode.3 strdup.3 strpbrk.3 strrchr.3 strsep.3 \
102 strsignal.3 strspn.3 strstr.3 strtok.3 strxfrm.3 swab.3 141 strsignal.3 strspn.3 strstr.3 strtok.3 strxfrm.3 swab.3 strlcpy.3
103 142
104MLINKS+=bm.3 bm_comp.3 bm.3 bm_exec.3 bm.3 bm_free.3 143MLINKS+=bm.3 bm_comp.3 bm.3 bm_exec.3 bm.3 bm_free.3
144MLINKS+=strchr.3 index.3
145MLINKS+=strrchr.3 rindex.3
105MLINKS+=strcasecmp.3 strncasecmp.3 146MLINKS+=strcasecmp.3 strncasecmp.3
106MLINKS+=strcat.3 strncat.3 147MLINKS+=strcat.3 strncat.3
107MLINKS+=strcmp.3 strncmp.3 148MLINKS+=strcmp.3 strncmp.3
108MLINKS+=strcpy.3 strncpy.3 149MLINKS+=strcpy.3 strncpy.3
150MLINKS+=strlcpy.3 strlcat.3
151MLINKS+=strtok.3 strtok_r.3
152MLINKS+=strerror.3 strerror_r.3
diff --git a/src/lib/libc/string/__strerror.c b/src/lib/libc/string/__strerror.c
index cd604906db..7301a7bc84 100644
--- a/src/lib/libc/string/__strerror.c
+++ b/src/lib/libc/string/__strerror.c
@@ -32,8 +32,7 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)strerror.c 5.6 (Berkeley) 5/4/91";*/ 35static char *rcsid = "$OpenBSD: __strerror.c,v 1.9 2003/03/13 15:47:33 deraadt Exp $";
36static char *rcsid = "$Id: __strerror.c,v 1.1.1.1 1995/10/18 08:42:20 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
38 37
39#ifdef NLS 38#ifdef NLS
@@ -46,9 +45,27 @@ static char *rcsid = "$Id: __strerror.c,v 1.1.1.1 1995/10/18 08:42:20 deraadt Ex
46#define sys_errlist _sys_errlist 45#define sys_errlist _sys_errlist
47#define sys_nerr _sys_nerr 46#define sys_nerr _sys_nerr
48 47
48#include <errno.h>
49#include <limits.h>
49#include <stdio.h> 50#include <stdio.h>
50#include <string.h> 51#include <string.h>
51 52
53static char *
54itoa(num)
55 int num;
56{
57 static char buffer[11];
58 char *p;
59
60 p = buffer + 4;
61 while (num >= 10) {
62 *--p = (num % 10) + '0';
63 num /= 10;
64 }
65 *p = (num % 10) + '0';
66 return p;
67}
68
52/* 69/*
53 * Since perror() is not allowed to change the contents of strerror()'s 70 * Since perror() is not allowed to change the contents of strerror()'s
54 * static buffer, both functions supply their own buffers to the 71 * static buffer, both functions supply their own buffers to the
@@ -60,32 +77,37 @@ __strerror(num, buf)
60 int num; 77 int num;
61 char *buf; 78 char *buf;
62{ 79{
63#define UPREFIX "Unknown error: %u" 80#define UPREFIX "Unknown error: "
64 register unsigned int errnum; 81 register unsigned int errnum;
65
66#ifdef NLS 82#ifdef NLS
67 nl_catd catd ; 83 int save_errno;
84 nl_catd catd;
85
68 catd = catopen("libc", 0); 86 catd = catopen("libc", 0);
69#endif 87#endif
70 88
71 errnum = num; /* convert to unsigned */ 89 errnum = num; /* convert to unsigned */
72 if (errnum < sys_nerr) { 90 if (errnum < sys_nerr) {
73#ifdef NLS 91#ifdef NLS
74 strcpy(buf, catgets(catd, 1, errnum, 92 strlcpy(buf, catgets(catd, 1, errnum,
75 (char *)sys_errlist[errnum])); 93 (char *)sys_errlist[errnum]), NL_TEXTMAX);
76#else 94#else
77 return(sys_errlist[errnum]); 95 return(sys_errlist[errnum]);
78#endif 96#endif
79 } else { 97 } else {
80#ifdef NLS 98#ifdef NLS
81 sprintf(buf, catgets(catd, 1, 0xffff, UPREFIX), errnum); 99 strlcpy(buf, catgets(catd, 1, 0xffff, UPREFIX), NL_TEXTMAX);
82#else 100#else
83 sprintf(buf, UPREFIX, errnum); 101 strlcpy(buf, UPREFIX, NL_TEXTMAX);
84#endif 102#endif
103 strlcat(buf, itoa(errnum), NL_TEXTMAX);
104 errno = EINVAL;
85 } 105 }
86 106
87#ifdef NLS 107#ifdef NLS
108 save_errno = errno;
88 catclose(catd); 109 catclose(catd);
110 errno = save_errno;
89#endif 111#endif
90 112
91 return buf; 113 return buf;
diff --git a/src/lib/libc/string/__strsignal.c b/src/lib/libc/string/__strsignal.c
index 1937e2d608..2616872232 100644
--- a/src/lib/libc/string/__strsignal.c
+++ b/src/lib/libc/string/__strsignal.c
@@ -32,8 +32,7 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)strerror.c 5.6 (Berkeley) 5/4/91";*/ 35static char *rcsid = "$OpenBSD: __strsignal.c,v 1.7 2003/03/13 15:47:33 deraadt Exp $";
36static char *rcsid = "$Id: __strsignal.c,v 1.1.1.1 1995/10/18 08:42:20 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
38 37
39#ifdef NLS 38#ifdef NLS
@@ -46,15 +45,31 @@ static char *rcsid = "$Id: __strsignal.c,v 1.1.1.1 1995/10/18 08:42:20 deraadt E
46#define sys_siglist _sys_siglist 45#define sys_siglist _sys_siglist
47 46
48#include <stdio.h> 47#include <stdio.h>
48#include <limits.h>
49#include <signal.h> 49#include <signal.h>
50#include <string.h> 50#include <string.h>
51 51
52static char *itoa(num)
53 int num;
54{
55 static char buffer[11];
56 char *p;
57
58 p = buffer + 4;
59 while (num >= 10) {
60 *--p = (num % 10) + '0';
61 num /= 10;
62 }
63 *p = (num % 10) + '0';
64 return p;
65}
66
52char * 67char *
53__strsignal(num, buf) 68__strsignal(num, buf)
54 int num; 69 int num;
55 char *buf; 70 char *buf;
56{ 71{
57#define UPREFIX "Unknown signal: %u" 72#define UPREFIX "Unknown signal: "
58 register unsigned int signum; 73 register unsigned int signum;
59 74
60#ifdef NLS 75#ifdef NLS
@@ -65,17 +80,18 @@ __strsignal(num, buf)
65 signum = num; /* convert to unsigned */ 80 signum = num; /* convert to unsigned */
66 if (signum < NSIG) { 81 if (signum < NSIG) {
67#ifdef NLS 82#ifdef NLS
68 strcpy(buf, catgets(catd, 2, signum, 83 strlcpy(buf, catgets(catd, 2, signum,
69 (char *)sys_siglist[signum])); 84 (char *)sys_siglist[signum]), NL_TEXTMAX);
70#else 85#else
71 return((char *)sys_siglist[signum]); 86 return((char *)sys_siglist[signum]);
72#endif 87#endif
73 } else { 88 } else {
74#ifdef NLS 89#ifdef NLS
75 sprintf(buf, catgets(catd, 1, 0xffff, UPREFIX), signum); 90 strlcpy(buf, catgets(catd, 1, 0xffff, UPREFIX), NL_TEXTMAX);
76#else 91#else
77 sprintf(buf, UPREFIX, signum); 92 strlcpy(buf, UPREFIX, NL_TEXTMAX);
78#endif 93#endif
94 strlcat(buf, itoa(signum), NL_TEXTMAX);
79 } 95 }
80 96
81#ifdef NLS 97#ifdef NLS
diff --git a/src/lib/libc/string/bcmp.3 b/src/lib/libc/string/bcmp.3
index 118c55c579..d880c1e6f0 100644
--- a/src/lib/libc/string/bcmp.3
+++ b/src/lib/libc/string/bcmp.3
@@ -31,12 +31,11 @@
31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32.\" SUCH DAMAGE. 32.\" SUCH DAMAGE.
33.\" 33.\"
34.\" from: @(#)bcmp.3 5.4 (Berkeley) 4/19/91 34.\" $OpenBSD: bcmp.3,v 1.5 2000/04/21 15:24:18 aaron Exp $
35.\" $Id: bcmp.3,v 1.1.1.1 1995/10/18 08:42:20 deraadt Exp $
36.\" 35.\"
37.Dd April 19, 1991 36.Dd April 19, 1991
38.Dt BCMP 3 37.Dt BCMP 3
39.Os BSD 4.2 38.Os
40.Sh NAME 39.Sh NAME
41.Nm bcmp 40.Nm bcmp
42.Nd compare byte string 41.Nd compare byte string
@@ -47,8 +46,7 @@
47.Sh DESCRIPTION 46.Sh DESCRIPTION
48The 47The
49.Fn bcmp 48.Fn bcmp
50function 49function compares byte string
51compares byte string
52.Fa b1 50.Fa b1
53against byte string 51against byte string
54.Fa b2 , 52.Fa b2 ,
@@ -68,5 +66,5 @@ The strings may overlap.
68.Sh HISTORY 66.Sh HISTORY
69A 67A
70.Fn bcmp 68.Fn bcmp
71function first appeared in 69function first appeared in
72.Bx 4.2 . 70.Bx 4.2 .
diff --git a/src/lib/libc/string/bcmp.c b/src/lib/libc/string/bcmp.c
index 2cc38baee3..4ed00975a4 100644
--- a/src/lib/libc/string/bcmp.c
+++ b/src/lib/libc/string/bcmp.c
@@ -32,15 +32,19 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)bcmp.c 5.6 (Berkeley) 2/24/91";*/ 35static char *rcsid = "$OpenBSD: bcmp.c,v 1.4 1996/08/19 08:33:57 tholo Exp $";
36static char *rcsid = "$Id: bcmp.c,v 1.1.1.1 1995/10/18 08:42:20 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
38 37
38#ifndef _KERNEL
39#include <string.h> 39#include <string.h>
40#else
41#include <lib/libkern/libkern.h>
42#endif
40 43
41/* 44/*
42 * bcmp -- vax cmpc3 instruction 45 * bcmp -- vax cmpc3 instruction
43 */ 46 */
47int
44bcmp(b1, b2, length) 48bcmp(b1, b2, length)
45 const void *b1, *b2; 49 const void *b1, *b2;
46 register size_t length; 50 register size_t length;
diff --git a/src/lib/libc/string/bcopy.3 b/src/lib/libc/string/bcopy.3
index 6db3812caf..12bd248abf 100644
--- a/src/lib/libc/string/bcopy.3
+++ b/src/lib/libc/string/bcopy.3
@@ -32,12 +32,11 @@
32.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33.\" SUCH DAMAGE. 33.\" SUCH DAMAGE.
34.\" 34.\"
35.\" from: @(#)bcopy.3 5.3 (Berkeley) 4/19/91 35.\" $OpenBSD: bcopy.3,v 1.6 2003/04/07 18:53:58 deraadt Exp $
36.\" $Id: bcopy.3,v 1.1.1.1 1995/10/18 08:42:20 deraadt Exp $
37.\" 36.\"
38.Dd April 19, 1991 37.Dd April 19, 1991
39.Dt BCOPY 3 38.Dt BCOPY 3
40.Os BSD 4.2 39.Os
41.Sh NAME 40.Sh NAME
42.Nm bcopy 41.Nm bcopy
43.Nd copy byte string 42.Nd copy byte string
@@ -48,8 +47,7 @@
48.Sh DESCRIPTION 47.Sh DESCRIPTION
49The 48The
50.Fn bcopy 49.Fn bcopy
51function 50function copies
52copies
53.Fa len 51.Fa len
54bytes from string 52bytes from string
55.Fa src 53.Fa src
@@ -64,9 +62,10 @@ is zero, no bytes are copied.
64.Xr memcpy 3 , 62.Xr memcpy 3 ,
65.Xr memmove 3 , 63.Xr memmove 3 ,
66.Xr strcpy 3 , 64.Xr strcpy 3 ,
65.Xr strlcpy 3 ,
67.Xr strncpy 3 66.Xr strncpy 3
68.Sh HISTORY 67.Sh HISTORY
69A 68A
70.Fn bcopy 69.Fn bcopy
71function appeared in 70function appeared in
72.Bx 4.2 . 71.Bx 4.2 .
diff --git a/src/lib/libc/string/bcopy.c b/src/lib/libc/string/bcopy.c
index 92feed66ea..023a3b2db2 100644
--- a/src/lib/libc/string/bcopy.c
+++ b/src/lib/libc/string/bcopy.c
@@ -35,8 +35,7 @@
35 */ 35 */
36 36
37#if defined(LIBC_SCCS) && !defined(lint) 37#if defined(LIBC_SCCS) && !defined(lint)
38/*static char *sccsid = "from: @(#)bcopy.c 5.11 (Berkeley) 6/21/91";*/ 38static char *rcsid = "$OpenBSD: bcopy.c,v 1.2 1996/08/19 08:33:58 tholo Exp $";
39static char *rcsid = "$Id: bcopy.c,v 1.1.1.1 1995/10/18 08:42:20 deraadt Exp $";
40#endif /* LIBC_SCCS and not lint */ 39#endif /* LIBC_SCCS and not lint */
41 40
42#include <string.h> 41#include <string.h>
diff --git a/src/lib/libc/string/bm.3 b/src/lib/libc/string/bm.3
index 2264a6a1c4..7138ee4271 100644
--- a/src/lib/libc/string/bm.3
+++ b/src/lib/libc/string/bm.3
@@ -32,83 +32,84 @@
32.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33.\" SUCH DAMAGE. 33.\" SUCH DAMAGE.
34.\" 34.\"
35.\" from: @(#)bm.3 8.4 (Berkeley) 6/21/94 35.\" $OpenBSD: bm.3,v 1.6 2001/06/23 14:42:12 deraadt Exp $
36.\" $Id: bm.3,v 1.1.1.1 1995/10/18 08:42:20 deraadt Exp $
37.\" 36.\"
38.TH BM 3 37.Dd June 29, 1999
39.SH NAME 38.Dt BM 3
40bm_comp, bm_exec, bm_free \- Boyer-Moore string search 39.Os
41.SH SYNOPSIS 40.Sh NAME
42.ft B 41.Nm bm_comp ,
43#include <sys/types.h> 42.Nm bm_exec ,
44.br 43.Nm bm_free
45#include <bm.h> 44.Nd Boyer-Moore string search
46.sp 45.Sh SYNOPSIS
47bm_pat * 46.Fd #include <sys/types.h>
48.br 47.Fd #include <bm.h>
49bm_comp(u_char *pattern, size_t patlen, u_char freq[256]); 48.Ft bm_pat *
50.sp 49.Fn bm_comp "u_char *pattern" "size_t patlen" "u_char freq[256]"
51u_char * 50.Ft u_char *
52.br 51.Fn bm_exec "bm_pat *pdesc" "u_char *text" "size_t len"
53bm_exec(bm_pat *pdesc, u_char *text, size_t len); 52.Ft void
54.sp 53.Fn bm_free "bm_pat *pdesc"
55void 54.Sh DESCRIPTION
56.br
57bm_free(bm_pat *pdesc);
58.SH DESCRIPTION
59These routines implement an efficient mechanism to find an 55These routines implement an efficient mechanism to find an
60occurrence of a byte string within another byte string. 56occurrence of a byte string within another byte string.
61.PP 57.Pp
62.I Bm_comp 58.Fn bm_comp
63evaluates the 59evaluates
64.I patlen 60.Fa patlen
65bytes starting at 61bytes starting at
66.IR pattern , 62.Fa pattern
67and returns a pointer to a structure describing them. 63and returns a pointer to a structure describing them.
68The bytes referenced by 64The bytes referenced by
69.I pattern 65.Fa pattern
70may be of any value. 66may be of any value.
71.PP 67.Pp
72The search takes advantage of the frequency distribution of the 68The search takes advantage of the frequency distribution of the
73bytes in the text to be searched. 69bytes in the text to be searched.
74If specified, 70If specified,
75.I freq 71.Ar freq
76should be an array of 256 values, 72should be an array of 256 values,
77with higher values indicating that the corresponding character occurs 73with higher values indicating that the corresponding character occurs
78more frequently. 74more frequently.
79(A less than optimal frequency distribution can only result in less 75(A less than optimal frequency distribution can only result in less
80than optimal performance, not incorrect results.) 76than optimal performance, not incorrect results.)
81If 77If
82.I freq 78.Ar freq
83is NULL, 79is
80.Dv NULL ,
84a system default table is used. 81a system default table is used.
85.PP 82.Pp
86.I Bm_exec 83.Fn bm_exec
87returns a pointer to the leftmost occurrence of the string given to 84returns a pointer to the leftmost occurrence of the string given to
88.I bm_comp 85.Fn bm_comp
89within 86within
90.IR text , 87.Ar text ,
91or NULL if none occurs. 88or
89.Dv NULL
90if none occurs.
92The number of bytes in 91The number of bytes in
93.I text 92.Ar text
94must be specified by 93must be specified by
95.IR len . 94.Ar len .
96.PP 95.Pp
97Space allocated for the returned description is discarded 96Space allocated for the returned description is discarded
98by calling 97by calling
99.I bm_free 98.Fn bm_free
100with the returned description as an argument. 99with the returned description as an argument.
101.PP 100.Pp
102The asymptotic speed of 101The asymptotic speed of
103.I bm_exec 102.Fn bm_exec
104is 103is
105.RI O( len / patlen ). 104.Pf O Ns Pq len / patlen .
106.PP 105.Sh SEE ALSO
107.SH "SEE ALSO" 106.Xr regexp 3 ,
108.IR regexp (3), 107.Xr strstr 3
109.IR strstr (3) 108.Rs
110.sp 109.%R "Fast String Searching"
111.IR "Fast String Searching" , 110.%A Andrew Hume
112Hume and Sunday, 111.%A Daniel Sunday
113Software Practice and Experience, 112.%J "Software Practice and Experience"
114Vol. 21, 11 (November 1991) pp. 1221-48. 113.%V Volume 21, 11 (November 1991)
114.%P 1221-48
115.Re
diff --git a/src/lib/libc/string/bm.c b/src/lib/libc/string/bm.c
index 68eac22ecc..b191d340f6 100644
--- a/src/lib/libc/string/bm.c
+++ b/src/lib/libc/string/bm.c
@@ -34,10 +34,9 @@
34 * SUCH DAMAGE. 34 * SUCH DAMAGE.
35 */ 35 */
36 36
37#ifndef lint 37#if defined(LIBC_SCCS) && !defined(lint)
38/* from: static char sccsid[] = "@(#)bm.c 8.7 (Berkeley) 6/21/94"; */ 38static char *rcsid = "$OpenBSD: bm.c,v 1.3 1996/08/19 08:33:59 tholo Exp $";
39static char *rcsid = "$Id: bm.c,v 1.1.1.1 1995/10/18 08:42:20 deraadt Exp $"; 39#endif /* LIBC_SCCS and not lint */
40#endif /* not lint */
41 40
42#include <sys/types.h> 41#include <sys/types.h>
43 42
diff --git a/src/lib/libc/string/bstring.3 b/src/lib/libc/string/bstring.3
index 12fcfb0cc1..85283321c8 100644
--- a/src/lib/libc/string/bstring.3
+++ b/src/lib/libc/string/bstring.3
@@ -31,8 +31,7 @@
31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32.\" SUCH DAMAGE. 32.\" SUCH DAMAGE.
33.\" 33.\"
34.\" from: @(#)bstring.3 6.8 (Berkeley) 4/19/91 34.\" $OpenBSD: bstring.3,v 1.4 2000/04/21 15:24:19 aaron Exp $
35.\" $Id: bstring.3,v 1.1.1.1 1995/10/18 08:42:21 deraadt Exp $
36.\" 35.\"
37.Dd April 19, 1991 36.Dd April 19, 1991
38.Dt BSTRING 3 37.Dt BSTRING 3
@@ -45,7 +44,7 @@
45.Nm memchr , 44.Nm memchr ,
46.Nm memcmp , 45.Nm memcmp ,
47.Nm memcpy , 46.Nm memcpy ,
48.Nm memmove, 47.Nm memmove ,
49.Nm memset 48.Nm memset
50.Nd byte string operations 49.Nd byte string operations
51.Sh SYNOPSIS 50.Sh SYNOPSIS
@@ -97,14 +96,15 @@ and
97conform to 96conform to
98.St -ansiC . 97.St -ansiC .
99.Sh HISTORY 98.Sh HISTORY
100The functions 99The
101.Fn bzero 100.Fn bzero
102and 101and
103.Fn memccpy 102.Fn memccpy
104appeared in 103functions appeared in
105.Bx 4.3 ; 104.Bx 4.3 .
106the functions 105The
107.Fn bcmp , 106.Fn bcmp
108.Fn bcopy , 107and
109appeared in 108.Fn bcopy
109functions appeared in
110.Bx 4.2 . 110.Bx 4.2 .
diff --git a/src/lib/libc/string/bzero.3 b/src/lib/libc/string/bzero.3
index 4f0141e051..a735d5ef3f 100644
--- a/src/lib/libc/string/bzero.3
+++ b/src/lib/libc/string/bzero.3
@@ -31,12 +31,11 @@
31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32.\" SUCH DAMAGE. 32.\" SUCH DAMAGE.
33.\" 33.\"
34.\" from: @(#)bzero.3 5.3 (Berkeley) 4/19/91 34.\" $OpenBSD: bzero.3,v 1.5 2000/04/21 15:24:19 aaron Exp $
35.\" $Id: bzero.3,v 1.1.1.1 1995/10/18 08:42:21 deraadt Exp $
36.\" 35.\"
37.Dd April 19, 1991 36.Dd April 19, 1991
38.Dt BZERO 3 37.Dt BZERO 3
39.Os BSD 4.3 38.Os
40.Sh NAME 39.Sh NAME
41.Nm bzero 40.Nm bzero
42.Nd write zeroes to a byte string 41.Nd write zeroes to a byte string
@@ -47,8 +46,7 @@
47.Sh DESCRIPTION 46.Sh DESCRIPTION
48The 47The
49.Fn bzero 48.Fn bzero
50function 49function writes
51writes
52.Fa len 50.Fa len
53zero bytes to the string 51zero bytes to the string
54.Fa b . 52.Fa b .
@@ -63,6 +61,5 @@ does nothing.
63.Sh HISTORY 61.Sh HISTORY
64A 62A
65.Fn bzero 63.Fn bzero
66function 64function appeared in
67appeared in
68.Bx 4.3 . 65.Bx 4.3 .
diff --git a/src/lib/libc/string/bzero.c b/src/lib/libc/string/bzero.c
index 4865e396ef..3e660a307f 100644
--- a/src/lib/libc/string/bzero.c
+++ b/src/lib/libc/string/bzero.c
@@ -32,11 +32,14 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)bzero.c 5.7 (Berkeley) 2/24/91";*/ 35static char *rcsid = "$OpenBSD: bzero.c,v 1.3 1996/08/19 08:34:00 tholo Exp $";
36static char *rcsid = "$Id: bzero.c,v 1.1.1.1 1995/10/18 08:42:21 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
38 37
38#ifndef _KERNEL
39#include <string.h> 39#include <string.h>
40#else
41#include <lib/libkern/libkern.h>
42#endif
40 43
41/* 44/*
42 * bzero -- vax movc5 instruction 45 * bzero -- vax movc5 instruction
diff --git a/src/lib/libc/string/ffs.3 b/src/lib/libc/string/ffs.3
index 6464bea2b1..dc7a20741e 100644
--- a/src/lib/libc/string/ffs.3
+++ b/src/lib/libc/string/ffs.3
@@ -31,8 +31,7 @@
31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32.\" SUCH DAMAGE. 32.\" SUCH DAMAGE.
33.\" 33.\"
34.\" from: @(#)ffs.3 5.3 (Berkeley) 4/19/91 34.\" $OpenBSD: ffs.3,v 1.3 2000/04/21 15:24:19 aaron Exp $
35.\" $Id: ffs.3,v 1.1.1.1 1995/10/18 08:42:21 deraadt Exp $
36.\" 35.\"
37.Dd April 19, 1991 36.Dd April 19, 1991
38.Dt FFS 3 37.Dt FFS 3
@@ -47,12 +46,10 @@
47.Sh DESCRIPTION 46.Sh DESCRIPTION
48The 47The
49.Fn ffs 48.Fn ffs
50function 49function finds the first bit set in
51finds the first bit set in
52.Fa value 50.Fa value
53and returns the index of that bit. 51and returns the index of that bit.
54Bits are numbered starting from 1, starting at the right-most 52Bits are numbered starting from 1, starting at the rightmost bit.
55bit.
56A return value of 0 means that the argument was zero. 53A return value of 0 means that the argument was zero.
57.Sh SEE ALSO 54.Sh SEE ALSO
58.Xr bitstring 3 55.Xr bitstring 3
diff --git a/src/lib/libc/string/ffs.c b/src/lib/libc/string/ffs.c
index 42bc87ddea..887ce437d4 100644
--- a/src/lib/libc/string/ffs.c
+++ b/src/lib/libc/string/ffs.c
@@ -1,42 +1,19 @@
1/*- 1/* $OpenBSD: ffs.c,v 1.5 2000/07/02 03:10:38 mickey Exp $ */
2 * Copyright (c) 1990 The Regents of the University of California. 2
3 * All rights reserved. 3/*
4 * 4 * Public domain.
5 * Redistribution and use in source and binary forms, with or without 5 * Written by Dale Rahn.
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */ 6 */
33 7
34#if defined(LIBC_SCCS) && !defined(lint) 8#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)ffs.c 5.4 (Berkeley) 5/17/90";*/ 9static char *rcsid = "$OpenBSD: ffs.c,v 1.5 2000/07/02 03:10:38 mickey Exp $";
36static char *rcsid = "$Id: ffs.c,v 1.1.1.1 1995/10/18 08:42:21 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 10#endif /* LIBC_SCCS and not lint */
38 11
12#if !defined(_KERNEL) && !defined(_STANDALONE)
39#include <string.h> 13#include <string.h>
14#else
15#include <lib/libkern/libkern.h>
16#endif
40 17
41/* 18/*
42 * ffs -- vax ffs instruction 19 * ffs -- vax ffs instruction
@@ -46,10 +23,27 @@ ffs(mask)
46 register int mask; 23 register int mask;
47{ 24{
48 register int bit; 25 register int bit;
26 register unsigned int r = mask;
27 static const signed char t[16] = {
28 -28, 1, 2, 1,
29 3, 1, 2, 1,
30 4, 1, 2, 1,
31 3, 1, 2, 1
32 };
33
34 bit = 0;
35 if (!(r & 0xffff)) {
36 bit += 16;
37 r >>= 16;
38 }
39 if (!(r & 0xff)) {
40 bit += 8;
41 r >>= 8;
42 }
43 if (!(r & 0xf)) {
44 bit += 4;
45 r >>= 4;
46 }
49 47
50 if (mask == 0) 48 return (bit + t[ r & 0xf ]);
51 return(0);
52 for (bit = 1; !(mask & 1); bit++)
53 mask >>= 1;
54 return(bit);
55} 49}
diff --git a/src/lib/libc/string/index.c b/src/lib/libc/string/index.c
index 3d9c05f961..8e4b146493 100644
--- a/src/lib/libc/string/index.c
+++ b/src/lib/libc/string/index.c
@@ -32,19 +32,17 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)index.c 5.7 (Berkeley) 2/24/91";*/ 35static char *rcsid = "$OpenBSD: index.c,v 1.3 2002/07/24 04:16:01 millert Exp $";
36static char *rcsid = "$Id: index.c,v 1.1.1.1 1995/10/18 08:42:21 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
38 37
39#include <string.h> 38#include <string.h>
40 39
41char * 40char *
42#ifdef STRCHR 41#ifdef STRCHR
43strchr(p, ch) 42strchr(const char *p, int ch)
44#else 43#else
45index(p, ch) 44index(const char *p, int ch)
46#endif 45#endif
47 register const char *p, ch;
48{ 46{
49 for (;; ++p) { 47 for (;; ++p) {
50 if (*p == ch) 48 if (*p == ch)
diff --git a/src/lib/libc/string/memccpy.3 b/src/lib/libc/string/memccpy.3
index 61df704028..007fa44274 100644
--- a/src/lib/libc/string/memccpy.3
+++ b/src/lib/libc/string/memccpy.3
@@ -1,5 +1,7 @@
1.\" Copyright (c) 1990, 1991 The Regents of the University of California. 1.\" $OpenBSD: memccpy.3,v 1.7 2003/04/07 18:53:58 deraadt Exp $
2.\" All rights reserved. 2.\"
3.\" Copyright (c) 1990, 1991, 1993
4.\" The Regents of the University of California. All rights reserved.
3.\" 5.\"
4.\" Redistribution and use in source and binary forms, with or without 6.\" Redistribution and use in source and binary forms, with or without
5.\" modification, are permitted provided that the following conditions 7.\" modification, are permitted provided that the following conditions
@@ -29,14 +31,14 @@
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE. 32.\" SUCH DAMAGE.
31.\" 33.\"
32.\" from: @(#)memccpy.3 5.4 (Berkeley) 4/19/91 34.\" @(#)memccpy.3 8.1 (Berkeley) 6/9/93
33.\" $Id: memccpy.3,v 1.1.1.1 1995/10/18 08:42:21 deraadt Exp $
34.\" 35.\"
35.Dd April 19, 1991 36.Dd June 9, 1993
36.Dt MEMCCPY 3 37.Dt MEMCCPY 3
37.Os 38.Os
38.Sh NAME 39.Sh NAME
39.Nm memccpy 40.Nm memccpy
41.Nd copy string until character found
40.Sh SYNOPSIS 42.Sh SYNOPSIS
41.Fd #include <string.h> 43.Fd #include <string.h>
42.Ft void * 44.Ft void *
@@ -44,14 +46,15 @@
44.Sh DESCRIPTION 46.Sh DESCRIPTION
45The 47The
46.Fn memccpy 48.Fn memccpy
47function 49function copies bytes from string
48copies bytes from string
49.Fa src 50.Fa src
50to string 51to string
51.Fa dst . 52.Fa dst .
52If the character 53If the character
53.Fa c 54.Fa c
54(as converted to an unsigned char) occurs in the string 55(as converted to an
56.Li unsigned char )
57occurs in the string
55.Fa src , 58.Fa src ,
56the copy stops and a pointer to the byte after the copy of 59the copy stops and a pointer to the byte after the copy of
57.Fa c 60.Fa c
@@ -60,14 +63,15 @@ in the string
60is returned. 63is returned.
61Otherwise, 64Otherwise,
62.Fa len 65.Fa len
63bytes are copied, and a NULL pointer is returned. 66bytes are copied, and a null pointer is returned.
64.Sh SEE ALSO 67.Sh SEE ALSO
65.Xr bcopy 3 , 68.Xr bcopy 3 ,
66.Xr memcpy 3 , 69.Xr memcpy 3 ,
67.Xr memmove 3 , 70.Xr memmove 3 ,
68.Xr strcpy 3 71.Xr strcpy 3 ,
72.Xr strlcpy 3
69.Sh HISTORY 73.Sh HISTORY
70The 74The
71.Fn memccpy 75.Fn memccpy
72function is 76function first appeared in
73.Ud . 77.Bx 4.4 .
diff --git a/src/lib/libc/string/memccpy.c b/src/lib/libc/string/memccpy.c
index 3a1d7bcca1..020e6e5679 100644
--- a/src/lib/libc/string/memccpy.c
+++ b/src/lib/libc/string/memccpy.c
@@ -1,6 +1,8 @@
1/* $OpenBSD: memccpy.c,v 1.3 1997/08/20 04:09:39 millert Exp $ */
2
1/*- 3/*-
2 * Copyright (c) 1990 The Regents of the University of California. 4 * Copyright (c) 1990, 1993
3 * All rights reserved. 5 * The Regents of the University of California. All rights reserved.
4 * 6 *
5 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
@@ -32,8 +34,11 @@
32 */ 34 */
33 35
34#if defined(LIBC_SCCS) && !defined(lint) 36#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)memccpy.c 5.8 (Berkeley) 5/30/91";*/ 37#if 0
36static char *rcsid = "$Id: memccpy.c,v 1.1.1.1 1995/10/18 08:42:21 deraadt Exp $"; 38static char sccsid[] = "@(#)memccpy.c 8.1 (Berkeley) 6/4/93";
39#else
40static char *rcsid = "$OpenBSD: memccpy.c,v 1.3 1997/08/20 04:09:39 millert Exp $";
41#endif
37#endif /* LIBC_SCCS and not lint */ 42#endif /* LIBC_SCCS and not lint */
38 43
39#include <string.h> 44#include <string.h>
diff --git a/src/lib/libc/string/memchr.3 b/src/lib/libc/string/memchr.3
index 265711e3b5..632c440b5b 100644
--- a/src/lib/libc/string/memchr.3
+++ b/src/lib/libc/string/memchr.3
@@ -33,8 +33,7 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)memchr.3 5.4 (Berkeley) 6/29/91 36.\" $OpenBSD: memchr.3,v 1.5 2000/04/21 15:24:19 aaron Exp $
37.\" $Id: memchr.3,v 1.1.1.1 1995/10/18 08:42:21 deraadt Exp $
38.\" 37.\"
39.Dd June 29, 1991 38.Dd June 29, 1991
40.Dt MEMCHR 3 39.Dt MEMCHR 3
@@ -49,23 +48,21 @@
49.Sh DESCRIPTION 48.Sh DESCRIPTION
50The 49The
51.Fn memchr 50.Fn memchr
52function 51function locates the first occurrence of
53locates the first occurrence of
54.Fa c 52.Fa c
55(converted to an unsigned char) 53(converted to an
54.Li unsigned char )
56in string 55in string
57.Fa b . 56.Fa b .
58.Sh RETURN VALUES 57.Sh RETURN VALUES
59The 58The
60.Fn memchr 59.Fn memchr
61function 60function returns a pointer to the byte located, or
62returns a pointer to the byte located, 61.Dv NULL
63or NULL if no such byte exists within 62if no such byte exists within
64.Fa len 63.Fa len
65bytes. 64bytes.
66.Sh SEE ALSO 65.Sh SEE ALSO
67.Xr index 3 ,
68.Xr rindex 3 ,
69.Xr strchr 3 , 66.Xr strchr 3 ,
70.Xr strcspn 3 , 67.Xr strcspn 3 ,
71.Xr strpbrk 3 , 68.Xr strpbrk 3 ,
@@ -77,6 +74,5 @@ bytes.
77.Sh STANDARDS 74.Sh STANDARDS
78The 75The
79.Fn memchr 76.Fn memchr
80function 77function conforms to
81conforms to
82.St -ansiC . 78.St -ansiC .
diff --git a/src/lib/libc/string/memchr.c b/src/lib/libc/string/memchr.c
index 61652c6bb1..d605d4734f 100644
--- a/src/lib/libc/string/memchr.c
+++ b/src/lib/libc/string/memchr.c
@@ -35,8 +35,7 @@
35 */ 35 */
36 36
37#if defined(LIBC_SCCS) && !defined(lint) 37#if defined(LIBC_SCCS) && !defined(lint)
38/*static char *sccsid = "from: @(#)memchr.c 5.6 (Berkeley) 1/26/91";*/ 38static char *rcsid = "$OpenBSD: memchr.c,v 1.4 2001/09/07 08:09:31 espie Exp $";
39static char *rcsid = "$Id: memchr.c,v 1.1.1.1 1995/10/18 08:42:21 deraadt Exp $";
40#endif /* LIBC_SCCS and not lint */ 39#endif /* LIBC_SCCS and not lint */
41 40
42#include <string.h> 41#include <string.h>
@@ -44,14 +43,14 @@ static char *rcsid = "$Id: memchr.c,v 1.1.1.1 1995/10/18 08:42:21 deraadt Exp $"
44void * 43void *
45memchr(s, c, n) 44memchr(s, c, n)
46 const void *s; 45 const void *s;
47 register unsigned char c; 46 int c;
48 register size_t n; 47 size_t n;
49{ 48{
50 if (n != 0) { 49 if (n != 0) {
51 register const unsigned char *p = s; 50 const unsigned char *p = s;
52 51
53 do { 52 do {
54 if (*p++ == c) 53 if (*p++ == (unsigned char)c)
55 return ((void *)(p - 1)); 54 return ((void *)(p - 1));
56 } while (--n != 0); 55 } while (--n != 0);
57 } 56 }
diff --git a/src/lib/libc/string/memcmp.3 b/src/lib/libc/string/memcmp.3
index 13901c1009..db4fef364b 100644
--- a/src/lib/libc/string/memcmp.3
+++ b/src/lib/libc/string/memcmp.3
@@ -33,8 +33,7 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)memcmp.3 5.5 (Berkeley) 6/29/91 36.\" $OpenBSD: memcmp.3,v 1.4 2000/04/21 15:24:19 aaron Exp $
37.\" $Id: memcmp.3,v 1.1.1.1 1995/10/18 08:42:21 deraadt Exp $
38.\" 37.\"
39.Dd June 29, 1991 38.Dd June 29, 1991
40.Dt MEMCMP 3 39.Dt MEMCMP 3
@@ -49,8 +48,7 @@
49.Sh DESCRIPTION 48.Sh DESCRIPTION
50The 49The
51.Fn memcmp 50.Fn memcmp
52function 51function compares byte string
53compares byte string
54.Fa b1 52.Fa b1
55against byte string 53against byte string
56.Fa b2 . 54.Fa b2 .
@@ -60,10 +58,11 @@ bytes long.
60.Sh RETURN VALUES 58.Sh RETURN VALUES
61The 59The
62.Fn memcmp 60.Fn memcmp
63function 61function returns zero if the two strings are identical,
64returns zero if the the two strings are identical,
65otherwise returns the difference between the first two differing bytes 62otherwise returns the difference between the first two differing bytes
66(treated as unsigned char values, so that 63(treated as
64.Li unsigned char
65values, so that
67.Sq Li \e200 66.Sq Li \e200
68is greater than 67is greater than
69.Sq Li \&\e0 , 68.Sq Li \&\e0 ,
@@ -78,6 +77,5 @@ Zero-length strings are always identical.
78.Sh STANDARDS 77.Sh STANDARDS
79The 78The
80.Fn memcmp 79.Fn memcmp
81function 80function conforms to
82conforms to
83.St -ansiC . 81.St -ansiC .
diff --git a/src/lib/libc/string/memcmp.c b/src/lib/libc/string/memcmp.c
index 23d2ab2393..5ce33e2998 100644
--- a/src/lib/libc/string/memcmp.c
+++ b/src/lib/libc/string/memcmp.c
@@ -35,8 +35,7 @@
35 */ 35 */
36 36
37#if defined(LIBC_SCCS) && !defined(lint) 37#if defined(LIBC_SCCS) && !defined(lint)
38/*static char *sccsid = "from: @(#)memcmp.c 5.6 (Berkeley) 1/26/91";*/ 38static char *rcsid = "$OpenBSD: memcmp.c,v 1.2 1996/08/19 08:34:05 tholo Exp $";
39static char *rcsid = "$Id: memcmp.c,v 1.1.1.1 1995/10/18 08:42:21 deraadt Exp $";
40#endif /* LIBC_SCCS and not lint */ 39#endif /* LIBC_SCCS and not lint */
41 40
42#include <string.h> 41#include <string.h>
diff --git a/src/lib/libc/string/memcpy.3 b/src/lib/libc/string/memcpy.3
index 3f4bb643c9..46168a103b 100644
--- a/src/lib/libc/string/memcpy.3
+++ b/src/lib/libc/string/memcpy.3
@@ -33,8 +33,7 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)memcpy.3 5.5 (Berkeley) 6/29/91 36.\" $OpenBSD: memcpy.3,v 1.4 2003/04/07 18:53:58 deraadt Exp $
37.\" $Id: memcpy.3,v 1.1.1.1 1995/10/18 08:42:21 deraadt Exp $
38.\" 37.\"
39.Dd June 29, 1991 38.Dd June 29, 1991
40.Dt MEMCPY 3 39.Dt MEMCPY 3
@@ -49,8 +48,7 @@
49.Sh DESCRIPTION 48.Sh DESCRIPTION
50The 49The
51.Fn memcpy 50.Fn memcpy
52function 51function copies
53copies
54.Fa len 52.Fa len
55bytes from string 53bytes from string
56.Fa src 54.Fa src
@@ -59,19 +57,18 @@ to string
59.Sh RETURN VALUES 57.Sh RETURN VALUES
60The 58The
61.Fn memcpy 59.Fn memcpy
62function 60function returns the original value of
63returns the original value of
64.Fa dst . 61.Fa dst .
65.Sh SEE ALSO 62.Sh SEE ALSO
66.Xr bcopy 3 , 63.Xr bcopy 3 ,
67.Xr memccpy 3 , 64.Xr memccpy 3 ,
68.Xr memmove 3 , 65.Xr memmove 3 ,
69.Xr strcpy 3 66.Xr strcpy 3 ,
67.Xr strlcpy 3
70.Sh STANDARDS 68.Sh STANDARDS
71The 69The
72.Fn memcpy 70.Fn memcpy
73function 71function conforms to
74conforms to
75.St -ansiC . 72.St -ansiC .
76.Sh BUGS 73.Sh BUGS
77In this implementation 74In this implementation
diff --git a/src/lib/libc/string/memmove.3 b/src/lib/libc/string/memmove.3
index 24422e7971..41d42f78e0 100644
--- a/src/lib/libc/string/memmove.3
+++ b/src/lib/libc/string/memmove.3
@@ -33,8 +33,7 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)memmove.3 5.5 (Berkeley) 6/29/91 36.\" $OpenBSD: memmove.3,v 1.4 2003/04/07 18:53:58 deraadt Exp $
37.\" $Id: memmove.3,v 1.1.1.1 1995/10/18 08:42:21 deraadt Exp $
38.\" 37.\"
39.Dd June 29, 1991 38.Dd June 29, 1991
40.Dt MEMMOVE 3 39.Dt MEMMOVE 3
@@ -49,8 +48,7 @@
49.Sh DESCRIPTION 48.Sh DESCRIPTION
50The 49The
51.Fn memmove 50.Fn memmove
52function 51function copies
53copies
54.Fa len 52.Fa len
55bytes from string 53bytes from string
56.Fa src 54.Fa src
@@ -67,10 +65,10 @@ function returns the original value of
67.Xr bcopy 3 , 65.Xr bcopy 3 ,
68.Xr memccpy 3 , 66.Xr memccpy 3 ,
69.Xr memcpy 3 , 67.Xr memcpy 3 ,
70.Xr strcpy 3 68.Xr strcpy 3 ,
69.Xr strlcpy 3
71.Sh STANDARDS 70.Sh STANDARDS
72The 71The
73.Fn memmove 72.Fn memmove
74function 73function conforms to
75conforms to
76.St -ansiC . 74.St -ansiC .
diff --git a/src/lib/libc/string/memset.3 b/src/lib/libc/string/memset.3
index 1afc052182..9da14983c7 100644
--- a/src/lib/libc/string/memset.3
+++ b/src/lib/libc/string/memset.3
@@ -33,8 +33,7 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)memset.3 5.4 (Berkeley) 6/29/91 36.\" $OpenBSD: memset.3,v 1.4 2000/04/21 15:24:19 aaron Exp $
37.\" $Id: memset.3,v 1.1.1.1 1995/10/18 08:42:21 deraadt Exp $
38.\" 37.\"
39.Dd June 29, 1991 38.Dd June 29, 1991
40.Dt MEMSET 3 39.Dt MEMSET 3
@@ -49,12 +48,18 @@
49.Sh DESCRIPTION 48.Sh DESCRIPTION
50The 49The
51.Fn memset 50.Fn memset
52function 51function writes
53writes
54.Fa len 52.Fa len
55bytes of value 53bytes of value
56.Fa c 54.Fa c
57(converted to an unsigned char) to the string 55(converted to an
56.Li unsigned char )
57to the string
58.Fa b .
59.Sh RETURN VALUES
60The
61.Fn memset
62function returns the original value of
58.Fa b . 63.Fa b .
59.Sh SEE ALSO 64.Sh SEE ALSO
60.Xr bzero 3 , 65.Xr bzero 3 ,
@@ -62,6 +67,5 @@ bytes of value
62.Sh STANDARDS 67.Sh STANDARDS
63The 68The
64.Fn memset 69.Fn memset
65function 70function conforms to
66conforms to
67.St -ansiC . 71.St -ansiC .
diff --git a/src/lib/libc/string/memset.c b/src/lib/libc/string/memset.c
index 117de2e80b..c3373a21a9 100644
--- a/src/lib/libc/string/memset.c
+++ b/src/lib/libc/string/memset.c
@@ -35,8 +35,7 @@
35 */ 35 */
36 36
37#if defined(LIBC_SCCS) && !defined(lint) 37#if defined(LIBC_SCCS) && !defined(lint)
38/*static char *sccsid = "from: @(#)memset.c 5.6 (Berkeley) 1/26/91";*/ 38static char *rcsid = "$OpenBSD: memset.c,v 1.2 1996/08/19 08:34:07 tholo Exp $";
39static char *rcsid = "$Id: memset.c,v 1.1.1.1 1995/10/18 08:42:21 deraadt Exp $";
40#endif /* LIBC_SCCS and not lint */ 39#endif /* LIBC_SCCS and not lint */
41 40
42#include <string.h> 41#include <string.h>
diff --git a/src/lib/libc/string/rindex.3 b/src/lib/libc/string/rindex.3
deleted file mode 100644
index b13b3513e0..0000000000
--- a/src/lib/libc/string/rindex.3
+++ /dev/null
@@ -1,81 +0,0 @@
1.\" Copyright (c) 1990, 1991 The Regents of the University of California.
2.\" All rights reserved.
3.\"
4.\" This code is derived from software contributed to Berkeley by
5.\" Chris Torek.
6.\" Redistribution and use in source and binary forms, with or without
7.\" modification, are permitted provided that the following conditions
8.\" are met:
9.\" 1. Redistributions of source code must retain the above copyright
10.\" notice, this list of conditions and the following disclaimer.
11.\" 2. Redistributions in binary form must reproduce the above copyright
12.\" notice, this list of conditions and the following disclaimer in the
13.\" documentation and/or other materials provided with the distribution.
14.\" 3. All advertising materials mentioning features or use of this software
15.\" must display the following acknowledgement:
16.\" This product includes software developed by the University of
17.\" California, Berkeley and its contributors.
18.\" 4. Neither the name of the University nor the names of its contributors
19.\" may be used to endorse or promote products derived from this software
20.\" without specific prior written permission.
21.\"
22.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32.\" SUCH DAMAGE.
33.\"
34.\" from: @(#)rindex.3 5.2 (Berkeley) 4/19/91
35.\" $Id: rindex.3,v 1.1.1.1 1995/10/18 08:42:21 deraadt Exp $
36.\"
37.Dd April 19, 1991
38.Dt RINDEX 3
39.Os
40.Sh NAME
41.Nm rindex
42.Nd locate character in string
43.Sh SYNOPSIS
44.Fd #include <string.h>
45.Ft char *
46.Fn rindex "const char *s" "int c"
47.Sh DESCRIPTION
48The
49.Fn rindex
50function
51locates the last character
52matching
53.Fa c
54(converted to a
55.Em char )
56in the null-terminated string
57.Fa s .
58The character c is returned if it is found; otherwise NULL is returned.
59If
60.Fa c
61is
62.Ql \e0 ,
63.Fn rindex
64locates the terminating
65.Ql \e0 .
66.Sh SEE ALSO
67.Xr index 3 ,
68.Xr memchr 3 ,
69.Xr strchr 3 ,
70.Xr strcspn 3 ,
71.Xr strpbrk 3 ,
72.Xr strrchr 3 ,
73.Xr strsep 3 ,
74.Xr strspn 3 ,
75.Xr strstr 3 ,
76.Xr strtok 3
77.Sh HISTORY
78A
79.Fn rindex
80function appeared in
81.At v6 .
diff --git a/src/lib/libc/string/rindex.c b/src/lib/libc/string/rindex.c
index 1b84c92072..7c7c94ae81 100644
--- a/src/lib/libc/string/rindex.c
+++ b/src/lib/libc/string/rindex.c
@@ -32,19 +32,17 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)rindex.c 5.9 (Berkeley) 2/24/91";*/ 35static char *rcsid = "$OpenBSD: rindex.c,v 1.3 2002/07/24 04:16:01 millert Exp $";
36static char *rcsid = "$Id: rindex.c,v 1.1.1.1 1995/10/18 08:42:21 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
38 37
39#include <string.h> 38#include <string.h>
40 39
41char * 40char *
42#ifdef STRRCHR 41#ifdef STRRCHR
43strrchr(p, ch) 42strrchr(const char *p, int ch)
44#else 43#else
45rindex(p, ch) 44rindex(const char *p, int ch)
46#endif 45#endif
47 register const char *p, ch;
48{ 46{
49 register char *save; 47 register char *save;
50 48
diff --git a/src/lib/libc/string/strcasecmp.3 b/src/lib/libc/string/strcasecmp.3
index 46e9010e4f..cd9be07c61 100644
--- a/src/lib/libc/string/strcasecmp.3
+++ b/src/lib/libc/string/strcasecmp.3
@@ -1,5 +1,7 @@
1.\" Copyright (c) 1990, 1991 The Regents of the University of California. 1.\" $OpenBSD: strcasecmp.3,v 1.7 2003/05/10 06:40:44 jmc Exp $
2.\" All rights reserved. 2.\"
3.\" Copyright (c) 1990, 1991, 1993
4.\" The Regents of the University of California. All rights reserved.
3.\" 5.\"
4.\" This code is derived from software contributed to Berkeley by 6.\" This code is derived from software contributed to Berkeley by
5.\" Chris Torek. 7.\" Chris Torek.
@@ -31,14 +33,14 @@
31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
33.\" 35.\"
34.\" from: @(#)strcasecmp.3 5.4 (Berkeley) 4/19/91 36.\" @(#)strcasecmp.3 8.1 (Berkeley) 6/9/93
35.\" $Id: strcasecmp.3,v 1.1.1.1 1995/10/18 08:42:21 deraadt Exp $
36.\" 37.\"
37.Dd April 19, 1991 38.Dd June 9, 1993
38.Dt STRCASECMP 3 39.Dt STRCASECMP 3
39.Os 40.Os
40.Sh NAME 41.Sh NAME
41.Nm strcasecmp 42.Nm strcasecmp ,
43.Nm strncasecmp
42.Nd compare strings, ignoring case 44.Nd compare strings, ignoring case
43.Sh SYNOPSIS 45.Sh SYNOPSIS
44.Fd #include <string.h> 46.Fd #include <string.h>
@@ -51,13 +53,12 @@ The
51.Fn strcasecmp 53.Fn strcasecmp
52and 54and
53.Fn strncasecmp 55.Fn strncasecmp
54functions 56functions compare the null-terminated strings
55compare the null-terminated strings
56.Fa s1 57.Fa s1
57and 58and
58.Fa s2 59.Fa s2
59and return an integer greater than, equal to, or less than 0, 60and return an integer greater than, equal to, or less than 0,
60according as 61according to whether
61.Fa s1 62.Fa s1
62is lexicographically greater than, equal to, or less than 63is lexicographically greater than, equal to, or less than
63.Fa s2 64.Fa s2
@@ -68,7 +69,6 @@ The comparison is done using unsigned characters, so that
68is greater than 69is greater than
69.Ql \e0 . 70.Ql \e0 .
70.Pp 71.Pp
71The
72.Fn strncasecmp 72.Fn strncasecmp
73compares at most 73compares at most
74.Fa len 74.Fa len
@@ -84,5 +84,5 @@ The
84.Fn strcasecmp 84.Fn strcasecmp
85and 85and
86.Fn strncasecmp 86.Fn strncasecmp
87functions are 87functions first appeared in
88.Ud . 88.Bx 4.4 .
diff --git a/src/lib/libc/string/strcasecmp.c b/src/lib/libc/string/strcasecmp.c
index 79bd0081e3..1f487524aa 100644
--- a/src/lib/libc/string/strcasecmp.c
+++ b/src/lib/libc/string/strcasecmp.c
@@ -1,6 +1,8 @@
1/* $OpenBSD: strcasecmp.c,v 1.3 1997/08/20 04:13:57 millert Exp $ */
2
1/* 3/*
2 * Copyright (c) 1987 Regents of the University of California. 4 * Copyright (c) 1987, 1993
3 * All rights reserved. 5 * The Regents of the University of California. All rights reserved.
4 * 6 *
5 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
@@ -31,13 +33,16 @@
31 * SUCH DAMAGE. 33 * SUCH DAMAGE.
32 */ 34 */
33 35
36#include <string.h>
37
34#if defined(LIBC_SCCS) && !defined(lint) 38#if defined(LIBC_SCCS) && !defined(lint)
35/*static const char sccsid[] = "from: @(#)strcasecmp.c 5.10 (Berkeley) 1/26/91";*/ 39#if 0
36static char *rcsid = "$Id: strcasecmp.c,v 1.1.1.1 1995/10/18 08:42:21 deraadt Exp $"; 40static char sccsid[] = "@(#)strcasecmp.c 8.1 (Berkeley) 6/4/93";
41#else
42static char *rcsid = "$OpenBSD: strcasecmp.c,v 1.3 1997/08/20 04:13:57 millert Exp $";
43#endif
37#endif /* LIBC_SCCS and not lint */ 44#endif /* LIBC_SCCS and not lint */
38 45
39#include <string.h>
40
41typedef unsigned char u_char; 46typedef unsigned char u_char;
42 47
43/* 48/*
diff --git a/src/lib/libc/string/strcat.3 b/src/lib/libc/string/strcat.3
index 5357d65754..e9e5163bd3 100644
--- a/src/lib/libc/string/strcat.3
+++ b/src/lib/libc/string/strcat.3
@@ -33,14 +33,14 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)strcat.3 5.6 (Berkeley) 6/29/91 36.\" $OpenBSD: strcat.3,v 1.8 2000/04/21 15:24:19 aaron Exp $
37.\" $Id: strcat.3,v 1.1.1.1 1995/10/18 08:42:22 deraadt Exp $
38.\" 37.\"
39.Dd June 29, 1991 38.Dd July 8, 1997
40.Dt STRCAT 3 39.Dt STRCAT 3
41.Os 40.Os
42.Sh NAME 41.Sh NAME
43.Nm strcat 42.Nm strcat ,
43.Nm strncat
44.Nd concatenate strings 44.Nd concatenate strings
45.Sh SYNOPSIS 45.Sh SYNOPSIS
46.Fd #include <string.h> 46.Fd #include <string.h>
@@ -53,8 +53,7 @@ The
53.Fn strcat 53.Fn strcat
54and 54and
55.Fn strncat 55.Fn strncat
56functions 56functions append a copy of the null-terminated string
57append a copy of the null-terminated string
58.Fa append 57.Fa append
59to the end of the null-terminated string 58to the end of the null-terminated string
60.Fa s , 59.Fa s ,
@@ -66,29 +65,71 @@ must have sufficient space to hold the result.
66.Pp 65.Pp
67The 66The
68.Fn strncat 67.Fn strncat
69function 68function appends not more than
70appends not more than
71.Fa count 69.Fa count
72characters. 70characters where space for the terminating
71.Ql \e0
72should not be included in
73.Fa count .
73.Sh RETURN VALUES 74.Sh RETURN VALUES
74The 75The
75.Fn strcat 76.Fn strcat
76and 77and
77.Fn strncat 78.Fn strncat
78functions 79functions return the pointer
79return the pointer
80.Fa s . 80.Fa s .
81.Sh EXAMPLES
82The following appends
83.Dq Li abc
84to
85.Dq Li chararray :
86.Bd -literal -offset indent
87char *letters = "abcdefghi";
88
89(void)strncat(chararray, letters, 3);
90.Ed
91.Pp
92The following example shows how to use
93.Fn strncat
94safely in conjunction with
95.Xr strncpy 3 .
96.Bd -literal -offset indent
97char buf[BUFSIZ];
98char *input, *suffix;
99
100(void)strncpy(buf, input, sizeof(buf) - 1);
101buf[sizeof(buf) - 1] = '\e0';
102(void)strncat(buf, suffix, sizeof(buf) - 1 - strlen(buf));
103.Ed
104.Pp
105The above will copy as many characters from
106.Dq Li input
107to
108.Dq Li buf
109as will fit.
110It then appends as many characters from suffix as will fit (or none
111if there is no space).
112For operations like this, the
113.Xr strlcpy 3
114and
115.Xr strlcat 3
116functions are a better choice, as shown below.
117.Bd -literal -offset indent
118(void)strlcpy(buf, input, sizeof(buf));
119(void)strlcat(buf, suffix, sizeof(buf));
120.Ed
81.Sh SEE ALSO 121.Sh SEE ALSO
82.Xr bcopy 3 , 122.Xr bcopy 3 ,
83.Xr memccpy 3 , 123.Xr memccpy 3 ,
84.Xr memcpy 3 , 124.Xr memcpy 3 ,
85.Xr memmove 3 , 125.Xr memmove 3 ,
86.Xr strcpy 3 126.Xr strcpy 3 ,
127.Xr strlcat 3 ,
128.Xr strlcpy 3
87.Sh STANDARDS 129.Sh STANDARDS
88The 130The
89.Fn strcat 131.Fn strcat
90and 132and
91.Fn strncat 133.Fn strncat
92functions 134functions conform to
93conform to
94.St -ansiC . 135.St -ansiC .
diff --git a/src/lib/libc/string/strcat.c b/src/lib/libc/string/strcat.c
index e741b84f03..374a2b7464 100644
--- a/src/lib/libc/string/strcat.c
+++ b/src/lib/libc/string/strcat.c
@@ -32,11 +32,14 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)strcat.c 5.6 (Berkeley) 2/24/91";*/ 35static char *rcsid = "$OpenBSD: strcat.c,v 1.4 1996/08/19 08:34:10 tholo Exp $";
36static char *rcsid = "$Id: strcat.c,v 1.1.1.1 1995/10/18 08:42:22 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
38 37
38#ifndef _KERNEL
39#include <string.h> 39#include <string.h>
40#else
41#include <lib/libkern/libkern.h>
42#endif
40 43
41char * 44char *
42strcat(s, append) 45strcat(s, append)
@@ -46,6 +49,6 @@ strcat(s, append)
46 char *save = s; 49 char *save = s;
47 50
48 for (; *s; ++s); 51 for (; *s; ++s);
49 while (*s++ = *append++); 52 while ((*s++ = *append++) != '\0');
50 return(save); 53 return(save);
51} 54}
diff --git a/src/lib/libc/string/strchr.3 b/src/lib/libc/string/strchr.3
index 18b50301f3..1333a305d6 100644
--- a/src/lib/libc/string/strchr.3
+++ b/src/lib/libc/string/strchr.3
@@ -33,29 +33,29 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)strchr.3 5.4 (Berkeley) 6/29/91 36.\" $OpenBSD: strchr.3,v 1.7 2000/04/21 15:24:19 aaron Exp $
37.\" $Id: strchr.3,v 1.1.1.1 1995/10/18 08:42:22 deraadt Exp $
38.\" 37.\"
39.Dd June 29, 1991 38.Dd June 29, 1991
40.Dt STRCHR 3 39.Dt STRCHR 3
41.Os 40.Os
42.Sh NAME 41.Sh NAME
43.Nm strchr 42.Nm strchr ,
44.Nd locate character in string 43.Nm index
44.Nd locate first occurrence of a character in a string
45.Sh SYNOPSIS 45.Sh SYNOPSIS
46.Fd #include <string.h> 46.Fd #include <string.h>
47.Ft char * 47.Ft char *
48.Fn strchr "const char *s" "int c" 48.Fn strchr "const char *s" "int c"
49.Ft char *
50.Fn index "const char *s" "int c"
49.Sh DESCRIPTION 51.Sh DESCRIPTION
50The 52The
51.Fn strchr 53.Fn strchr
52function locates the first occurrence of 54function locates the first occurrence of the character
53.Ar c 55.Fa c
54in the string pointed to by 56in the string
55.Ar s . 57.Fa s .
56The terminating 58The terminating NUL character is considered part of the string.
57.Dv NULL
58character is considered part of the string.
59If 59If
60.Fa c 60.Fa c
61is 61is
@@ -63,16 +63,31 @@ is
63.Fn strchr 63.Fn strchr
64locates the terminating 64locates the terminating
65.Ql \e0 . 65.Ql \e0 .
66.Pp
67The
68.Fn index
69function is an old synonym for
70.Fn strchr .
66.Sh RETURN VALUES 71.Sh RETURN VALUES
67The function 72The
68.Fn strchr 73.Fn strchr
69returns a pointer to the located character, or 74function returns a pointer to the located character or
70.Dv NULL 75.Dv NULL
71if the character does not appear in the string. 76if the character does not appear in the string.
77.Sh EXAMPLES
78After the following call to
79.Fn strchr ,
80.Va p
81will point to the string
82.Qq oobar :
83.Bd -literal -offset indent
84char *p;
85char *s = "foobar";
86
87p = strchr(s, 'o');
88.Ed
72.Sh SEE ALSO 89.Sh SEE ALSO
73.Xr index 3 ,
74.Xr memchr 3 , 90.Xr memchr 3 ,
75.Xr rindex 3 ,
76.Xr strcspn 3 , 91.Xr strcspn 3 ,
77.Xr strpbrk 3 , 92.Xr strpbrk 3 ,
78.Xr strrchr 3 , 93.Xr strrchr 3 ,
@@ -83,6 +98,9 @@ if the character does not appear in the string.
83.Sh STANDARDS 98.Sh STANDARDS
84The 99The
85.Fn strchr 100.Fn strchr
86function 101function conforms to
87conforms to
88.St -ansiC . 102.St -ansiC .
103.Pp
104The
105.Fn index
106function is deprecated and shouldn't be used in new code.
diff --git a/src/lib/libc/string/strcmp.3 b/src/lib/libc/string/strcmp.3
index fecaa85410..0482604eae 100644
--- a/src/lib/libc/string/strcmp.3
+++ b/src/lib/libc/string/strcmp.3
@@ -33,14 +33,14 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)strcmp.3 5.6 (Berkeley) 6/29/91 36.\" $OpenBSD: strcmp.3,v 1.6 2003/05/10 06:40:44 jmc Exp $
37.\" $Id: strcmp.3,v 1.1.1.1 1995/10/18 08:42:22 deraadt Exp $
38.\" 37.\"
39.Dd June 29, 1991 38.Dd June 29, 1991
40.Dt STRCMP 3 39.Dt STRCMP 3
41.Os 40.Os
42.Sh NAME 41.Sh NAME
43.Nm strcmp 42.Nm strcmp ,
43.Nm strncmp
44.Nd compare strings 44.Nd compare strings
45.Sh SYNOPSIS 45.Sh SYNOPSIS
46.Fd #include <string.h> 46.Fd #include <string.h>
@@ -53,8 +53,7 @@ The
53.Fn strcmp 53.Fn strcmp
54and 54and
55.Fn strncmp 55.Fn strncmp
56functions 56functions lexicographically compare the null-terminated strings
57lexicographically compare the null-terminated strings
58.Fa s1 57.Fa s1
59and 58and
60.Fa s2 . 59.Fa s2 .
@@ -64,7 +63,7 @@ The
64and 63and
65.Fn strncmp 64.Fn strncmp
66return an integer greater than, equal to, or less than 0, according 65return an integer greater than, equal to, or less than 0, according
67as the string 66to whether the string
68.Fa s1 67.Fa s1
69is greater than, equal to, or less than the string 68is greater than, equal to, or less than the string
70.Fa s2 . 69.Fa s2 .
@@ -73,9 +72,8 @@ The comparison is done using unsigned characters, so that
73is greater than 72is greater than
74.Ql \e0 . 73.Ql \e0 .
75.Pp 74.Pp
76The
77.Fn strncmp 75.Fn strncmp
78compares not more than 76compares at most
79.Fa len 77.Fa len
80characters. 78characters.
81.Sh SEE ALSO 79.Sh SEE ALSO
@@ -89,6 +87,5 @@ The
89.Fn strcmp 87.Fn strcmp
90and 88and
91.Fn strncmp 89.Fn strncmp
92functions 90functions conform to
93conform to
94.St -ansiC . 91.St -ansiC .
diff --git a/src/lib/libc/string/strcmp.c b/src/lib/libc/string/strcmp.c
index ae19e2e26e..9a5b208323 100644
--- a/src/lib/libc/string/strcmp.c
+++ b/src/lib/libc/string/strcmp.c
@@ -35,11 +35,14 @@
35 */ 35 */
36 36
37#if defined(LIBC_SCCS) && !defined(lint) 37#if defined(LIBC_SCCS) && !defined(lint)
38/*static char *sccsid = "from: @(#)strcmp.c 5.5 (Berkeley) 1/26/91";*/ 38static char *rcsid = "$OpenBSD: strcmp.c,v 1.3 1996/08/19 08:34:12 tholo Exp $";
39static char *rcsid = "$Id: strcmp.c,v 1.1.1.1 1995/10/18 08:42:22 deraadt Exp $";
40#endif /* LIBC_SCCS and not lint */ 39#endif /* LIBC_SCCS and not lint */
41 40
41#ifndef _KERNEL
42#include <string.h> 42#include <string.h>
43#else
44#include <lib/libkern/libkern.h>
45#endif
43 46
44/* 47/*
45 * Compare strings. 48 * Compare strings.
diff --git a/src/lib/libc/string/strcoll.3 b/src/lib/libc/string/strcoll.3
index 12f73f98f2..62086c79ac 100644
--- a/src/lib/libc/string/strcoll.3
+++ b/src/lib/libc/string/strcoll.3
@@ -33,8 +33,7 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)strcoll.3 5.6 (Berkeley) 6/29/91 36.\" $OpenBSD: strcoll.3,v 1.4 2003/05/10 06:40:44 jmc Exp $
37.\" $Id: strcoll.3,v 1.1.1.1 1995/10/18 08:42:22 deraadt Exp $
38.\" 37.\"
39.Dd June 29, 1991 38.Dd June 29, 1991
40.Dt STRCOLL 3 39.Dt STRCOLL 3
@@ -49,14 +48,13 @@
49.Sh DESCRIPTION 48.Sh DESCRIPTION
50The 49The
51.Fn strcoll 50.Fn strcoll
52function 51function lexicographically compares the null-terminated strings
53lexicographically compares the null-terminated strings
54.Fa s1 52.Fa s1
55and 53and
56.Fa s2 54.Fa s2
57according to the current locale collation 55according to the current locale collation
58and returns an integer greater than, equal to, or less than 0, 56and returns an integer greater than, equal to, or less than 0,
59according as 57according to whether
60.Fa s1 58.Fa s1
61is greater than, equal to, or less than 59is greater than, equal to, or less than
62.Fa s2 . 60.Fa s2 .
@@ -70,6 +68,5 @@ is greater than, equal to, or less than
70.Sh STANDARDS 68.Sh STANDARDS
71The 69The
72.Fn strcoll 70.Fn strcoll
73function 71function conforms to
74conforms to
75.St -ansiC . 72.St -ansiC .
diff --git a/src/lib/libc/string/strcoll.c b/src/lib/libc/string/strcoll.c
index 86c742cba9..dca0b10d25 100644
--- a/src/lib/libc/string/strcoll.c
+++ b/src/lib/libc/string/strcoll.c
@@ -35,8 +35,7 @@
35 */ 35 */
36 36
37#if defined(LIBC_SCCS) && !defined(lint) 37#if defined(LIBC_SCCS) && !defined(lint)
38/*static char *sccsid = "from: @(#)strcoll.c 5.2 (Berkeley) 1/26/91";*/ 38static char *rcsid = "$OpenBSD: strcoll.c,v 1.2 1996/08/19 08:34:13 tholo Exp $";
39static char *rcsid = "$Id: strcoll.c,v 1.1.1.1 1995/10/18 08:42:22 deraadt Exp $";
40#endif /* LIBC_SCCS and not lint */ 39#endif /* LIBC_SCCS and not lint */
41 40
42#include <string.h> 41#include <string.h>
diff --git a/src/lib/libc/string/strcpy.3 b/src/lib/libc/string/strcpy.3
index 1ca12c2707..d3c095916b 100644
--- a/src/lib/libc/string/strcpy.3
+++ b/src/lib/libc/string/strcpy.3
@@ -33,14 +33,14 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)strcpy.3 5.4 (Berkeley) 6/29/91 36.\" $OpenBSD: strcpy.3,v 1.11 2002/05/13 17:04:43 millert Exp $
37.\" $Id: strcpy.3,v 1.1.1.1 1995/10/18 08:42:22 deraadt Exp $
38.\" 37.\"
39.Dd June 29, 1991 38.Dd June 29, 1991
40.Dt STRCPY 3 39.Dt STRCPY 3
41.Os BSD 4 40.Os
42.Sh NAME 41.Sh NAME
43.Nm strcpy 42.Nm strcpy ,
43.Nm strncpy
44.Nd copy strings 44.Nd copy strings
45.Sh SYNOPSIS 45.Sh SYNOPSIS
46.Fd #include <string.h> 46.Fd #include <string.h>
@@ -53,8 +53,7 @@ The
53.Fn strcpy 53.Fn strcpy
54and 54and
55.Fn strncpy 55.Fn strncpy
56functions 56functions copy the string
57copy the string
58.Fa src 57.Fa src
59to 58to
60.Fa dst 59.Fa dst
@@ -62,7 +61,6 @@ to
62.Ql \e0 61.Ql \e0
63character). 62character).
64.Pp 63.Pp
65The
66.Fn strncpy 64.Fn strncpy
67copies not more than 65copies not more than
68.Fa len 66.Fa len
@@ -78,45 +76,79 @@ characters long, and
78.Em not 76.Em not
79terminating 77terminating
80.Fa dst 78.Fa dst
81if 79if the length of
82.Fa src 80.Fa src
83is more than 81is greater than or equal to
84.Fa len 82.Fa len .
85characters long.
86.Sh RETURN VALUES 83.Sh RETURN VALUES
87The 84The
88.Fn strcpy 85.Fn strcpy
89and 86and
90.Fn strncpy 87.Fn strncpy
91functions 88functions return
92return
93.Fa dst . 89.Fa dst .
94.Sh EXAMPLES 90.Sh EXAMPLES
95The following sets 91The following sets
96.Dq Li chararray 92.Va chararray
97to 93to
98.Dq Li abc\e0\e0\e0 : 94.Dq abc\e0\e0\e0 :
99.Bd -literal -offset indent 95.Bd -literal -offset indent
100(void)strncpy(chararray, "abc", 6). 96(void)strncpy(chararray, "abc", 6);
101.Ed 97.Ed
102.Pp 98.Pp
103The following sets 99The following sets
104.Dq Li chararray 100.Va chararray
105to 101to
106.Dq Li abcdef : 102.Dq abcdef
103and does
104.Em not
105null terminate
106.Va chararray
107because the source string is >= the length parameter.
108.Fn strncpy
109.Em only
110null terminates the destination string when the length of the source
111string is less than the length parameter.
107.Bd -literal -offset indent 112.Bd -literal -offset indent
108(void)strncpy(chararray, "abcdefgh", 6); 113(void)strncpy(chararray, "abcdefgh", 6);
109.Ed 114.Ed
115.Pp
116The following copies as many characters from
117.Va input
118to
119.Va buf
120as will fit and null terminates the result.
121Because
122.Fn strncpy
123does
124.Em not
125guarantee to null terminate the string itself, we must do this by hand.
126.Bd -literal -offset indent
127char buf[BUFSIZ];
128
129(void)strncpy(buf, input, sizeof(buf) - 1);
130buf[sizeof(buf) - 1] = '\e0';
131.Ed
132.Pp
133Note that
134.Xr strlcpy 3
135is a better choice for this kind of operation.
136The equivalent using
137.Xr strlcpy 3
138is simply:
139.Bd -literal -offset indent
140(void)strlcpy(buf, input, sizeof(buf));
141.Ed
110.Sh SEE ALSO 142.Sh SEE ALSO
111.Xr bcopy 3 , 143.Xr bcopy 3 ,
112.Xr memccpy 3 , 144.Xr memccpy 3 ,
113.Xr memcpy 3 , 145.Xr memcpy 3 ,
114.Xr memmove 3 146.Xr memmove 3 ,
147.Xr strlcpy 3
115.Sh STANDARDS 148.Sh STANDARDS
116The 149The
117.Fn strcpy 150.Fn strcpy
118and 151and
119.Fn strncpy 152.Fn strncpy
120functions 153functions conform to
121conform to
122.St -ansiC . 154.St -ansiC .
diff --git a/src/lib/libc/string/strcpy.c b/src/lib/libc/string/strcpy.c
index 669bfde23e..76b063fc10 100644
--- a/src/lib/libc/string/strcpy.c
+++ b/src/lib/libc/string/strcpy.c
@@ -32,11 +32,14 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)strcpy.c 5.7 (Berkeley) 2/24/91";*/ 35static char *rcsid = "$OpenBSD: strcpy.c,v 1.4 1996/08/19 08:34:14 tholo Exp $";
36static char *rcsid = "$Id: strcpy.c,v 1.1.1.1 1995/10/18 08:42:22 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
38 37
38#ifndef _KERNEL
39#include <string.h> 39#include <string.h>
40#else
41#include <lib/libkern/libkern.h>
42#endif
40 43
41char * 44char *
42strcpy(to, from) 45strcpy(to, from)
@@ -45,6 +48,6 @@ strcpy(to, from)
45{ 48{
46 char *save = to; 49 char *save = to;
47 50
48 for (; *to = *from; ++from, ++to); 51 for (; (*to = *from) != '\0'; ++from, ++to);
49 return(save); 52 return(save);
50} 53}
diff --git a/src/lib/libc/string/strcspn.3 b/src/lib/libc/string/strcspn.3
index cc9e5c2fe3..37e8f163f1 100644
--- a/src/lib/libc/string/strcspn.3
+++ b/src/lib/libc/string/strcspn.3
@@ -33,8 +33,7 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)strcspn.3 5.3 (Berkeley) 6/29/91 36.\" $OpenBSD: strcspn.3,v 1.5 2000/04/21 15:24:20 aaron Exp $
37.\" $Id: strcspn.3,v 1.1.1.1 1995/10/18 08:42:22 deraadt Exp $
38.\" 37.\"
39.Dd June 29, 1991 38.Dd June 29, 1991
40.Dt STRCSPN 3 39.Dt STRCSPN 3
@@ -49,27 +48,36 @@
49.Sh DESCRIPTION 48.Sh DESCRIPTION
50The 49The
51.Fn strcspn 50.Fn strcspn
52function 51function spans the initial part of the null-terminated string
53spans the initial part of the null-terminated string
54.Fa s 52.Fa s
55as long as the characters from 53as long as the characters from
56.Fa s 54.Fa s
57do not occur in string 55do not occur in string
58.Fa charset 56.Fa charset
59(it 57(it spans the
60spans the
61.Em complement 58.Em complement
62of 59of
63.Fa charset ) . 60.Fa charset ) .
64.Sh RETURN VALUES 61.Sh RETURN VALUES
65The 62The
66.Fn strcspn 63.Fn strcspn
67function 64function returns the number of characters spanned.
68returns the number of characters spanned. 65.Sh EXAMPLES
66The following call to
67.Fn strcspn
68will return 3, since the first three characters of string
69.Fa s
70do not occur in string
71.Fa charset :
72.Bd -literal -offset indent
73char *s = "foobar";
74char *charset = "bar";
75size_t span;
76
77span = strcspn(s, charset);
78.Ed
69.Sh SEE ALSO 79.Sh SEE ALSO
70.Xr index 3 ,
71.Xr memchr 3 , 80.Xr memchr 3 ,
72.Xr rindex 3 ,
73.Xr strchr 3 , 81.Xr strchr 3 ,
74.Xr strpbrk 3 , 82.Xr strpbrk 3 ,
75.Xr strrchr 3 , 83.Xr strrchr 3 ,
@@ -80,6 +88,5 @@ returns the number of characters spanned.
80.Sh STANDARDS 88.Sh STANDARDS
81The 89The
82.Fn strcspn 90.Fn strcspn
83function 91function conforms to
84conforms to
85.St -ansiC . 92.St -ansiC .
diff --git a/src/lib/libc/string/strcspn.c b/src/lib/libc/string/strcspn.c
index acb4d2a3af..f7261564a7 100644
--- a/src/lib/libc/string/strcspn.c
+++ b/src/lib/libc/string/strcspn.c
@@ -35,8 +35,7 @@
35 */ 35 */
36 36
37#if defined(LIBC_SCCS) && !defined(lint) 37#if defined(LIBC_SCCS) && !defined(lint)
38/*static char *sccsid = "from: @(#)strcspn.c 5.6 (Berkeley) 1/26/91";*/ 38static char *rcsid = "$OpenBSD: strcspn.c,v 1.2 1996/08/19 08:34:15 tholo Exp $";
39static char *rcsid = "$Id: strcspn.c,v 1.1.1.1 1995/10/18 08:42:22 deraadt Exp $";
40#endif /* LIBC_SCCS and not lint */ 39#endif /* LIBC_SCCS and not lint */
41 40
42#include <string.h> 41#include <string.h>
diff --git a/src/lib/libc/string/strdup.3 b/src/lib/libc/string/strdup.3
index 925cbf3d46..a0dc705f66 100644
--- a/src/lib/libc/string/strdup.3
+++ b/src/lib/libc/string/strdup.3
@@ -1,5 +1,7 @@
1.\" Copyright (c) 1990, 1991 The Regents of the University of California. 1.\" $OpenBSD: strdup.3,v 1.11 2003/04/07 18:53:58 deraadt Exp $
2.\" All rights reserved. 2.\"
3.\" Copyright (c) 1990, 1991, 1993
4.\" The Regents of the University of California. All rights reserved.
3.\" 5.\"
4.\" Redistribution and use in source and binary forms, with or without 6.\" Redistribution and use in source and binary forms, with or without
5.\" modification, are permitted provided that the following conditions 7.\" modification, are permitted provided that the following conditions
@@ -29,10 +31,9 @@
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE. 32.\" SUCH DAMAGE.
31.\" 33.\"
32.\" from: @(#)strdup.3 5.3 (Berkeley) 4/19/91 34.\" @(#)strdup.3 8.1 (Berkeley) 6/9/93
33.\" $Id: strdup.3,v 1.1.1.1 1995/10/18 08:42:22 deraadt Exp $
34.\" 35.\"
35.Dd April 19, 1991 36.Dd June 9, 1993
36.Dt STRDUP 3 37.Dt STRDUP 3
37.Os 38.Os
38.Sh NAME 39.Sh NAME
@@ -41,25 +42,47 @@
41.Sh SYNOPSIS 42.Sh SYNOPSIS
42.Fd #include <string.h> 43.Fd #include <string.h>
43.Ft char * 44.Ft char *
44.Fn strdup "const char *str" 45.Fn strdup "const char *s"
45.Sh DESCRIPTION 46.Sh DESCRIPTION
46The 47The
47.Fn strdup 48.Fn strdup
48function 49function allocates sufficient memory for a copy of the string
49allocates sufficient memory for a copy 50.Fa s ,
50of the string
51.Fa str ,
52does the copy, and returns a pointer to it. 51does the copy, and returns a pointer to it.
53The pointer may subsequently be used as an 52The pointer may subsequently be used as an argument to the function
54argument to the function
55.Xr free 3 . 53.Xr free 3 .
54.Pp
55If insufficient memory is available,
56.Dv NULL
57is returned.
58.Sh EXAMPLES
59The following will point
60.Va p
61to an allocated area of memory containing the null-terminated string
62.Qq foobar :
63.Bd -literal -offset indent
64char *p;
65
66if ((p = strdup("foobar")) == NULL) {
67 fprintf(stderr, "Out of memory.\en");
68 exit(1);
69}
70.Ed
71.Sh ERRORS
72The
73.Fn strdup
74function may fail and set the external variable
75.Va errno
76for any of the errors specified for the library function
77.Xr malloc 3 .
56.Sh SEE ALSO 78.Sh SEE ALSO
57.Xr free 3 , 79.Xr free 3 ,
58.Xr malloc 3 , 80.Xr malloc 3 ,
59.Xt strcpy 3 , 81.Xr strcpy 3 ,
60.Xt strlen 3 82.Xr strlcpy 3 ,
83.Xr strlen 3
61.Sh HISTORY 84.Sh HISTORY
62The 85The
63.Fn strdup 86.Fn strdup
64function 87function first appeared in
65.Ud . 88.Bx 4.4 .
diff --git a/src/lib/libc/string/strdup.c b/src/lib/libc/string/strdup.c
index 27ede44110..be7f7ad094 100644
--- a/src/lib/libc/string/strdup.c
+++ b/src/lib/libc/string/strdup.c
@@ -1,6 +1,8 @@
1/* $OpenBSD: strdup.c,v 1.3 1997/08/20 04:18:52 millert Exp $ */
2
1/* 3/*
2 * Copyright (c) 1988 The Regents of the University of California. 4 * Copyright (c) 1988, 1993
3 * All rights reserved. 5 * The Regents of the University of California. All rights reserved.
4 * 6 *
5 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
@@ -32,10 +34,16 @@
32 */ 34 */
33 35
34#if defined(LIBC_SCCS) && !defined(lint) 36#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)strdup.c 5.4 (Berkeley) 2/24/91";*/ 37#if 0
36static char *rcsid = "$Id: strdup.c,v 1.1.1.1 1995/10/18 08:42:22 deraadt Exp $"; 38static char sccsid[] = "@(#)strdup.c 8.1 (Berkeley) 6/4/93";
39#else
40static char *rcsid = "$OpenBSD: strdup.c,v 1.3 1997/08/20 04:18:52 millert Exp $";
41#endif
37#endif /* LIBC_SCCS and not lint */ 42#endif /* LIBC_SCCS and not lint */
38 43
44#include <sys/types.h>
45
46#include <stddef.h>
39#include <stdlib.h> 47#include <stdlib.h>
40#include <string.h> 48#include <string.h>
41 49
@@ -43,12 +51,12 @@ char *
43strdup(str) 51strdup(str)
44 const char *str; 52 const char *str;
45{ 53{
46 size_t len; 54 size_t siz;
47 char *copy; 55 char *copy;
48 56
49 len = strlen(str) + 1; 57 siz = strlen(str) + 1;
50 if (!(copy = malloc(len))) 58 if ((copy = malloc(siz)) == NULL)
51 return((char *)NULL); 59 return(NULL);
52 memcpy(copy, str, len); 60 (void)memcpy(copy, str, siz);
53 return(copy); 61 return(copy);
54} 62}
diff --git a/src/lib/libc/string/strerror.3 b/src/lib/libc/string/strerror.3
index c9d8504dbb..05cb7e9d9c 100644
--- a/src/lib/libc/string/strerror.3
+++ b/src/lib/libc/string/strerror.3
@@ -33,12 +33,11 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)strerror.3 6.9 (Berkeley) 6/29/91 36.\" $OpenBSD: strerror.3,v 1.5 2002/11/21 20:45:05 marc Exp $
37.\" $Id: strerror.3,v 1.1.1.1 1995/10/18 08:42:22 deraadt Exp $
38.\" 37.\"
39.Dd June 29, 1991 38.Dd June 29, 1991
40.Dt STRERROR 3 39.Dt STRERROR 3
41.Os BSD 4 40.Os
42.Sh NAME 41.Sh NAME
43.Nm strerror 42.Nm strerror
44.Nd get error message string 43.Nd get error message string
@@ -46,15 +45,35 @@
46.Fd #include <string.h> 45.Fd #include <string.h>
47.Ft char * 46.Ft char *
48.Fn strerror "int errnum" 47.Fn strerror "int errnum"
48.Ft int
49.Fn strerror_r "int errnum" "char *strerrbuf" "size_t buflen"
49.Sh DESCRIPTION 50.Sh DESCRIPTION
50The 51The
51.Fn strerror 52.Fn strerror
52function returns a pointer to the language-dependent error message 53function returns a pointer to the language-dependent error message
53string affiliated with an error number. 54string affiliated with the specified error number
55.Fa errnum .
56The returned string contains a maximum of
57.Dv NL_TEXTMAX
58characters, including the trailing NUL.
54.Pp 59.Pp
55The array pointed to is not to be modified by the program, but may be 60The array pointed to is not to be modified by the program, but may be
56overwritten by subsequent calls to 61overwritten by subsequent calls to
57.Fn strerror . 62.Fn strerror .
63.Pp
64.Fn strerror_r
65is a thread safe version of
66.Fn strerror
67that places the error message in the given buffer
68.Fa strerrbuf .
69If the error message is larger then
70.Fa buflen
71the message will be truncated to fit within buflen and
72.Er ERANGE
73is returned.
74.Fn strerror_r
75returns zero upon successful completion.
76An error number is returned, otherwise.
58.Sh SEE ALSO 77.Sh SEE ALSO
59.Xr intro 2 , 78.Xr intro 2 ,
60.Xr perror 3 , 79.Xr perror 3 ,
@@ -64,3 +83,7 @@ The
64.Fn strerror 83.Fn strerror
65function conforms to 84function conforms to
66.St -ansiC . 85.St -ansiC .
86The
87.Fn strerror_r
88function conforms to
89.St -p1003.1 .
diff --git a/src/lib/libc/string/strerror.c b/src/lib/libc/string/strerror.c
index c3f5ab5d98..b884a67df3 100644
--- a/src/lib/libc/string/strerror.c
+++ b/src/lib/libc/string/strerror.c
@@ -32,8 +32,7 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)strerror.c 5.6 (Berkeley) 5/4/91";*/ 35static char *rcsid = "$OpenBSD: strerror.c,v 1.3 2002/02/16 21:27:24 millert Exp $";
36static char *rcsid = "$Id: strerror.c,v 1.1.1.1 1995/10/18 08:42:22 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
38 37
39#include <string.h> 38#include <string.h>
@@ -45,7 +44,7 @@ static char *rcsid = "$Id: strerror.c,v 1.1.1.1 1995/10/18 08:42:22 deraadt Exp
45 * internal function __strerror(). 44 * internal function __strerror().
46 */ 45 */
47 46
48extern char *__strerror __P((int, char *)); 47extern char *__strerror(int, char *);
49 48
50char * 49char *
51strerror(num) 50strerror(num)
diff --git a/src/lib/libc/string/strerror_r.c b/src/lib/libc/string/strerror_r.c
new file mode 100644
index 0000000000..aab6db5303
--- /dev/null
+++ b/src/lib/libc/string/strerror_r.c
@@ -0,0 +1,30 @@
1/* $OpenBSD: strerror_r.c,v 1.1 2002/11/21 20:45:05 marc Exp $ */
2/* Public Domain <marc@snafu.org> */
3
4#if defined(LIBC_SCCS) && !defined(lint)
5static char *rcsid = "$OpenBSD: strerror_r.c,v 1.1 2002/11/21 20:45:05 marc Exp $";
6#endif /* LIBC_SCCS and not lint */
7
8#include <errno.h>
9#include <limits.h>
10#include <string.h>
11
12extern char *__strerror(int, char *);
13
14int
15strerror_r(int errnum, char *strerrbuf, size_t buflen)
16{
17 int save_errno;
18 int ret_errno;
19 char buf[NL_TEXTMAX];
20
21 save_errno = errno;
22 errno = 0;
23 __strerror(errnum, buf);
24 if (strlcpy(strerrbuf, buf, buflen) >= buflen)
25 errno = ERANGE;
26 ret_errno = errno;
27 errno = save_errno;
28
29 return (ret_errno);
30}
diff --git a/src/lib/libc/string/strftime.3 b/src/lib/libc/string/strftime.3
deleted file mode 100644
index f14db4bb13..0000000000
--- a/src/lib/libc/string/strftime.3
+++ /dev/null
@@ -1,202 +0,0 @@
1.\" Copyright (c) 1989, 1991 The Regents of the University of California.
2.\" All rights reserved.
3.\"
4.\" This code is derived from software contributed to Berkeley by
5.\" the American National Standards Committee X3, on Information
6.\" Processing Systems.
7.\"
8.\" Redistribution and use in source and binary forms, with or without
9.\" modification, are permitted provided that the following conditions
10.\" are met:
11.\" 1. Redistributions of source code must retain the above copyright
12.\" notice, this list of conditions and the following disclaimer.
13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution.
16.\" 3. All advertising materials mentioning features or use of this software
17.\" must display the following acknowledgement:
18.\" This product includes software developed by the University of
19.\" California, Berkeley and its contributors.
20.\" 4. Neither the name of the University nor the names of its contributors
21.\" may be used to endorse or promote products derived from this software
22.\" without specific prior written permission.
23.\"
24.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE.
35.\"
36.\" from: @(#)strftime.3 5.12 (Berkeley) 6/29/91
37.\" $Id: strftime.3,v 1.1.1.1 1995/10/18 08:42:22 deraadt Exp $
38.\"
39.Dd June 29, 1991
40.Dt STRFTIME 3
41.Os
42.Sh NAME
43.Nm strftime
44.Nd format date and time
45.Sh SYNOPSIS
46.Fd #include <time.h>
47.Ft size_t
48.Fn strftime "char *buf" "size_t maxsize" "const char *format" "const struct tm *timeptr"
49.Sh DESCRIPTION
50The
51.Fn strftime
52function formats the information from
53.Fa timeptr
54into the buffer
55.Fa buf
56according to the string pointed to by
57.Fa format .
58.Pp
59The
60.Fa format
61string consists of zero or more conversion specifications and
62ordinary characters.
63All ordinary characters are copied directly into the buffer.
64A conversion specification consists of a percent sign
65.Ql %
66and one other character.
67.Pp
68No more than
69.Fa maxsize
70characters will be placed into the array.
71If the total number of resulting characters, including the terminating
72null character, is not more than
73.Fa maxsize ,
74.Fn strftime
75returns the number of characters in the array, not counting the
76terminating null.
77Otherwise, zero is returned.
78.Pp
79Each conversion specification is replaced by the characters as
80follows which are then copied into the buffer.
81.Bl -tag -width "xxxx"
82.It Cm \&%A
83is replaced by the locale's full weekday name.
84.It Cm %a
85is replaced by the locale's abbreviated weekday name.
86.It Cm \&%B
87is replaced by the locale's full month name.
88.It Cm \&%b No or Cm \&%h
89is replaced by the locale's abbreviated month name.
90.It Cm \&%C
91is replaced by the century (a year divided by 100 and truncated to an integer)
92as a decimal number (00-99).
93.It Cm \&%c
94is replaced by the locale's appropriate date and time representation.
95.It Cm \&%D
96is replaced by the date in the format
97.Dq Li %m/%d/%y .
98.It Cm \&%d
99is replaced by the day of the month as a decimal number (01-31).
100.It Cm \&%e
101is replaced by the day of month as a decimal number (1-31);
102single digits are preceded by a blank.
103.It Cm \&%H
104is replaced by the hour (24-hour clock) as a decimal number (00-23).
105.It Cm \&%I
106is replaced by the hour (12-hour clock) as a decimal number (01-12).
107.It Cm \&%j
108is replaced by the day of the year as a decimal number (001-366).
109.It Cm \&%k
110is replaced by the hour (24-hour clock) as a decimal number (0-23);
111single digits are preceded by a blank.
112.It Cm \&%l
113is replaced by the hour (12-hour clock) as a decimal number (1-12);
114single digits are preceded by a blank.
115.It Cm \&%M
116is replaced by the minute as a decimal number (00-59).
117.It Cm %m
118is replaced by the month as a decimal number (01-12).
119.It Cm %n
120is replaced by a newline.
121.It Cm %p
122is replaced by the locale's equivalent of either
123.Dq Tn AM
124or
125.Dq Tn PM .
126.It Cm \&%R
127is replaced by the time in the format
128.Dq Li %H:%M .
129.It Cm \&%r
130is replaced by the locale's representation of 12-hour clock time
131using AM/PM notation.
132.It Cm \&%T
133is replaced by the time in the format
134.Dq Li %H:%M:%S .
135.It Cm \&%t
136is replaced by a tab.
137.It Cm \&%S
138is replaced by the second as a decimal number (00-60).
139.It Cm %s
140is replaced by the number of seconds since the Epoch, UCT (see
141.Xr mktime 3 ) .
142.It Cm \&%U
143is replaced by the week number of the year (Sunday as the first day of
144the week) as a decimal number (00-53).
145.It Cm \&%u
146is replaced by the weekday (Monday as the first day of the week)
147as a decimal number (1-7).
148.It Cm \&%V
149is replaced by the week number of the year (Monday as the first day of
150the week) as a decimal number (01-53). If the week containing January
1511 has four or more days in the new year, then it is week 1; otherwise
152it is week 53 of the previous year, and the next week is week 1.
153.It Cm \&%W
154is replaced by the week number of the year (Monday as the first day of
155the week) as a decimal number (00-53).
156.It Cm \&%w
157is replaced by the weekday (Sunday as the first day of the week)
158as a decimal number (0-6).
159.It Cm \&%X
160is replaced by the locale's appropriate date representation.
161.It Cm \&%x
162is replaced by the locale's appropriate time representation.
163.It Cm \&%Y
164is replaced by the year with century as a decimal number.
165.It Cm \&%y
166is replaced by the year without century as a decimal number (00-99).
167.It Cm \&%Z
168is replaced by the time zone name.
169.It Cm %%
170is replaced by
171.Ql % .
172.El
173.Sh SEE ALSO
174.Xr date 1 ,
175.Xr ctime 3 ,
176.Xr printf 1 ,
177.Xr printf 3
178.Sh STANDARDS
179The
180.Fn strftime
181function
182conforms to
183.St -ansiC .
184The
185.Ql \&%C ,
186.Ql \&%D ,
187.Ql \&%e ,
188.Ql \&%h ,
189.Ql \&%k ,
190.Ql \&%l ,
191.Ql \&%n ,
192.Ql \&%r ,
193.Ql \&%R ,
194.Ql \&%s .
195.Ql \&%t ,
196.Ql \&%T ,
197.Ql \&%u ,
198and
199.Ql \&%V
200conversion specifications are extensions.
201.Sh BUGS
202There is no conversion specification for the phase of the moon.
diff --git a/src/lib/libc/string/strftime.c b/src/lib/libc/string/strftime.c
deleted file mode 100644
index fffa9ecbb0..0000000000
--- a/src/lib/libc/string/strftime.c
+++ /dev/null
@@ -1,317 +0,0 @@
1/*
2 * Copyright (c) 1989 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)strftime.c 5.11 (Berkeley) 2/24/91";*/
36static char *rcsid = "$Id: strftime.c,v 1.1.1.1 1995/10/18 08:42:22 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */
38
39#include <sys/localedef.h>
40#include <locale.h>
41#include <string.h>
42#include <tzfile.h>
43#include <time.h>
44
45static size_t gsize;
46static char *pt;
47static int _add(), _conv(), _secs();
48static size_t _fmt();
49
50size_t
51strftime(s, maxsize, format, t)
52 char *s;
53 size_t maxsize;
54 const char *format;
55 const struct tm *t;
56{
57 tzset();
58
59 pt = s;
60 if ((gsize = maxsize) < 1)
61 return(0);
62 if (_fmt(format, t)) {
63 *pt = '\0';
64 return(maxsize - gsize);
65 }
66 return(0);
67}
68
69#define SUN_WEEK(t) (((t)->tm_yday + 7 - \
70 ((t)->tm_wday)) / 7)
71#define MON_WEEK(t) (((t)->tm_yday + 7 - \
72 ((t)->tm_wday ? (t)->tm_wday - 1 : 6)) / 7)
73static size_t
74_fmt(format, t)
75 register char *format;
76 struct tm *t;
77{
78 for (; *format; ++format) {
79 if (*format == '%') {
80 ++format;
81 if (*format == 'E') {
82 /* Alternate Era */
83 ++format;
84 } else if (*format == 'O') {
85 /* Alternate numeric symbols */
86 ++format;
87 }
88 switch(*format) {
89 case '\0':
90 --format;
91 break;
92 case 'A':
93 if (t->tm_wday < 0 || t->tm_wday > 6)
94 return(0);
95 if (!_add(_CurrentTimeLocale->day[t->tm_wday]))
96 return(0);
97 continue;
98 case 'a':
99 if (t->tm_wday < 0 || t->tm_wday > 6)
100 return(0);
101 if (!_add(_CurrentTimeLocale->abday[t->tm_wday]))
102 return(0);
103 continue;
104 case 'B':
105 if (t->tm_mon < 0 || t->tm_mon > 11)
106 return(0);
107 if (!_add(_CurrentTimeLocale->mon[t->tm_mon]))
108 return(0);
109 continue;
110 case 'b':
111 case 'h':
112 if (t->tm_mon < 0 || t->tm_mon > 11)
113 return(0);
114 if (!_add(_CurrentTimeLocale->abmon[t->tm_mon]))
115 return(0);
116 continue;
117 case 'C':
118 if (!_conv((t->tm_year + TM_YEAR_BASE) / 100,
119 2, '0'))
120 return(0);
121 continue;
122 case 'c':
123 if (!_fmt(_CurrentTimeLocale->d_t_fmt, t))
124 return(0);
125 continue;
126 case 'D':
127 if (!_fmt("%m/%d/%y", t))
128 return(0);
129 continue;
130 case 'd':
131 if (!_conv(t->tm_mday, 2, '0'))
132 return(0);
133 continue;
134 case 'e':
135 if (!_conv(t->tm_mday, 2, ' '))
136 return(0);
137 continue;
138 case 'H':
139 if (!_conv(t->tm_hour, 2, '0'))
140 return(0);
141 continue;
142 case 'I':
143 if (!_conv(t->tm_hour % 12 ?
144 t->tm_hour % 12 : 12, 2, '0'))
145 return(0);
146 continue;
147 case 'j':
148 if (!_conv(t->tm_yday + 1, 3, '0'))
149 return(0);
150 continue;
151 case 'k':
152 if (!_conv(t->tm_hour, 2, ' '))
153 return(0);
154 continue;
155 case 'l':
156 if (!_conv(t->tm_hour % 12 ?
157 t->tm_hour % 12: 12, 2, ' '))
158 return(0);
159 continue;
160 case 'M':
161 if (!_conv(t->tm_min, 2, '0'))
162 return(0);
163 continue;
164 case 'm':
165 if (!_conv(t->tm_mon + 1, 2, '0'))
166 return(0);
167 continue;
168 case 'n':
169 if (!_add("\n"))
170 return(0);
171 continue;
172 case 'p':
173 if (!_add(_CurrentTimeLocale->am_pm[t->tm_hour >= 12]))
174 return(0);
175 continue;
176 case 'R':
177 if (!_fmt("%H:%M", t))
178 return(0);
179 continue;
180 case 'r':
181 if (!_fmt(_CurrentTimeLocale->t_fmt_ampm, t))
182 return(0);
183 continue;
184 case 'S':
185 if (!_conv(t->tm_sec, 2, '0'))
186 return(0);
187 continue;
188 case 's':
189 if (!_secs(t))
190 return(0);
191 continue;
192 case 'T':
193 if (!_fmt("%H:%M:%S", t))
194 return(0);
195 continue;
196 case 't':
197 if (!_add("\t"))
198 return(0);
199 continue;
200 case 'U':
201 if (!_conv(SUN_WEEK(t), 2, '0'))
202 return(0);
203 continue;
204 case 'u':
205 if (!_conv(t->tm_wday ? t->tm_wday : 7, 2, '0'))
206 return(0);
207 continue;
208 case 'V':
209 {
210 /* ISO 8601 Week Of Year:
211 If the week (Monday - Sunday) containing
212 January 1 has four or more days in the new
213 year, then it is week 1; otherwise it is
214 week 53 of the previous year and the next
215 week is week one. */
216
217 int week = MON_WEEK(t);
218
219 if (((t->tm_yday + 7 - (t->tm_wday + 1)) % 7) >= 4) {
220 week++;
221 } else if (week == 0) {
222 week = 53;
223 }
224
225 if (!_conv(week, 2, '0'))
226 return(0);
227 continue;
228 }
229 case 'W':
230 if (!_conv(MON_WEEK(t), 2, '0'))
231 return(0);
232 continue;
233 case 'w':
234 if (!_conv(t->tm_wday, 1, '0'))
235 return(0);
236 continue;
237 case 'x':
238 if (!_fmt(_CurrentTimeLocale->d_fmt, t))
239 return(0);
240 continue;
241 case 'X':
242 if (!_fmt(_CurrentTimeLocale->t_fmt, t))
243 return(0);
244 continue;
245 case 'y':
246 if (!_conv((t->tm_year + TM_YEAR_BASE) % 100,
247 2, '0'))
248 return(0);
249 continue;
250 case 'Y':
251 if (!_conv((t->tm_year + TM_YEAR_BASE), 4, '0'))
252 return(0);
253 continue;
254 case 'Z':
255 if (t->tm_zone && !_add(t->tm_zone))
256 return(0);
257 continue;
258 case '%':
259 /*
260 * X311J/88-090 (4.12.3.5): if conversion char is
261 * undefined, behavior is undefined. Print out the
262 * character itself as printf(3) does.
263 */
264 default:
265 break;
266 }
267 }
268 if (!gsize--)
269 return(0);
270 *pt++ = *format;
271 }
272 return(gsize);
273}
274
275static
276_secs(t)
277 struct tm *t;
278{
279 static char buf[15];
280 register time_t s;
281 register char *p;
282 struct tm tmp;
283
284 /* Make a copy, mktime(3) modifies the tm struct. */
285 tmp = *t;
286 s = mktime(&tmp);
287 for (p = buf + sizeof(buf) - 2; s > 0 && p > buf; s /= 10)
288 *p-- = s % 10 + '0';
289 return(_add(++p));
290}
291
292static
293_conv(n, digits, pad)
294 int n, digits;
295 char pad;
296{
297 static char buf[10];
298 register char *p;
299
300 for (p = buf + sizeof(buf) - 2; n > 0 && p > buf; n /= 10, --digits)
301 *p-- = n % 10 + '0';
302 while (p > buf && digits-- > 0)
303 *p-- = pad;
304 return(_add(++p));
305}
306
307static
308_add(str)
309 register char *str;
310{
311 for (;; ++pt, --gsize) {
312 if (!gsize)
313 return(0);
314 if (!(*pt = *str++))
315 return(1);
316 }
317}
diff --git a/src/lib/libc/string/string.3 b/src/lib/libc/string/string.3
index aaf97e0321..7a67b96b53 100644
--- a/src/lib/libc/string/string.3
+++ b/src/lib/libc/string/string.3
@@ -31,27 +31,28 @@
31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32.\" SUCH DAMAGE. 32.\" SUCH DAMAGE.
33.\" 33.\"
34.\" from: @(#)string.3 6.9 (Berkeley) 4/19/91 34.\" $OpenBSD: string.3,v 1.8 2000/04/21 15:24:20 aaron Exp $
35.\" $Id: string.3,v 1.1.1.1 1995/10/18 08:42:22 deraadt Exp $
36.\" 35.\"
37.Dd April 19, 1991 36.Dd April 19, 1991
38.Dt STRING 3 37.Dt STRING 3
39.Os BSD 4 38.Os
40.Sh NAME 39.Sh NAME
41.Nm strcat , 40.Nm strcat ,
41.Nm strlcat ,
42.Nm strncat , 42.Nm strncat ,
43.Nm strchr , 43.Nm strchr ,
44.Nm strrchr , 44.Nm strrchr ,
45.Nm strcmp , 45.Nm strcmp ,
46.Nm strncmp , 46.Nm strncmp ,
47.Nm strcasecmp, 47.Nm strcasecmp ,
48.Nm strncasecmp , 48.Nm strncasecmp ,
49.Nm strcpy , 49.Nm strcpy ,
50.Nm strlcpy ,
50.Nm strncpy , 51.Nm strncpy ,
51.Nm strerror , 52.Nm strerror ,
52.Nm strlen , 53.Nm strlen ,
53.Nm strpbrk , 54.Nm strpbrk ,
54.Nm strsep, 55.Nm strsep ,
55.Nm strspn , 56.Nm strspn ,
56.Nm strcspn , 57.Nm strcspn ,
57.Nm strstr , 58.Nm strstr ,
@@ -62,7 +63,9 @@
62.Sh SYNOPSIS 63.Sh SYNOPSIS
63.Fd #include <string.h> 64.Fd #include <string.h>
64.Ft char * 65.Ft char *
65.Fn strcat "char *s" "const char * append" 66.Fn strcat "char *s" "const char *append"
67.Ft char *
68.Fn strlcat "char *s" "const char *append" "size_t size"
66.Ft char * 69.Ft char *
67.Fn strncat "char *s" "const char *append" "size_t count" 70.Fn strncat "char *s" "const char *append" "size_t count"
68.Ft char * 71.Ft char *
@@ -80,6 +83,8 @@
80.Ft char * 83.Ft char *
81.Fn strcpy "char *dst" "const char *src" 84.Fn strcpy "char *dst" "const char *src"
82.Ft char * 85.Ft char *
86.Fn strlcpy "char *dst" "const char *src" "size_t size"
87.Ft char *
83.Fn strncpy "char *dst" "const char *src" "size_t count" 88.Fn strncpy "char *dst" "const char *src" "size_t count"
84.Ft char * 89.Ft char *
85.Fn strerror "int errno" 90.Fn strerror "int errno"
@@ -103,7 +108,7 @@
103.Fn rindex "const char *s" "int c" 108.Fn rindex "const char *s" "int c"
104.Sh DESCRIPTION 109.Sh DESCRIPTION
105The string functions 110The string functions
106functions manipulate strings terminated by a 111manipulate strings terminated by a
107null byte. 112null byte.
108.Pp 113.Pp
109See the specific manual pages for more information. 114See the specific manual pages for more information.
@@ -115,23 +120,25 @@ Except as noted in their specific manual pages,
115the string functions do not test the destination 120the string functions do not test the destination
116for size limitations. 121for size limitations.
117.Sh SEE ALSO 122.Sh SEE ALSO
123.Xr bstring 3 ,
118.Xr index 3 , 124.Xr index 3 ,
125.Xr rindex 3 ,
126.Xr strcasecmp 3 ,
119.Xr strcat 3 , 127.Xr strcat 3 ,
120.Xr strchr 3 , 128.Xr strchr 3 ,
121.Xr strrchr 3 ,
122.Xr strcmp 3 , 129.Xr strcmp 3 ,
123.Xr strcasecmp 3 ,
124.Xr strcpy 3 , 130.Xr strcpy 3 ,
131.Xr strcspn 3 ,
125.Xr strerror 3 , 132.Xr strerror 3 ,
133.Xr strlcat 3 ,
134.Xr strlcpy 3 ,
126.Xr strlen 3 , 135.Xr strlen 3 ,
127.Xr strpbrk 3 , 136.Xr strpbrk 3 ,
137.Xr strrchr 3 ,
128.Xr strsep 3 , 138.Xr strsep 3 ,
129.Xr strspn 3 , 139.Xr strspn 3 ,
130.Xr strcspn 3 ,
131.Xr strstr 3 , 140.Xr strstr 3 ,
132.Xr strtok 3 , 141.Xr strtok 3
133.Xr rindex 3
134.Xr bstring 3
135.Sh STANDARDS 142.Sh STANDARDS
136The 143The
137.Fn strcat , 144.Fn strcat ,
@@ -145,12 +152,10 @@ The
145.Fn strerror , 152.Fn strerror ,
146.Fn strlen , 153.Fn strlen ,
147.Fn strpbrk , 154.Fn strpbrk ,
148.Fn strsep ,
149.Fn strspn , 155.Fn strspn ,
150.Fn strcspn , 156.Fn strcspn ,
151.Fn strstr , 157.Fn strstr ,
152and 158and
153.Fn strtok 159.Fn strtok
154functions 160functions conform to
155conform to
156.St -ansiC . 161.St -ansiC .
diff --git a/src/lib/libc/string/strlcat.c b/src/lib/libc/string/strlcat.c
new file mode 100644
index 0000000000..16c59b2759
--- /dev/null
+++ b/src/lib/libc/string/strlcat.c
@@ -0,0 +1,59 @@
1/* $OpenBSD: strlcat.c,v 1.10 2003/04/12 21:56:39 millert Exp $ */
2
3/*
4 * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND TODD C. MILLER DISCLAIMS ALL
11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
12 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL TODD C. MILLER BE LIABLE
13 * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
15 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
16 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#if defined(LIBC_SCCS) && !defined(lint)
20static char *rcsid = "$OpenBSD: strlcat.c,v 1.10 2003/04/12 21:56:39 millert Exp $";
21#endif /* LIBC_SCCS and not lint */
22
23#include <sys/types.h>
24#include <string.h>
25
26/*
27 * Appends src to string dst of size siz (unlike strncat, siz is the
28 * full size of dst, not space left). At most siz-1 characters
29 * will be copied. Always NUL terminates (unless siz <= strlen(dst)).
30 * Returns strlen(src) + MIN(siz, strlen(initial dst)).
31 * If retval >= siz, truncation occurred.
32 */
33size_t
34strlcat(char *dst, const char *src, size_t siz)
35{
36 register char *d = dst;
37 register const char *s = src;
38 register size_t n = siz;
39 size_t dlen;
40
41 /* Find the end of dst and adjust bytes left but don't go past end */
42 while (n-- != 0 && *d != '\0')
43 d++;
44 dlen = d - dst;
45 n = siz - dlen;
46
47 if (n == 0)
48 return(dlen + strlen(s));
49 while (*s != '\0') {
50 if (n != 1) {
51 *d++ = *s;
52 n--;
53 }
54 s++;
55 }
56 *d = '\0';
57
58 return(dlen + (s - src)); /* count does not include NUL */
59}
diff --git a/src/lib/libc/string/strlcpy.3 b/src/lib/libc/string/strlcpy.3
new file mode 100644
index 0000000000..b6c58b5a75
--- /dev/null
+++ b/src/lib/libc/string/strlcpy.3
@@ -0,0 +1,179 @@
1.\" $OpenBSD: strlcpy.3,v 1.15 2003/04/12 21:56:39 millert Exp $
2.\"
3.\" Copyright (c) 1998, 2000 Todd C. Miller <Todd.Miller@courtesan.com>
4.\"
5.\" Permission to use, copy, modify, and distribute this software for any
6.\" purpose with or without fee is hereby granted, provided that the above
7.\" copyright notice and this permission notice appear in all copies.
8.\"
9.\" THE SOFTWARE IS PROVIDED "AS IS" AND TODD C. MILLER DISCLAIMS ALL
10.\" WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
11.\" OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL TODD C. MILLER BE LIABLE
12.\" FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
14.\" OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
15.\" CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16.\"
17.Dd June 22, 1998
18.Dt STRLCPY 3
19.Os
20.Sh NAME
21.Nm strlcpy ,
22.Nm strlcat
23.Nd size-bounded string copying and concatenation
24.Sh SYNOPSIS
25.Fd #include <string.h>
26.Ft size_t
27.Fn strlcpy "char *dst" "const char *src" "size_t size"
28.Ft size_t
29.Fn strlcat "char *dst" "const char *src" "size_t size"
30.Sh DESCRIPTION
31The
32.Fn strlcpy
33and
34.Fn strlcat
35functions copy and concatenate strings respectively.
36They are designed
37to be safer, more consistent, and less error prone replacements for
38.Xr strncpy 3
39and
40.Xr strncat 3 .
41Unlike those functions,
42.Fn strlcpy
43and
44.Fn strlcat
45take the full size of the buffer (not just the length) and guarantee to
46NUL-terminate the result (as long as
47.Fa size
48is larger than 0 or, in the case of
49.Fn strlcat ,
50as long as there is at least one byte free in
51.Fa dst ) .
52Note that you should include a byte for the NUL in
53.Fa size .
54Also note that
55.Fn strlcpy
56and
57.Fn strlcat
58only operate on true
59.Dq C
60strings.
61This means that for
62.Fn strlcpy
63.Fa src
64must be NUL-terminated and for
65.Fn strlcat
66both
67.Fa src
68and
69.Fa dst
70must be NUL-terminated.
71.Pp
72The
73.Fn strlcpy
74function copies up to
75.Fa size
76- 1 characters from the NUL-terminated string
77.Fa src
78to
79.Fa dst ,
80NUL-terminating the result.
81.Pp
82The
83.Fn strlcat
84function appends the NUL-terminated string
85.Fa src
86to the end of
87.Fa dst .
88It will append at most
89.Fa size
90- strlen(dst) - 1 bytes, NUL-terminating the result.
91.Sh RETURN VALUES
92The
93.Fn strlcpy
94and
95.Fn strlcat
96functions return the total length of the string they tried to create.
97For
98.Fn strlcpy
99that means the length of
100.Fa src .
101For
102.Fn strlcat
103that means the initial length of
104.Fa dst
105plus
106the length of
107.Fa src .
108While this may seem somewhat confusing it was done to make
109truncation detection simple.
110.Pp
111Note however, that if
112.Fn strlcat
113traverses
114.Fa size
115characters without finding a NUL, the length of the string is considered
116to be
117.Fa size
118and the destination string will not be NUL-terminated (since there was
119no space for the NUL).
120This keeps
121.Fn strlcat
122from running off the end of a string.
123In practice this should not happen (as it means that either
124.Fa size
125is incorrect or that
126.Fa dst
127is not a proper
128.Dq C
129string).
130The check exists to prevent potential security problems in incorrect code.
131.Sh EXAMPLES
132The following code fragment illustrates the simple case:
133.Bd -literal -offset indent
134char *s, *p, buf[BUFSIZ];
135
136\&...
137
138(void)strlcpy(buf, s, sizeof(buf));
139(void)strlcat(buf, p, sizeof(buf));
140.Ed
141.Pp
142To detect truncation, perhaps while building a pathname, something
143like the following might be used:
144.Bd -literal -offset indent
145char *dir, *file, pname[MAXPATHLEN];
146
147\&...
148
149if (strlcpy(pname, dir, sizeof(pname)) >= sizeof(pname))
150 goto toolong;
151if (strlcat(pname, file, sizeof(pname)) >= sizeof(pname))
152 goto toolong;
153.Ed
154.Pp
155Since we know how many characters we copied the first time, we can
156speed things up a bit by using a copy instead of an append:
157.Bd -literal -offset indent
158char *dir, *file, pname[MAXPATHLEN];
159size_t n;
160
161\&...
162
163n = strlcpy(pname, dir, sizeof(pname));
164if (n >= sizeof(pname))
165 goto toolong;
166if (strlcpy(pname + n, file, sizeof(pname) - n) >= sizeof(pname) - n)
167 goto toolong;
168.Ed
169.Pp
170However, one may question the validity of such optimizations, as they
171defeat the whole purpose of
172.Fn strlcpy
173and
174.Fn strlcat .
175As a matter of fact, the first version of this manual page got it wrong.
176.Sh SEE ALSO
177.Xr snprintf 3 ,
178.Xr strncat 3 ,
179.Xr strncpy 3
diff --git a/src/lib/libc/string/strlcpy.c b/src/lib/libc/string/strlcpy.c
new file mode 100644
index 0000000000..8da97768c0
--- /dev/null
+++ b/src/lib/libc/string/strlcpy.c
@@ -0,0 +1,55 @@
1/* $OpenBSD: strlcpy.c,v 1.7 2003/04/12 21:56:39 millert Exp $ */
2
3/*
4 * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND TODD C. MILLER DISCLAIMS ALL
11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
12 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL TODD C. MILLER BE LIABLE
13 * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
15 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
16 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#if defined(LIBC_SCCS) && !defined(lint)
20static char *rcsid = "$OpenBSD: strlcpy.c,v 1.7 2003/04/12 21:56:39 millert Exp $";
21#endif /* LIBC_SCCS and not lint */
22
23#include <sys/types.h>
24#include <string.h>
25
26/*
27 * Copy src to string dst of size siz. At most siz-1 characters
28 * will be copied. Always NUL terminates (unless siz == 0).
29 * Returns strlen(src); if retval >= siz, truncation occurred.
30 */
31size_t
32strlcpy(char *dst, const char *src, size_t siz)
33{
34 register char *d = dst;
35 register const char *s = src;
36 register size_t n = siz;
37
38 /* Copy as many bytes as will fit */
39 if (n != 0 && --n != 0) {
40 do {
41 if ((*d++ = *s++) == 0)
42 break;
43 } while (--n != 0);
44 }
45
46 /* Not enough room in dst, add NUL and traverse rest of src */
47 if (n == 0) {
48 if (siz != 0)
49 *d = '\0'; /* NUL-terminate dst */
50 while (*s++)
51 ;
52 }
53
54 return(s - src - 1); /* count does not include NUL */
55}
diff --git a/src/lib/libc/string/strlen.3 b/src/lib/libc/string/strlen.3
index f4aff363ee..759e724056 100644
--- a/src/lib/libc/string/strlen.3
+++ b/src/lib/libc/string/strlen.3
@@ -33,15 +33,14 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)strlen.3 5.4 (Berkeley) 6/29/91 36.\" $OpenBSD: strlen.3,v 1.4 2000/04/21 15:24:20 aaron Exp $
37.\" $Id: strlen.3,v 1.1.1.1 1995/10/18 08:42:22 deraadt Exp $
38.\" 37.\"
39.Dd June 29, 1991 38.Dd June 29, 1991
40.Dt STRLEN 3 39.Dt STRLEN 3
41.Os 40.Os
42.Sh NAME 41.Sh NAME
43.Nm strlen 42.Nm strlen
44.Nd find length of string 43.Nd find length of a string
45.Sh SYNOPSIS 44.Sh SYNOPSIS
46.Fd #include <string.h> 45.Fd #include <string.h>
47.Ft size_t 46.Ft size_t
@@ -49,23 +48,18 @@
49.Sh DESCRIPTION 48.Sh DESCRIPTION
50The 49The
51.Fn strlen 50.Fn strlen
52function 51function computes the length of the string
53computes the length of the string
54.Fa s . 52.Fa s .
55.Sh RETURN VALUES 53.Sh RETURN VALUES
56The 54The
57.Fn strlen 55.Fn strlen
58function 56function returns the number of characters that precede the terminating
59returns 57.Tn NUL
60the number of characters that precede the
61terminating
62.Dv NUL
63character. 58character.
64.Sh SEE ALSO 59.Sh SEE ALSO
65.Xr string 3 60.Xr string 3
66.Sh STANDARDS 61.Sh STANDARDS
67The 62The
68.Fn strlen 63.Fn strlen
69function 64function conforms to
70conforms to
71.St -ansiC . 65.St -ansiC .
diff --git a/src/lib/libc/string/strlen.c b/src/lib/libc/string/strlen.c
index d23aadafc0..ab006e04c2 100644
--- a/src/lib/libc/string/strlen.c
+++ b/src/lib/libc/string/strlen.c
@@ -1,6 +1,8 @@
1/* $OpenBSD: strlen.c,v 1.4 2001/07/29 21:15:23 millert Exp $ */
2
1/*- 3/*-
2 * Copyright (c) 1990 The Regents of the University of California. 4 * Copyright (c) 1990, 1993
3 * All rights reserved. 5 * The Regents of the University of California. All rights reserved.
4 * 6 *
5 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
@@ -32,19 +34,23 @@
32 */ 34 */
33 35
34#if defined(LIBC_SCCS) && !defined(lint) 36#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)strlen.c 5.5 (Berkeley) 1/26/91";*/ 37static char *rcsid = "$OpenBSD: strlen.c,v 1.4 2001/07/29 21:15:23 millert Exp $";
36static char *rcsid = "$Id: strlen.c,v 1.1.1.1 1995/10/18 08:42:22 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 38#endif /* LIBC_SCCS and not lint */
38 39
40#if !defined(_KERNEL) && !defined(_STANDALONE)
39#include <string.h> 41#include <string.h>
42#else
43#include <lib/libkern/libkern.h>
44#endif
40 45
41size_t 46size_t
42strlen(str) 47strlen(str)
43 const char *str; 48 const char *str;
44{ 49{
45 register const char *s; 50 const char *s;
46 51
47 for (s = str; *s; ++s); 52 for (s = str; *s; ++s)
48 return(s - str); 53 ;
54 return (s - str);
49} 55}
50 56
diff --git a/src/lib/libc/string/strmode.3 b/src/lib/libc/string/strmode.3
index 1907e7ab03..36452bfd95 100644
--- a/src/lib/libc/string/strmode.3
+++ b/src/lib/libc/string/strmode.3
@@ -1,5 +1,7 @@
1.\" Copyright (c) 1990, 1991 The Regents of the University of California. 1.\" $OpenBSD: strmode.3,v 1.9 2003/04/02 19:00:26 jmc Exp $
2.\" All rights reserved. 2.\"
3.\" Copyright (c) 1990, 1991, 1993
4.\" The Regents of the University of California. All rights reserved.
3.\" 5.\"
4.\" Redistribution and use in source and binary forms, with or without 6.\" Redistribution and use in source and binary forms, with or without
5.\" modification, are permitted provided that the following conditions 7.\" modification, are permitted provided that the following conditions
@@ -29,10 +31,9 @@
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE. 32.\" SUCH DAMAGE.
31.\" 33.\"
32.\" from: @(#)strmode.3 5.4 (Berkeley) 7/31/91 34.\" @(#)strmode.3 8.3 (Berkeley) 7/28/94
33.\" $Id: strmode.3,v 1.1.1.1 1995/10/18 08:42:22 deraadt Exp $
34.\" 35.\"
35.Dd July 31, 1991 36.Dd July 28, 1994
36.Dt STRMODE 3 37.Dt STRMODE 3
37.Os 38.Os
38.Sh NAME 39.Sh NAME
@@ -45,15 +46,13 @@
45.Sh DESCRIPTION 46.Sh DESCRIPTION
46The 47The
47.Fn strmode 48.Fn strmode
48function 49function converts a file
49converts a file
50.Fa mode 50.Fa mode
51(the type and permission information associated with an inode, see 51(the type and permission information associated with an inode, see
52.Xr stat 2 ) 52.Xr stat 2 )
53into a symbolic string which is stored in the location referenced by 53into a symbolic string which is stored in the location referenced by
54.Fa bp . 54.Fa bp .
55This stored string is eleven characters in length plus a trailing 55This stored string is eleven characters in length plus a trailing null byte.
56.Dv NULL .
57.Pp 56.Pp
58The first character is the inode type, and will be one of the following: 57The first character is the inode type, and will be one of the following:
59.Pp 58.Pp
@@ -69,9 +68,11 @@ directory
69.It l 68.It l
70symbolic link 69symbolic link
71.It p 70.It p
72fifo 71FIFO
73.It s 72.It s
74socket 73socket
74.It w
75whiteout
75.It ? 76.It ?
76unknown inode type 77unknown inode type
77.El 78.El
@@ -80,46 +81,58 @@ The next nine characters encode three sets of permissions, in three
80characters each. 81characters each.
81The first three characters are the permissions for the owner of the 82The first three characters are the permissions for the owner of the
82file, the second three for the group the file belongs to, and the 83file, the second three for the group the file belongs to, and the
83third for the ``other'', or default, set of users. 84third for the
85.Dq other ,
86or default, set of users.
84.Pp 87.Pp
85Permission checking is done as specifically as possible. 88Permission checking is done as specifically as possible.
86If read permission is denied to the owner of a file in the first set 89If read permission is denied to the owner of a file in the first set
87of permissions, the owner of the file will not be able to read the file. 90of permissions, the owner of the file will not be able to read the file.
88This is true even if the owner is in the file's group and the group 91This is true even if the owner is in the file's group and the group
89permissions allow reading or the ``other'' permissions allow reading. 92permissions allow reading or the
93.Dq other
94permissions allow reading.
90.Pp 95.Pp
91If the first character of the three character set is an ``r'', the file is 96If the first character of the three character set is an
92readable for that set of users; if a dash ``\-'', it is not readable. 97.Sq r ,
98the file is readable for that set of users; if a dash
99.Pq Ql - ,
100it is not readable.
93.Pp 101.Pp
94If the second character of the three character set is a ``w'', the file is 102If the second character of the three character set is a
95writable for that set of users; if a dash ``\-'', it is not writable. 103.Sq w ,
104the file is writable for that set of users; if a dash
105.Pq Ql - ,
106it is not writable.
96.Pp 107.Pp
97The third character is the first of the following characters that apply: 108The third character is the first of the following characters that apply:
98.Bl -tag -width xxxx 109.Bl -tag -width xxxx
99.It S 110.It S
100If the character is part of the owner permissions and the file is not 111If the character is part of the owner permissions and the file is not
101executable or the directory is not searchable, by the owner, and the 112executable or the directory is not searchable by the owner, and the
102set-user-id bit is set. 113set-user-ID bit is set.
103.It S 114.It S
104If the character is part of the group permissions and the file is not 115If the character is part of the group permissions and the file is not
105executable or the directory is not searchable, by the group, and the 116executable or the directory is not searchable by the group, and the
106set-group-id bit is set. 117set-group-ID bit is set.
107.It T 118.It T
108If the character is part of the other permissions and the file is not 119If the character is part of the other permissions and the file is not
109executable or the directory is not searchable, by others, and the ``sticky'' 120executable or the directory is not searchable by others, and the
121.Dq sticky
110.Pq Dv S_ISVTX 122.Pq Dv S_ISVTX
111bit is set. 123bit is set.
112.It s 124.It s
113If the character is part of the owner permissions and the file is 125If the character is part of the owner permissions and the file is
114executable or the directory searchable, by the owner, and the set-user-id 126executable or the directory searchable by the owner, and the set-user-ID
115bit is set. 127bit is set.
116.It s 128.It s
117If the character is part of the group permissions and the file is 129If the character is part of the group permissions and the file is
118executable or the directory searchable, by the group, and the set-group-id 130executable or the directory searchable by the group, and the set-group-ID
119bit is set. 131bit is set.
120.It t 132.It t
121If the character is part of the other permissions and the file is 133If the character is part of the other permissions and the file is
122executable or the directory searchable, by others, and the ``sticky'' 134executable or the directory searchable by others, and the
135.Dq sticky
123.Pq Dv S_ISVTX 136.Pq Dv S_ISVTX
124bit is set. 137bit is set.
125.It x 138.It x
@@ -128,14 +141,15 @@ The file is executable or the directory is searchable.
128None of the above apply. 141None of the above apply.
129.El 142.El
130.Pp 143.Pp
131The last character is a plus sign ``+'' if any there are any alternate 144The last character is a plus sign
145.Pq Ql +
146if there are any alternate
132or additional access control methods associated with the inode, otherwise 147or additional access control methods associated with the inode, otherwise
133it will be a space. 148it will be a space.
134.Sh RETURN VALUES 149.Sh RETURN VALUES
135The 150The
136.Fn strmode 151.Fn strmode
137function 152function always returns 0.
138always returns 0.
139.Sh SEE ALSO 153.Sh SEE ALSO
140.Xr chmod 1 , 154.Xr chmod 1 ,
141.Xr find 1 , 155.Xr find 1 ,
@@ -145,5 +159,5 @@ always returns 0.
145.Sh HISTORY 159.Sh HISTORY
146The 160The
147.Fn strmode 161.Fn strmode
148function 162function first appeared in
149.Ud . 163.Bx 4.4 .
diff --git a/src/lib/libc/string/strmode.c b/src/lib/libc/string/strmode.c
index 441fc76e90..5e7f15e857 100644
--- a/src/lib/libc/string/strmode.c
+++ b/src/lib/libc/string/strmode.c
@@ -32,8 +32,7 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)strmode.c 5.3 (Berkeley) 5/18/90";*/ 35static char *rcsid = "$OpenBSD: strmode.c,v 1.3 1997/06/13 13:57:20 deraadt Exp $";
36static char *rcsid = "$Id: strmode.c,v 1.1.1.1 1995/10/18 08:42:22 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
38 37
39#include <sys/types.h> 38#include <sys/types.h>
@@ -70,6 +69,11 @@ strmode(mode, p)
70 *p++ = 'p'; 69 *p++ = 'p';
71 break; 70 break;
72#endif 71#endif
72#ifdef S_IFWHT
73 case S_IFWHT: /* whiteout */
74 *p++ = 'w';
75 break;
76#endif
73 default: /* unknown */ 77 default: /* unknown */
74 *p++ = '?'; 78 *p++ = '?';
75 break; 79 break;
diff --git a/src/lib/libc/string/strncat.c b/src/lib/libc/string/strncat.c
index 3d96452af4..27ae2ba324 100644
--- a/src/lib/libc/string/strncat.c
+++ b/src/lib/libc/string/strncat.c
@@ -35,8 +35,7 @@
35 */ 35 */
36 36
37#if defined(LIBC_SCCS) && !defined(lint) 37#if defined(LIBC_SCCS) && !defined(lint)
38/*static char *sccsid = "from: @(#)strncat.c 5.6 (Berkeley) 1/26/91";*/ 38static char *rcsid = "$OpenBSD: strncat.c,v 1.2 1996/08/19 08:34:21 tholo Exp $";
39static char *rcsid = "$Id: strncat.c,v 1.1.1.1 1995/10/18 08:42:23 deraadt Exp $";
40#endif /* LIBC_SCCS and not lint */ 39#endif /* LIBC_SCCS and not lint */
41 40
42#include <string.h> 41#include <string.h>
diff --git a/src/lib/libc/string/strncmp.c b/src/lib/libc/string/strncmp.c
index 0638d4dcf2..0224957f8b 100644
--- a/src/lib/libc/string/strncmp.c
+++ b/src/lib/libc/string/strncmp.c
@@ -32,11 +32,14 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)strncmp.c 5.6 (Berkeley) 1/26/91";*/ 35static char *rcsid = "$OpenBSD: strncmp.c,v 1.3 1996/08/19 08:34:21 tholo Exp $";
36static char *rcsid = "$Id: strncmp.c,v 1.1.1.1 1995/10/18 08:42:23 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
38 37
38#ifndef _KERNEL
39#include <string.h> 39#include <string.h>
40#else
41#include <lib/libkern/libkern.h>
42#endif
40 43
41int 44int
42strncmp(s1, s2, n) 45strncmp(s1, s2, n)
diff --git a/src/lib/libc/string/strncpy.c b/src/lib/libc/string/strncpy.c
index 5215311b75..01bc8a872e 100644
--- a/src/lib/libc/string/strncpy.c
+++ b/src/lib/libc/string/strncpy.c
@@ -35,8 +35,7 @@
35 */ 35 */
36 36
37#if defined(LIBC_SCCS) && !defined(lint) 37#if defined(LIBC_SCCS) && !defined(lint)
38/*static char *sccsid = "from: @(#)strncpy.c 5.6 (Berkeley) 1/26/91";*/ 38static char *rcsid = "$OpenBSD: strncpy.c,v 1.2 1996/08/19 08:34:22 tholo Exp $";
39static char *rcsid = "$Id: strncpy.c,v 1.1.1.1 1995/10/18 08:42:23 deraadt Exp $";
40#endif /* LIBC_SCCS and not lint */ 39#endif /* LIBC_SCCS and not lint */
41 40
42#include <string.h> 41#include <string.h>
diff --git a/src/lib/libc/string/strpbrk.3 b/src/lib/libc/string/strpbrk.3
index 8578546c05..52bf13b924 100644
--- a/src/lib/libc/string/strpbrk.3
+++ b/src/lib/libc/string/strpbrk.3
@@ -33,8 +33,7 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)strpbrk.3 5.4 (Berkeley) 6/29/91 36.\" $OpenBSD: strpbrk.3,v 1.5 2000/04/21 15:24:20 aaron Exp $
37.\" $Id: strpbrk.3,v 1.1.1.1 1995/10/18 08:42:23 deraadt Exp $
38.\" 37.\"
39.Dd June 29, 1991 38.Dd June 29, 1991
40.Dt STRPBRK 3 39.Dt STRPBRK 3
@@ -49,8 +48,7 @@
49.Sh DESCRIPTION 48.Sh DESCRIPTION
50The 49The
51.Fn strpbrk 50.Fn strpbrk
52function 51function locates in the null-terminated string
53locates in the null-terminated string
54.Fa s 52.Fa s
55the first occurrence of any character in the string 53the first occurrence of any character in the string
56.Fa charset 54.Fa charset
@@ -58,13 +56,12 @@ and returns a pointer to this character.
58If no characters from 56If no characters from
59.Fa charset 57.Fa charset
60occur anywhere in 58occur anywhere in
61.Fa s 59.Fa s ,
62.Fn strpbrk 60.Fn strpbrk
63returns NULL. 61returns
62.Dv NULL .
64.Sh SEE ALSO 63.Sh SEE ALSO
65.Xr index 3 ,
66.Xr memchr 3 , 64.Xr memchr 3 ,
67.Xr rindex 3 ,
68.Xr strchr 3 , 65.Xr strchr 3 ,
69.Xr strcspn 3 , 66.Xr strcspn 3 ,
70.Xr strrchr 3 , 67.Xr strrchr 3 ,
@@ -75,6 +72,5 @@ returns NULL.
75.Sh STANDARDS 72.Sh STANDARDS
76The 73The
77.Fn strpbrk 74.Fn strpbrk
78function 75function conforms to
79conforms to
80.St -ansiC . 76.St -ansiC .
diff --git a/src/lib/libc/string/strpbrk.c b/src/lib/libc/string/strpbrk.c
index f1d542a525..748a3a8c94 100644
--- a/src/lib/libc/string/strpbrk.c
+++ b/src/lib/libc/string/strpbrk.c
@@ -32,8 +32,7 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)strpbrk.c 5.8 (Berkeley) 1/26/91";*/ 35static char *rcsid = "$OpenBSD: strpbrk.c,v 1.2 1996/08/19 08:34:23 tholo Exp $";
36static char *rcsid = "$Id: strpbrk.c,v 1.1.1.1 1995/10/18 08:42:23 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
38 37
39#include <string.h> 38#include <string.h>
diff --git a/src/lib/libc/string/strrchr.3 b/src/lib/libc/string/strrchr.3
index 1d98cbff24..394fc2aad3 100644
--- a/src/lib/libc/string/strrchr.3
+++ b/src/lib/libc/string/strrchr.3
@@ -33,28 +33,31 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)strrchr.3 5.3 (Berkeley) 6/29/91 36.\" $OpenBSD: strrchr.3,v 1.6 2000/04/21 15:24:20 aaron Exp $
37.\" $Id: strrchr.3,v 1.1.1.1 1995/10/18 08:42:23 deraadt Exp $
38.\" 37.\"
39.Dd June 29, 1991 38.Dd June 29, 1991
40.Dt STRRCHR 3 39.Dt STRRCHR 3
41.Os 40.Os
42.Sh NAME 41.Sh NAME
43.Nm strrchr 42.Nm strrchr ,
44.Nd locate character in string 43.Nm rindex
44.Nd locate last occurrence of a character in a string
45.Sh SYNOPSIS 45.Sh SYNOPSIS
46.Fd #include <string.h> 46.Fd #include <string.h>
47.Ft char * 47.Ft char *
48.Fn strrchr "const char *s" "int c" 48.Fn strrchr "const char *s" "int c"
49.Ft char *
50.Fn rindex "const char *s" "int c"
49.Sh DESCRIPTION 51.Sh DESCRIPTION
50The 52The
51.Fn strrchr 53.Fn strrchr
52function 54function locates the last occurrence of the character
53locates the last occurrence of
54.Fa c 55.Fa c
55(converted to a char)
56in the string 56in the string
57.Fa s . 57.Fa s .
58The terminating
59.Tn NUL
60character is considered part of the string.
58If 61If
59.Fa c 62.Fa c
60is 63is
@@ -62,20 +65,31 @@ is
62.Fn strrchr 65.Fn strrchr
63locates the terminating 66locates the terminating
64.Ql \e0 . 67.Ql \e0 .
68.Pp
69The
70.Fn rindex
71function is an old synonym for
72.Fn strrchr .
65.Sh RETURN VALUES 73.Sh RETURN VALUES
66The 74The
67.Fn strrchr 75.Fn strrchr
68function 76function returns a pointer to the located character or
69returns a pointer to the character, 77.Dv NULL
70or a null 78if the character does not appear in the string.
71pointer if 79.Sh EXAMPLES
72.Fa c 80After the following call to
73does not occur anywhere in 81.Fn strrchr ,
74.Fa s . 82.Va p
83will point to the string
84.Qq obar :
85.Bd -literal -offset indent
86char *p;
87char *s = "foobar";
88
89p = strrchr(s, 'o');
90.Ed
75.Sh SEE ALSO 91.Sh SEE ALSO
76.Xr index 3 ,
77.Xr memchr 3 , 92.Xr memchr 3 ,
78.Xr rindex 3 ,
79.Xr strchr 3 , 93.Xr strchr 3 ,
80.Xr strcspn 3 , 94.Xr strcspn 3 ,
81.Xr strpbrk 3 , 95.Xr strpbrk 3 ,
@@ -86,6 +100,9 @@ does not occur anywhere in
86.Sh STANDARDS 100.Sh STANDARDS
87The 101The
88.Fn strrchr 102.Fn strrchr
89function 103function conforms to
90conforms to
91.St -ansiC . 104.St -ansiC .
105.Pp
106The
107.Fn rindex
108function is deprecated and shouldn't be used in new code.
diff --git a/src/lib/libc/string/strsep.3 b/src/lib/libc/string/strsep.3
index 21aa7376f2..848dab1eb3 100644
--- a/src/lib/libc/string/strsep.3
+++ b/src/lib/libc/string/strsep.3
@@ -1,8 +1,11 @@
1.\" Copyright (c) 1990, 1991 The Regents of the University of California. 1.\" $OpenBSD: strsep.3,v 1.10 2001/11/21 14:32:45 deraadt Exp $
2.\" All rights reserved. 2.\"
3.\" Copyright (c) 1990, 1991, 1993
4.\" The Regents of the University of California. All rights reserved.
3.\" 5.\"
4.\" This code is derived from software contributed to Berkeley by 6.\" This code is derived from software contributed to Berkeley by
5.\" Chris Torek. 7.\" Chris Torek.
8.\"
6.\" Redistribution and use in source and binary forms, with or without 9.\" Redistribution and use in source and binary forms, with or without
7.\" modification, are permitted provided that the following conditions 10.\" modification, are permitted provided that the following conditions
8.\" are met: 11.\" are met:
@@ -31,10 +34,9 @@
31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32.\" SUCH DAMAGE. 35.\" SUCH DAMAGE.
33.\" 36.\"
34.\" from: @(#)strsep.3 5.3 (Berkeley) 4/19/91 37.\" @(#)strsep.3 8.1 (Berkeley) 6/9/93
35.\" $Id: strsep.3,v 1.1.1.1 1995/10/18 08:42:23 deraadt Exp $
36.\" 38.\"
37.Dd April 19, 1991 39.Dd June 9, 1993
38.Dt STRSEP 3 40.Dt STRSEP 3
39.Os 41.Os
40.Sh NAME 42.Sh NAME
@@ -43,27 +45,37 @@
43.Sh SYNOPSIS 45.Sh SYNOPSIS
44.Fd #include <string.h> 46.Fd #include <string.h>
45.Ft char * 47.Ft char *
46.Fn strsep "char **stringp" "char *delim" 48.Fn strsep "char **stringp" "const char *delim"
47.Sh DESCRIPTION 49.Sh DESCRIPTION
48The 50The
49.Fn strsep 51.Fn strsep
50locates in the null-terminated string at 52function locates, in the string referenced by
51.Fa *stringp
52the first occurrence of any character in
53.Fa delim
54and replaces this with a
55.Ql \e0 ,
56records the location of the immediate following character in
57.Fa *stringp , 53.Fa *stringp ,
58then returns the original value of 54the first occurrence of any character in the string
55.Fa delim
56(or the terminating
57.Ql \e0
58character) and replaces it with a
59.Ql \e0 .
60The location of the next character after the delimiter character
61(or
62.Dv NULL ,
63if the end of the string was reached) is stored in
59.Fa *stringp . 64.Fa *stringp .
60If no delimiter characters are found, 65The original value of
61.Fn strsep
62sets
63.Fa *stringp 66.Fa *stringp
67is returned.
68.Pp
69An
70.Dq empty
71field, i.e., one caused by two adjacent delimiter characters,
72can be detected by comparing the location referenced by the pointer returned
73by
74.Fn strsep
64to 75to
65.Dv NULL ; 76.Ql \e0 .
66if 77.Pp
78If
67.Fa *stringp 79.Fa *stringp
68is initially 80is initially
69.Dv NULL , 81.Dv NULL ,
@@ -73,20 +85,32 @@ returns
73.Sh EXAMPLES 85.Sh EXAMPLES
74The following uses 86The following uses
75.Fn strsep 87.Fn strsep
76to parse strings containing runs of white space, 88to parse a string, containing tokens delimited by whitespace, into an
77making up an argument vector: 89argument vector:
78.Bd -literal -offset indent 90.Bd -literal -offset indent
79char inputstring[100]; 91char **ap, *argv[10], *inputstring;
80char **argv[51], **ap = argv, *p, *val; 92
81/* set up inputstring */ 93for (ap = argv; ap < &argv[9] &&
82for (p = inputstring; p != NULL; ) { 94 (*ap = strsep(&inputstring, " \et")) != NULL;) {
83 while ((val = strsep(&p, " \et")) != NULL && *val == '\e0'); 95 if (**ap != '\e0')
84 *ap++ = val; 96 ap++;
85} 97}
86*ap = 0; 98*ap = NULL;
87.Ed 99.Ed
88.Sh HISTORY 100.Sh HISTORY
89The 101The
90.Fn strsep 102.Fn strsep
91function is 103function is intended as a replacement for the
92.Ud . 104.Fn strtok
105function.
106While the
107.Fn strtok
108function should be preferred for portability reasons (it conforms to
109.St -ansiC )
110it is unable to handle empty fields, i.e., detect fields delimited by
111two adjacent delimiter characters, or to be used for more than a single
112string at a time.
113The
114.Fn strsep
115function first appeared in
116.Bx 4.4 .
diff --git a/src/lib/libc/string/strsep.c b/src/lib/libc/string/strsep.c
index 69be7fe046..b69b715fc5 100644
--- a/src/lib/libc/string/strsep.c
+++ b/src/lib/libc/string/strsep.c
@@ -1,6 +1,8 @@
1/* $OpenBSD: strsep.c,v 1.3 1997/08/20 04:28:14 millert Exp $ */
2
1/*- 3/*-
2 * Copyright (c) 1990 The Regents of the University of California. 4 * Copyright (c) 1990, 1993
3 * All rights reserved. 5 * The Regents of the University of California. All rights reserved.
4 * 6 *
5 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
@@ -31,15 +33,19 @@
31 * SUCH DAMAGE. 33 * SUCH DAMAGE.
32 */ 34 */
33 35
36#include <string.h>
37#include <stdio.h>
38
34#if defined(LIBC_SCCS) && !defined(lint) 39#if defined(LIBC_SCCS) && !defined(lint)
35/*static const char sccsid[] = "from: @(#)strsep.c 5.4 (Berkeley) 1/26/91";*/ 40#if 0
36static char *rcsid = "$Id: strsep.c,v 1.1.1.1 1995/10/18 08:42:23 deraadt Exp $"; 41static char sccsid[] = "@(#)strsep.c 8.1 (Berkeley) 6/4/93";
42#else
43static char *rcsid = "$OpenBSD: strsep.c,v 1.3 1997/08/20 04:28:14 millert Exp $";
44#endif
37#endif /* LIBC_SCCS and not lint */ 45#endif /* LIBC_SCCS and not lint */
38 46
39#include <string.h>
40
41/* 47/*
42 * Get next token from string *stringp, where tokens are nonempty 48 * Get next token from string *stringp, where tokens are possibly-empty
43 * strings separated by characters from delim. 49 * strings separated by characters from delim.
44 * 50 *
45 * Writes NULs into the string at *stringp to end tokens. 51 * Writes NULs into the string at *stringp to end tokens.
@@ -47,7 +53,7 @@ static char *rcsid = "$Id: strsep.c,v 1.1.1.1 1995/10/18 08:42:23 deraadt Exp $"
47 * On return, *stringp points past the last NUL written (if there might 53 * On return, *stringp points past the last NUL written (if there might
48 * be further tokens), or is NULL (if there are definitely no more tokens). 54 * be further tokens), or is NULL (if there are definitely no more tokens).
49 * 55 *
50 * If *stringp is NULL, strtoken returns NULL. 56 * If *stringp is NULL, strsep returns NULL.
51 */ 57 */
52char * 58char *
53strsep(stringp, delim) 59strsep(stringp, delim)
diff --git a/src/lib/libc/string/strsignal.3 b/src/lib/libc/string/strsignal.3
index 3287fef53e..83b3775f4e 100644
--- a/src/lib/libc/string/strsignal.3
+++ b/src/lib/libc/string/strsignal.3
@@ -33,12 +33,11 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)strerror.3 6.9 (Berkeley) 6/29/91 36.\" $OpenBSD: strsignal.3,v 1.3 1999/05/23 14:11:03 aaron Exp $
37.\" $Id: strsignal.3,v 1.1.1.1 1995/10/18 08:42:23 deraadt Exp $
38.\" 37.\"
39.Dd June 29, 1991 38.Dd June 29, 1991
40.Dt STRSIGNAL 3 39.Dt STRSIGNAL 3
41.Os BSD 4 40.Os
42.Sh NAME 41.Sh NAME
43.Nm strsignal 42.Nm strsignal
44.Nd get signal description string 43.Nd get signal description string
diff --git a/src/lib/libc/string/strsignal.c b/src/lib/libc/string/strsignal.c
index ec4a267edf..90118f70f9 100644
--- a/src/lib/libc/string/strsignal.c
+++ b/src/lib/libc/string/strsignal.c
@@ -32,14 +32,13 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)strerror.c 5.6 (Berkeley) 5/4/91";*/ 35static char *rcsid = "$OpenBSD: strsignal.c,v 1.3 2002/02/16 21:27:24 millert Exp $";
36static char *rcsid = "$Id: strsignal.c,v 1.1.1.1 1995/10/18 08:42:23 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
38 37
39#include <string.h> 38#include <string.h>
40#include <limits.h> 39#include <limits.h>
41 40
42extern char *__strsignal __P((int, char *)); 41extern char *__strsignal(int, char *);
43 42
44char * 43char *
45strsignal(sig) 44strsignal(sig)
diff --git a/src/lib/libc/string/strspn.3 b/src/lib/libc/string/strspn.3
index 4de03aa58b..ca965aeb18 100644
--- a/src/lib/libc/string/strspn.3
+++ b/src/lib/libc/string/strspn.3
@@ -33,8 +33,7 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)strspn.3 5.3 (Berkeley) 6/29/91 36.\" $OpenBSD: strspn.3,v 1.6 2000/04/21 15:24:20 aaron Exp $
37.\" $Id: strspn.3,v 1.1.1.1 1995/10/18 08:42:23 deraadt Exp $
38.\" 37.\"
39.Dd June 29, 1991 38.Dd June 29, 1991
40.Dt STRSPN 3 39.Dt STRSPN 3
@@ -48,9 +47,8 @@
48.Fn strspn "const char *s" "const char *charset" 47.Fn strspn "const char *s" "const char *charset"
49.Sh DESCRIPTION 48.Sh DESCRIPTION
50The 49The
51.Xr strcspn 50.Fn strspn
52function 51function spans the initial part of the null-terminated string
53spans the initial part of the null-terminated string
54.Fa s 52.Fa s
55as long as the characters from 53as long as the characters from
56.Fa s 54.Fa s
@@ -59,12 +57,23 @@ occur in string
59.Sh RETURN VALUES 57.Sh RETURN VALUES
60The 58The
61.Fn strspn 59.Fn strspn
62function 60function returns the number of characters spanned.
63returns the number of characters spanned. 61.Sh EXAMPLES
62The following call to
63.Fn strspn
64will return 3, since the first three characters of string
65.Fa s
66are part of string
67.Fa charset :
68.Bd -literal -offset indent
69char *s = "foobar";
70char *charset = "of";
71size_t span;
72
73span = strspn(s, charset);
74.Ed
64.Sh SEE ALSO 75.Sh SEE ALSO
65.Xr index 3 ,
66.Xr memchr 3 , 76.Xr memchr 3 ,
67.Xr rindex 3 ,
68.Xr strchr 3 , 77.Xr strchr 3 ,
69.Xr strcspn 3 , 78.Xr strcspn 3 ,
70.Xr strpbrk 3 , 79.Xr strpbrk 3 ,
@@ -75,6 +84,5 @@ returns the number of characters spanned.
75.Sh STANDARDS 84.Sh STANDARDS
76The 85The
77.Fn strspn 86.Fn strspn
78function 87function conforms to
79conforms to
80.St -ansiC . 88.St -ansiC .
diff --git a/src/lib/libc/string/strspn.c b/src/lib/libc/string/strspn.c
index 6224b25c2a..41940f9190 100644
--- a/src/lib/libc/string/strspn.c
+++ b/src/lib/libc/string/strspn.c
@@ -32,8 +32,7 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)strspn.c 5.8 (Berkeley) 1/26/91";*/ 35static char *rcsid = "$OpenBSD: strspn.c,v 1.2 1996/08/19 08:34:26 tholo Exp $";
36static char *rcsid = "$Id: strspn.c,v 1.1.1.1 1995/10/18 08:42:23 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
38 37
39#include <string.h> 38#include <string.h>
diff --git a/src/lib/libc/string/strstr.3 b/src/lib/libc/string/strstr.3
index 24fdf540ed..10beea42ca 100644
--- a/src/lib/libc/string/strstr.3
+++ b/src/lib/libc/string/strstr.3
@@ -33,8 +33,7 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)strstr.3 5.3 (Berkeley) 6/29/91 36.\" $OpenBSD: strstr.3,v 1.5 2000/04/21 15:24:20 aaron Exp $
37.\" $Id: strstr.3,v 1.1.1.1 1995/10/18 08:42:23 deraadt Exp $
38.\" 37.\"
39.Dd June 29, 1991 38.Dd June 29, 1991
40.Dt STRSTR 3 39.Dt STRSTR 3
@@ -49,8 +48,7 @@
49.Sh DESCRIPTION 48.Sh DESCRIPTION
50The 49The
51.Fn strstr 50.Fn strstr
52function 51function locates the first occurrence of the null-terminated string
53locates the first occurrence of the null-terminated string
54.Fa little 52.Fa little
55in the null-terminated string 53in the null-terminated string
56.Fa big . 54.Fa big .
@@ -65,15 +63,14 @@ if
65occurs nowhere in 63occurs nowhere in
66.Fa big , 64.Fa big ,
67.Fn strstr 65.Fn strstr
68returns NULL; 66returns
67.Dv NULL ;
69otherwise 68otherwise
70.Fn strstr 69.Fn strstr
71returns a pointer to the first character of the first occurrence of 70returns a pointer to the first character of the first occurrence of
72.Fa little . 71.Fa little .
73.Sh SEE ALSO 72.Sh SEE ALSO
74.Xr index 3 ,
75.Xr memchr 3 , 73.Xr memchr 3 ,
76.Xr rindex 3 ,
77.Xr strchr 3 , 74.Xr strchr 3 ,
78.Xr strcspn 3 , 75.Xr strcspn 3 ,
79.Xr strpbrk 3 , 76.Xr strpbrk 3 ,
@@ -84,6 +81,5 @@ returns a pointer to the first character of the first occurrence of
84.Sh STANDARDS 81.Sh STANDARDS
85The 82The
86.Fn strstr 83.Fn strstr
87function 84function conforms to
88conforms to
89.St -ansiC . 85.St -ansiC .
diff --git a/src/lib/libc/string/strstr.c b/src/lib/libc/string/strstr.c
index 1ed59e357b..763c7e29d7 100644
--- a/src/lib/libc/string/strstr.c
+++ b/src/lib/libc/string/strstr.c
@@ -35,8 +35,7 @@
35 */ 35 */
36 36
37#if defined(LIBC_SCCS) && !defined(lint) 37#if defined(LIBC_SCCS) && !defined(lint)
38/*static char *sccsid = "from: @(#)strstr.c 5.2 (Berkeley) 1/26/91";*/ 38static char *rcsid = "$OpenBSD: strstr.c,v 1.2 1996/08/19 08:34:27 tholo Exp $";
39static char *rcsid = "$Id: strstr.c,v 1.1.1.1 1995/10/18 08:42:23 deraadt Exp $";
40#endif /* LIBC_SCCS and not lint */ 39#endif /* LIBC_SCCS and not lint */
41 40
42#include <string.h> 41#include <string.h>
diff --git a/src/lib/libc/string/strtok.3 b/src/lib/libc/string/strtok.3
index 644bd10aed..b8dad8eff0 100644
--- a/src/lib/libc/string/strtok.3
+++ b/src/lib/libc/string/strtok.3
@@ -33,29 +33,30 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)strtok.3 5.8 (Berkeley) 6/29/91 36.\" $OpenBSD: strtok.3,v 1.15 2001/08/06 10:42:26 mpech Exp $
37.\" $Id: strtok.3,v 1.1.1.1 1995/10/18 08:42:23 deraadt Exp $
38.\" 37.\"
39.Dd June 29, 1991 38.Dd June 29, 1991
40.Dt STRTOK 3 39.Dt STRTOK 3
41.Os BSD 3 40.Os
42.Sh NAME 41.Sh NAME
43.Nm strtok , 42.Nm strtok ,
44.Nm strsep 43.Nm strtok_r
45.Nd string token operations 44.Nd string token operations
46.Sh SYNOPSIS 45.Sh SYNOPSIS
47.Fd #include <string.h> 46.Fd #include <string.h>
48.Ft char * 47.Ft char *
49.Fn strtok "char *str" "const char *sep" 48.Fn strtok "char *str" "const char *sep"
49.Ft char *
50.Fn strtok_r "char *str" "const char *sep" "char **last"
50.Sh DESCRIPTION 51.Sh DESCRIPTION
51.Bf -symbolic 52.Bf -symbolic
52This interface is obsoleted by strsep(3). 53This interface is obsoleted by
54.Xr strsep 3 .
53.Ef 55.Ef
54.Pp 56.Pp
55The 57The
56.Fn strtok 58.Fn strtok
57function 59function is used to isolate sequential tokens in a null-terminated string,
58is used to isolate sequential tokens in a null-terminated string,
59.Fa str . 60.Fa str .
60These tokens are separated in the string by at least one of the 61These tokens are separated in the string by at least one of the
61characters in 62characters in
@@ -71,17 +72,65 @@ The separator string,
71must be supplied each time, and may change between calls. 72must be supplied each time, and may change between calls.
72.Pp 73.Pp
73The 74The
75.Fn strtok_r
76function is a version of
74.Fn strtok 77.Fn strtok
75function 78that takes an explicit context argument and is reentrant.
76returns a pointer to the beginning of each subsequent token in the string, 79.Pp
77after replacing the separator character itself with a 80The
78.Dv NUL 81.Fn strtok
82and
83.Fn strtok_r
84functions return a pointer to the beginning of each subsequent token
85in the string, after replacing the separator character itself with an
86.Tn ASCII NUL
79character. 87character.
80When no more tokens remain, a null pointer is returned. 88When no more tokens remain, a null pointer is returned.
89.Pp
90Since
91.Fn strtok
92and
93.Fn strtok_r
94modify the string,
95.Fa str
96should not point to an area in the initialized data segment.
97.Sh EXAMPLES
98The following will construct an array of pointers to each individual word in
99the string
100.Va s :
101.Bd -literal -offset indent
102#define MAXTOKENS 128
103
104char s[512], *p, *tokens[MAXTOKENS];
105char *last;
106int i = 0;
107
108snprintf(s, sizeof(s), "cat dog horse cow");
109
110for ((p = strtok_r(s, " ", &last)); p;
111 (p = strtok_r(NULL, " ", &last)), i++) {
112 if (i < MAXTOKENS - 1)
113 tokens[i] = p;
114}
115tokens[i] = NULL;
116.Ed
117.Pp
118That is,
119.Li tokens[0]
120will point to
121.Qq cat ,
122.Li tokens[1]
123will point to
124.Qq dog ,
125.Li tokens[2]
126will point to
127.Qq horse ,
128and
129.Li tokens[3]
130will point to
131.Qq cow .
81.Sh SEE ALSO 132.Sh SEE ALSO
82.Xr index 3 ,
83.Xr memchr 3 , 133.Xr memchr 3 ,
84.Xr rindex 3 ,
85.Xr strchr 3 , 134.Xr strchr 3 ,
86.Xr strcspn 3 , 135.Xr strcspn 3 ,
87.Xr strpbrk 3 , 136.Xr strpbrk 3 ,
@@ -92,21 +141,16 @@ When no more tokens remain, a null pointer is returned.
92.Sh STANDARDS 141.Sh STANDARDS
93The 142The
94.Fn strtok 143.Fn strtok
95function 144function conforms to
96conforms to
97.St -ansiC . 145.St -ansiC .
98.Sh BUGS 146.Sh BUGS
99There is no way to get tokens from multiple strings simultaneously.
100.Pp
101The System V 147The System V
102.Fn strtok , 148.Fn strtok ,
103if handed a string containing only delimiter characters, 149if handed a string containing only delimiter characters,
104will not alter the next starting point, so that a call to 150will not alter the next starting point, so that a call to
105.Fn strtok 151.Fn strtok
106with a different (or empty) delimiter string 152with a different (or empty) delimiter string
107may return a 153may return a non-null value.
108.Pf non- Dv NULL
109value.
110Since this implementation always alters the next starting point, 154Since this implementation always alters the next starting point,
111such a sequence of calls would always return 155such a sequence of calls would always return
112.Dv NULL . 156.Dv NULL .
diff --git a/src/lib/libc/string/strtok.c b/src/lib/libc/string/strtok.c
index 9f712579bf..d925dc75d0 100644
--- a/src/lib/libc/string/strtok.c
+++ b/src/lib/libc/string/strtok.c
@@ -32,8 +32,7 @@
32 */ 32 */
33 33
34#if defined(LIBC_SCCS) && !defined(lint) 34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)strtok.c 5.8 (Berkeley) 2/24/91";*/ 35static char *rcsid = "$OpenBSD: strtok.c,v 1.3 1999/11/09 11:19:46 art Exp $";
36static char *rcsid = "$Id: strtok.c,v 1.1.1.1 1995/10/18 08:42:23 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */ 36#endif /* LIBC_SCCS and not lint */
38 37
39#include <string.h> 38#include <string.h>
@@ -43,13 +42,23 @@ strtok(s, delim)
43 register char *s; 42 register char *s;
44 register const char *delim; 43 register const char *delim;
45{ 44{
45 static char *last;
46
47 return strtok_r(s, delim, &last);
48}
49
50char *
51strtok_r(s, delim, last)
52 register char *s;
53 register const char *delim;
54 char **last;
55{
46 register char *spanp; 56 register char *spanp;
47 register int c, sc; 57 register int c, sc;
48 char *tok; 58 char *tok;
49 static char *last;
50 59
51 60
52 if (s == NULL && (s = last) == NULL) 61 if (s == NULL && (s = *last) == NULL)
53 return (NULL); 62 return (NULL);
54 63
55 /* 64 /*
@@ -63,7 +72,7 @@ cont:
63 } 72 }
64 73
65 if (c == 0) { /* no non-delimiter characters */ 74 if (c == 0) { /* no non-delimiter characters */
66 last = NULL; 75 *last = NULL;
67 return (NULL); 76 return (NULL);
68 } 77 }
69 tok = s - 1; 78 tok = s - 1;
@@ -81,7 +90,7 @@ cont:
81 s = NULL; 90 s = NULL;
82 else 91 else
83 s[-1] = 0; 92 s[-1] = 0;
84 last = s; 93 *last = s;
85 return (tok); 94 return (tok);
86 } 95 }
87 } while (sc != 0); 96 } while (sc != 0);
diff --git a/src/lib/libc/string/strxfrm.3 b/src/lib/libc/string/strxfrm.3
index 84fd945472..1e5338993a 100644
--- a/src/lib/libc/string/strxfrm.3
+++ b/src/lib/libc/string/strxfrm.3
@@ -33,8 +33,7 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 34.\" SUCH DAMAGE.
35.\" 35.\"
36.\" from: @(#)strxfrm.3 5.4 (Berkeley) 6/29/91 36.\" $OpenBSD: strxfrm.3,v 1.3 2000/04/21 15:24:20 aaron Exp $
37.\" $Id: strxfrm.3,v 1.1.1.1 1995/10/18 08:42:23 deraadt Exp $
38.\" 37.\"
39.Dd June 29, 1991 38.Dd June 29, 1991
40.Dt STRXFRM 3 39.Dt STRXFRM 3
@@ -49,8 +48,7 @@
49.Sh DESCRIPTION 48.Sh DESCRIPTION
50The 49The
51.Fn strxfrm 50.Fn strxfrm
52function 51function does something horrible (see
53does something horrible (see
54.Tn ANSI 52.Tn ANSI
55standard). 53standard).
56In this implementation it just copies. 54In this implementation it just copies.
@@ -64,6 +62,5 @@ In this implementation it just copies.
64.Sh STANDARDS 62.Sh STANDARDS
65The 63The
66.Fn strxfrm 64.Fn strxfrm
67function 65function conforms to
68conforms to
69.St -ansiC . 66.St -ansiC .
diff --git a/src/lib/libc/string/strxfrm.c b/src/lib/libc/string/strxfrm.c
index d9df77b957..6b258edecc 100644
--- a/src/lib/libc/string/strxfrm.c
+++ b/src/lib/libc/string/strxfrm.c
@@ -35,8 +35,7 @@
35 */ 35 */
36 36
37#if defined(LIBC_SCCS) && !defined(lint) 37#if defined(LIBC_SCCS) && !defined(lint)
38/*static char *sccsid = "from: @(#)strxfrm.c 5.2 (Berkeley) 1/26/91";*/ 38static char *rcsid = "$OpenBSD: strxfrm.c,v 1.2 1996/08/19 08:34:29 tholo Exp $";
39static char *rcsid = "$Id: strxfrm.c,v 1.1.1.1 1995/10/18 08:42:23 deraadt Exp $";
40#endif /* LIBC_SCCS and not lint */ 39#endif /* LIBC_SCCS and not lint */
41 40
42#include <string.h> 41#include <string.h>
diff --git a/src/lib/libc/string/swab.3 b/src/lib/libc/string/swab.3
index 133c487bbd..628eb6b15f 100644
--- a/src/lib/libc/string/swab.3
+++ b/src/lib/libc/string/swab.3
@@ -29,8 +29,7 @@
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE. 30.\" SUCH DAMAGE.
31.\" 31.\"
32.\" from: @(#)swab.3 6.6 (Berkeley) 5/1/91 32.\" $OpenBSD: swab.3,v 1.4 2000/01/03 22:52:59 aaron Exp $
33.\" $Id: swab.3,v 1.1.1.1 1995/10/18 08:42:23 deraadt Exp $
34.\" 33.\"
35.Dd May 1, 1991 34.Dd May 1, 1991
36.Dt SWAB 3 35.Dt SWAB 3
@@ -39,7 +38,7 @@
39.Nm swab 38.Nm swab
40.Nd swap adjacent bytes 39.Nd swap adjacent bytes
41.Sh SYNOPSIS 40.Sh SYNOPSIS
42.Fd #include <string.h> 41.Fd #include <unistd.h>
43.Ft void 42.Ft void
44.Fn swab "const void *src" "void *dst" "size_t len" 43.Fn swab "const void *src" "void *dst" "size_t len"
45.Sh DESCRIPTION 44.Sh DESCRIPTION
@@ -55,7 +54,7 @@ swapping adjacent bytes.
55.Pp 54.Pp
56The argument 55The argument
57.Fa len 56.Fa len
58must be even number. 57must be an even number.
59.Sh SEE ALSO 58.Sh SEE ALSO
60.Xr bzero 3 , 59.Xr bzero 3 ,
61.Xr memset 3 60.Xr memset 3
diff --git a/src/lib/libc/string/swab.c b/src/lib/libc/string/swab.c
index f33fc53bd6..311cf13a53 100644
--- a/src/lib/libc/string/swab.c
+++ b/src/lib/libc/string/swab.c
@@ -35,11 +35,10 @@
35 */ 35 */
36 36
37#if defined(LIBC_SCCS) && !defined(lint) 37#if defined(LIBC_SCCS) && !defined(lint)
38/*static char *sccsid = "from: @(#)swab.c 5.10 (Berkeley) 3/6/91";*/ 38static char *rcsid = "$OpenBSD: swab.c,v 1.3 1998/02/10 02:19:48 deraadt Exp $";
39static char *rcsid = "$Id: swab.c,v 1.1.1.1 1995/10/18 08:42:23 deraadt Exp $";
40#endif /* LIBC_SCCS and not lint */ 39#endif /* LIBC_SCCS and not lint */
41 40
42#include <string.h> 41#include <unistd.h>
43 42
44void 43void
45swab(from, to, len) 44swab(from, to, len)