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.c193
-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.c157
-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.h135
-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.c1848
-rw-r--r--src/lib/libc/net/gethostbyname.3175
-rw-r--r--src/lib/libc/net/gethostnamadr.c941
-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.c361
-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.c391
-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.c508
-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.3452
-rw-r--r--src/lib/libc/net/inet6_rthdr_space.3325
-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.3148
-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.329
-rw-r--r--src/lib/libc/net/ns_addr.c20
-rw-r--r--src/lib/libc/net/ns_ntoa.c64
-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.c544
-rw-r--r--src/lib/libc/net/rcmdsh.3 (renamed from src/lib/libc/stdlib/calloc.3)92
-rw-r--r--src/lib/libc/net/rcmdsh.c153
-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.c1503
-rw-r--r--src/lib/libc/net/res_init.c435
-rw-r--r--src/lib/libc/net/res_mkquery.c230
-rw-r--r--src/lib/libc/net/res_query.c199
-rw-r--r--src/lib/libc/net/res_random.c229
-rw-r--r--src/lib/libc/net/res_send.c847
-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.c14
-rw-r--r--src/lib/libc/net/vars6.c42
-rw-r--r--src/lib/libc/stdlib/Makefile.inc41
-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.c88
-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.310
-rw-r--r--src/lib/libc/stdlib/atol.c3
-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/erand48.c4
-rw-r--r--src/lib/libc/stdlib/exit.324
-rw-r--r--src/lib/libc/stdlib/exit.c32
-rw-r--r--src/lib/libc/stdlib/free.382
-rw-r--r--src/lib/libc/stdlib/getenv.366
-rw-r--r--src/lib/libc/stdlib/getenv.c65
-rw-r--r--src/lib/libc/stdlib/getopt.3128
-rw-r--r--src/lib/libc/stdlib/getopt.c3
-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/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/malloc.3376
-rw-r--r--src/lib/libc/stdlib/malloc.c1592
-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.355
-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.335
-rw-r--r--src/lib/libc/stdlib/rand48.h4
-rw-r--r--src/lib/libc/stdlib/random.3105
-rw-r--r--src/lib/libc/stdlib/random.c95
-rw-r--r--src/lib/libc/stdlib/realloc.3100
-rw-r--r--src/lib/libc/stdlib/realpath.320
-rw-r--r--src/lib/libc/stdlib/realpath.c23
-rw-r--r--src/lib/libc/stdlib/seed48.c4
-rw-r--r--src/lib/libc/stdlib/setenv.c13
-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.c251
-rw-r--r--src/lib/libc/stdlib/strtol.3132
-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.3129
-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.inc63
-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.310
-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.383
-rw-r--r--src/lib/libc/string/index.c8
-rw-r--r--src/lib/libc/string/memccpy.325
-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.312
-rw-r--r--src/lib/libc/string/memmove.39
-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.322
-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.315
-rw-r--r--src/lib/libc/string/strcmp.c7
-rw-r--r--src/lib/libc/string/strcoll.39
-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.354
-rw-r--r--src/lib/libc/string/strdup.c26
-rw-r--r--src/lib/libc/string/strerror.311
-rw-r--r--src/lib/libc/string/strerror.c5
-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.c73
-rw-r--r--src/lib/libc/string/strlcpy.3190
-rw-r--r--src/lib/libc/string/strlcpy.c69
-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.370
-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
261 files changed, 23627 insertions, 4874 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..4e916ab99a
--- /dev/null
+++ b/src/lib/libc/crypt/arc4random.c
@@ -0,0 +1,193 @@
1/* $OpenBSD: arc4random.c,v 1.6 2001/06/05 05:05:38 pvalchev 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
47int rs_initialized;
48static struct arc4_stream rs;
49
50static inline void
51arc4_init(as)
52 struct arc4_stream *as;
53{
54 int n;
55
56 for (n = 0; n < 256; n++)
57 as->s[n] = n;
58 as->i = 0;
59 as->j = 0;
60}
61
62static inline void
63arc4_addrandom(as, dat, datlen)
64 struct arc4_stream *as;
65 u_char *dat;
66 int datlen;
67{
68 int n;
69 u_int8_t si;
70
71 as->i--;
72 for (n = 0; n < 256; n++) {
73 as->i = (as->i + 1);
74 si = as->s[as->i];
75 as->j = (as->j + si + dat[n % datlen]);
76 as->s[as->i] = as->s[as->j];
77 as->s[as->j] = si;
78 }
79 as->j = as->i;
80}
81
82static void
83arc4_stir(as)
84 struct arc4_stream *as;
85{
86 int fd;
87 struct {
88 struct timeval tv;
89 u_int rnd[(128 - sizeof(struct timeval)) / sizeof(u_int)];
90 } rdat;
91
92 gettimeofday(&rdat.tv, NULL);
93 fd = open("/dev/arandom", O_RDONLY);
94 if (fd != -1) {
95 read(fd, rdat.rnd, sizeof(rdat.rnd));
96 close(fd);
97 } else {
98 int i, mib[2];
99 size_t len;
100
101 /* Device could not be opened, we might be chrooted, take
102 * randomness from sysctl. */
103
104 mib[0] = CTL_KERN;
105 mib[1] = KERN_ARND;
106
107 for (i = 0; i < sizeof(rdat.rnd) / sizeof(u_int); i ++) {
108 len = sizeof(u_int);
109 if (sysctl(mib, 2, &rdat.rnd[i], &len, NULL, 0) == -1)
110 break;
111 }
112 }
113 /* fd < 0 or failed sysctl ? Ah, what the heck. We'll just take
114 * whatever was on the stack... */
115
116 arc4_addrandom(as, (void *) &rdat, sizeof(rdat));
117}
118
119static inline u_int8_t
120arc4_getbyte(as)
121 struct arc4_stream *as;
122{
123 u_int8_t si, sj;
124
125 as->i = (as->i + 1);
126 si = as->s[as->i];
127 as->j = (as->j + si);
128 sj = as->s[as->j];
129 as->s[as->i] = sj;
130 as->s[as->j] = si;
131 return (as->s[(si + sj) & 0xff]);
132}
133
134static inline u_int32_t
135arc4_getword(as)
136 struct arc4_stream *as;
137{
138 u_int32_t val;
139 val = arc4_getbyte(as) << 24;
140 val |= arc4_getbyte(as) << 16;
141 val |= arc4_getbyte(as) << 8;
142 val |= arc4_getbyte(as);
143 return val;
144}
145
146void
147arc4random_stir()
148{
149 if (!rs_initialized) {
150 arc4_init(&rs);
151 rs_initialized = 1;
152 }
153 arc4_stir(&rs);
154}
155
156void
157arc4random_addrandom(dat, datlen)
158 u_char *dat;
159 int datlen;
160{
161 if (!rs_initialized)
162 arc4random_stir();
163 arc4_addrandom(&rs, dat, datlen);
164}
165
166u_int32_t
167arc4random()
168{
169 if (!rs_initialized)
170 arc4random_stir();
171 return arc4_getword(&rs);
172}
173
174#if 0
175/*-------- Test code for i386 --------*/
176#include <stdio.h>
177#include <machine/pctr.h>
178int
179main(int argc, char **argv)
180{
181 const int iter = 1000000;
182 int i;
183 pctrval v;
184
185 v = rdtsc();
186 for (i = 0; i < iter; i++)
187 arc4random();
188 v = rdtsc() - v;
189 v /= iter;
190
191 printf("%qd cycles\n", v);
192}
193#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..8be04a6463
--- /dev/null
+++ b/src/lib/libc/crypt/blowfish.c
@@ -0,0 +1,694 @@
1/* $OpenBSD: blowfish.c,v 1.16 2002/02/19 19:39:36 millert 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 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..56ab66fbb5
--- /dev/null
+++ b/src/lib/libc/crypt/md5crypt.c
@@ -0,0 +1,157 @@
1/* $OpenBSD: md5crypt.c,v 1.10 2002/02/16 21:27:22 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.10 2002/02/16 21:27:22 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 strcpy(passwd,(const char *)magic);
112 strncat(passwd,(const char *)sp,sl);
113 strcat(passwd,"$");
114
115 MD5Final(final,&ctx);
116
117 /*
118 * and now, just to make sure things don't run too fast
119 * On a 60 Mhz Pentium this takes 34 msec, so you would
120 * need 30 seconds to build a 1000 entry dictionary...
121 */
122 for(i=0;i<1000;i++) {
123 MD5Init(&ctx1);
124 if(i & 1)
125 MD5Update(&ctx1,(const unsigned char *)pw,strlen(pw));
126 else
127 MD5Update(&ctx1,final,16);
128
129 if(i % 3)
130 MD5Update(&ctx1,sp,sl);
131
132 if(i % 7)
133 MD5Update(&ctx1,(const unsigned char *)pw,strlen(pw));
134
135 if(i & 1)
136 MD5Update(&ctx1,final,16);
137 else
138 MD5Update(&ctx1,(const unsigned char *)pw,strlen(pw));
139 MD5Final(final,&ctx1);
140 }
141
142 p = passwd + strlen(passwd);
143
144 l = (final[ 0]<<16) | (final[ 6]<<8) | final[12]; to64(p,l,4); p += 4;
145 l = (final[ 1]<<16) | (final[ 7]<<8) | final[13]; to64(p,l,4); p += 4;
146 l = (final[ 2]<<16) | (final[ 8]<<8) | final[14]; to64(p,l,4); p += 4;
147 l = (final[ 3]<<16) | (final[ 9]<<8) | final[15]; to64(p,l,4); p += 4;
148 l = (final[ 4]<<16) | (final[10]<<8) | final[ 5]; to64(p,l,4); p += 4;
149 l = final[11] ; to64(p,l,2); p += 2;
150 *p = '\0';
151
152 /* Don't leave anything around in vm they could use. */
153 memset(final,0,sizeof final);
154
155 return passwd;
156}
157
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..8cf06a86c4
--- /dev/null
+++ b/src/lib/libc/include/thread_private.h
@@ -0,0 +1,135 @@
1/* $OpenBSD: thread_private.h,v 1.11 2002/02/16 21:27:23 millert 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 * If the symbol _NO_WEAK_ALIASES is defined, then symbols will be
23 */
24
25#ifdef _NO_WEAK_ALIASES
26#ifdef _THREAD_SAFE
27#define WEAK_NAME(name) __CONCAT(_weak,name)
28#else
29#define WEAK_NAME(name) name
30#endif
31#define WEAK_ALIAS(name) /* unavailable */
32#define WEAK_PROTOTYPE(name) /* unnecessary */
33#else /* !_NO_WEAK_ALIASES */
34#define WEAK_NAME(name) __CONCAT(_weak_,name)
35#define WEAK_ALIAS(name) __weak_alias(name, WEAK_NAME(name))
36#ifdef __GNUC__
37#define WEAK_PROTOTYPE(name) __typeof__(name) WEAK_NAME(name)
38#else
39#define WEAK_PROTOTYPE(name) /* typeof() only in gcc */
40#endif
41#endif /* !_NO_WEAK_ALIASES */
42
43/*
44 * These macros help in making persistent storage thread-specific.
45 * Libc makes extensive use of private static data structures
46 * that hold state across function invocation, and these macros
47 * are no-ops when running single-threaded.
48 *
49 * Linking against the user-thread library causes these macros to
50 * allocate storage on a per-thread basis.
51 */
52
53#define __THREAD_MUTEX_NAME(name) __CONCAT(_libc_storage_mutex_,name)
54#define __THREAD_KEY_NAME(name) __CONCAT(_libc_storage_key_,name)
55
56struct _thread_private_key_struct {
57 pthread_once_t once;
58 void (*cleanfn)(void *);
59 pthread_key_t key;
60};
61
62void _libc_private_storage_lock(pthread_mutex_t *);
63void _libc_private_storage_unlock(pthread_mutex_t *);
64void * _libc_private_storage(volatile struct _thread_private_key_struct *,
65 void *, size_t, void *);
66
67/* Declare a module mutex. */
68#define _THREAD_PRIVATE_MUTEX(name) \
69 static pthread_mutex_t __THREAD_MUTEX_NAME(name) = \
70 PTHREAD_MUTEX_INITIALIZER
71
72/* Lock a module mutex against use by any other threads. */
73#define _THREAD_PRIVATE_MUTEX_LOCK(name) \
74 _libc_private_storage_lock(&__THREAD_MUTEX_NAME(name))
75
76/* Unlock a module mutex. */
77#define _THREAD_PRIVATE_MUTEX_UNLOCK(name) \
78 _libc_private_storage_unlock(&__THREAD_MUTEX_NAME(name))
79
80/* Declare a thread-private storage key. */
81#define _THREAD_PRIVATE_KEY(name) \
82 static volatile struct _thread_private_key_struct \
83 __THREAD_KEY_NAME(name) = { \
84 PTHREAD_ONCE_INIT, \
85 0 \
86 }
87
88/*
89 * In threaded mode, return a pointer to thread-private memory of
90 * the same size as, and (initially) with the same contents as 'storage'. If
91 * an error occurs, the 'error' parameter is returned.
92 * In single-threaded mode, no storage is allocated. Instead, a pointer
93 * to storage is always returned.
94 * The 'cleanfn' function of the key structure is called to free the storage.
95 * If 'cleanfn' is NULL, then free() is used. This hook can be useful for
96 * getting rid of memory leaks.
97 */
98#define _THREAD_PRIVATE(keyname, storage, error) \
99 _libc_private_storage(&__THREAD_KEY_NAME(keyname), \
100 &(storage), sizeof (storage), error)
101
102/*
103 * Macros for locking and unlocking FILEs. These test if the
104 * process is threaded to avoid locking when not required.
105 */
106#ifdef _FLOCK_DEBUG
107#define FLOCKFILE(fp) _flockfile_debug(fp, __FILE__, __LINE__)
108#else
109#define FLOCKFILE(fp) flockfile(fp)
110#endif
111#define FUNLOCKFILE(fp) funlockfile(fp)
112
113/*
114 * File descriptor locking definitions.
115 */
116#define FD_READ 0x1
117#define FD_WRITE 0x2
118#define FD_RDWR (FD_READ | FD_WRITE)
119
120#ifdef _LOCK_DEBUG
121#define _FD_LOCK(_fd,_type,_ts) _thread_fd_lock_debug(_fd, _type, \
122 _ts, __FILE__, __LINE__)
123#define _FD_UNLOCK(_fd,_type) _thread_fd_unlock_debug(_fd, _type, \
124 __FILE__, __LINE__)
125#else
126#define _FD_LOCK(_fd,_type,_ts) _thread_fd_lock(_fd, _type, _ts)
127#define _FD_UNLOCK(_fd,_type) _thread_fd_unlock(_fd, _type)
128#endif
129
130int _thread_fd_lock(int, int, struct timespec *);
131int _thread_fd_lock_debug(int, int, struct timespec *, char *, int);
132void _thread_fd_unlock(int, int);
133void _thread_fd_unlock_debug(int, int, char *, int);
134
135#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..5c4be16732
--- /dev/null
+++ b/src/lib/libc/net/getaddrinfo.3
@@ -0,0 +1,581 @@
1.\" $OpenBSD: getaddrinfo.3,v 1.20 2002/04/30 16:31:42 mpech 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
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 name of hardware interface associated
362with the link.
363.Po
364such as
365.Li ne0
366.Pc .
367Example would be like
368.Dq Li fe80::1%ne0 ,
369which means
370.Do
371.Li fe80::1
372on the link associated with
373.Li ne0
374interface
375.Dc .
376.Pp
377The implementation is still very experimental and non-standard.
378The current implementation assumes one-by-one relationship between
379interface 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 from address family.
388If the destination resolves to 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 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 getnameinfo 3 ,
536.Xr gethostbyname 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..915286a404
--- /dev/null
+++ b/src/lib/libc/net/getaddrinfo.c
@@ -0,0 +1,1848 @@
1/* $OpenBSD: getaddrinfo.c,v 1.43 2002/08/27 08:53:13 itojun 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 (pai->ai_flags & AI_NUMERICHOST)
439 ERR(EAI_NODATA);
440 if (hostname == NULL)
441 ERR(EAI_NODATA);
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
502_THREAD_PRIVATE_MUTEX(getaddrinfo_explore_fqdn);
503
504static int
505explore_fqdn(pai, hostname, servname, res)
506 const struct addrinfo *pai;
507 const char *hostname;
508 const char *servname;
509 struct addrinfo **res;
510{
511 struct addrinfo *result;
512 struct addrinfo *cur;
513 int error = 0;
514 char lookups[MAXDNSLUS];
515 int i;
516
517 _THREAD_PRIVATE_MUTEX_LOCK(getaddrinfo_explore_fqdn);
518
519 result = NULL;
520
521#if 0
522 /*
523 * If AI_ADDRCONFIG is specified, check if we are expected to
524 * return the address family or not.
525 * XXX does not handle PF_UNSPEC case, should filter final result
526 */
527 if ((pai->ai_flags & AI_ADDRCONFIG) != 0 && !addrconfig(pai)) {
528 _THREAD_PRIVATE_MUTEX_UNLOCK(getaddrinfo_explore_fqdn);
529 return 0;
530 }
531#endif
532
533 /*
534 * if the servname does not match socktype/protocol, ignore it.
535 */
536 if (get_portmatch(pai, servname) != 0) {
537 _THREAD_PRIVATE_MUTEX_UNLOCK(getaddrinfo_explore_fqdn);
538 return 0;
539 }
540
541 if ((_res.options & RES_INIT) == 0 && res_init() == -1)
542 strlcpy(lookups, "f", sizeof lookups);
543 else {
544 bcopy(_res.lookups, lookups, sizeof lookups);
545 if (lookups[0] == '\0')
546 strlcpy(lookups, "bf", sizeof lookups);
547 }
548
549 for (i = 0; i < MAXDNSLUS && result == NULL && lookups[i]; i++) {
550 switch (lookups[i]) {
551#ifdef YP
552 case 'y':
553 result = _yp_getaddrinfo(hostname, pai);
554 break;
555#endif
556 case 'b':
557 result = _dns_getaddrinfo(hostname, pai);
558 break;
559 case 'f':
560 result = _files_getaddrinfo(hostname, pai);
561 break;
562 }
563 }
564 if (result) {
565 for (cur = result; cur; cur = cur->ai_next) {
566 GET_PORT(cur, servname);
567 /* canonname should be filled already */
568 }
569 *res = result;
570 _THREAD_PRIVATE_MUTEX_UNLOCK(getaddrinfo_explore_fqdn);
571 return 0;
572 } else {
573 /* translate error code */
574 switch (h_errno) {
575 case NETDB_SUCCESS:
576 error = EAI_FAIL; /*XXX strange */
577 break;
578 case HOST_NOT_FOUND:
579 error = EAI_NODATA;
580 break;
581 case TRY_AGAIN:
582 error = EAI_AGAIN;
583 break;
584 case NO_RECOVERY:
585 error = EAI_FAIL;
586 break;
587 case NO_DATA:
588#if NO_ADDRESS != NO_DATA
589 case NO_ADDRESS:
590#endif
591 error = EAI_NODATA;
592 break;
593 default: /* unknown ones */
594 error = EAI_FAIL;
595 break;
596 }
597 }
598
599free:
600 if (result)
601 freeaddrinfo(result);
602 _THREAD_PRIVATE_MUTEX_UNLOCK(getaddrinfo_explore_fqdn);
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
871 if (servname == NULL)
872 return 0;
873 switch (ai->ai_family) {
874 case AF_INET:
875#ifdef AF_INET6
876 case AF_INET6:
877#endif
878 break;
879 default:
880 return 0;
881 }
882
883 switch (ai->ai_socktype) {
884 case SOCK_RAW:
885 return EAI_SERVICE;
886 case SOCK_DGRAM:
887 case SOCK_STREAM:
888 allownumeric = 1;
889 break;
890 case ANY:
891 allownumeric = 0;
892 break;
893 default:
894 return EAI_SOCKTYPE;
895 }
896
897 if (str_isnumber(servname)) {
898 if (!allownumeric)
899 return EAI_SERVICE;
900 port = atoi(servname);
901 if (port < 0 || port > 65535)
902 return EAI_SERVICE;
903 port = htons(port);
904 } else {
905 switch (ai->ai_socktype) {
906 case SOCK_DGRAM:
907 proto = "udp";
908 break;
909 case SOCK_STREAM:
910 proto = "tcp";
911 break;
912 default:
913 proto = NULL;
914 break;
915 }
916
917 if ((sp = getservbyname(servname, proto)) == NULL)
918 return EAI_SERVICE;
919 port = sp->s_port;
920 }
921
922 if (!matchonly) {
923 switch (ai->ai_family) {
924 case AF_INET:
925 ((struct sockaddr_in *)(void *)
926 ai->ai_addr)->sin_port = port;
927 break;
928#ifdef INET6
929 case AF_INET6:
930 ((struct sockaddr_in6 *)(void *)
931 ai->ai_addr)->sin6_port = port;
932 break;
933#endif
934 }
935 }
936
937 return 0;
938}
939
940static const struct afd *
941find_afd(af)
942 int af;
943{
944 const struct afd *afd;
945
946 if (af == PF_UNSPEC)
947 return NULL;
948 for (afd = afdl; afd->a_af; afd++) {
949 if (afd->a_af == af)
950 return afd;
951 }
952 return NULL;
953}
954
955#if 0
956/*
957 * post-2553: AI_ADDRCONFIG check. if we use getipnodeby* as backend, backend
958 * will take care of it.
959 * the semantics of AI_ADDRCONFIG is not defined well. we are not sure
960 * if the code is right or not.
961 */
962static int
963addrconfig(pai)
964 const struct addrinfo *pai;
965{
966 int s;
967
968 /* XXX errno */
969 s = socket(pai->ai_family, SOCK_DGRAM, 0);
970 if (s < 0)
971 return 0;
972 close(s);
973 return 1;
974}
975#endif
976
977#ifdef INET6
978/* convert a string to a scope identifier. XXX: IPv6 specific */
979static int
980ip6_str2scopeid(scope, sin6, scopeid)
981 char *scope;
982 struct sockaddr_in6 *sin6;
983 u_int32_t *scopeid;
984{
985 u_long lscopeid;
986 struct in6_addr *a6 = &sin6->sin6_addr;
987 char *ep;
988
989 /* empty scopeid portion is invalid */
990 if (*scope == '\0')
991 return -1;
992
993 if (IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6)) {
994 /*
995 * We currently assume a one-to-one mapping between links
996 * and interfaces, so we simply use interface indices for
997 * like-local scopes.
998 */
999 *scopeid = if_nametoindex(scope);
1000 if (*scopeid == 0)
1001 goto trynumeric;
1002 return 0;
1003 }
1004
1005 /* still unclear about literal, allow numeric only - placeholder */
1006 if (IN6_IS_ADDR_SITELOCAL(a6) || IN6_IS_ADDR_MC_SITELOCAL(a6))
1007 goto trynumeric;
1008 if (IN6_IS_ADDR_MC_ORGLOCAL(a6))
1009 goto trynumeric;
1010 else
1011 goto trynumeric; /* global */
1012
1013 /* try to convert to a numeric id as a last resort */
1014 trynumeric:
1015 errno = 0;
1016 lscopeid = strtoul(scope, &ep, 10);
1017 *scopeid = (u_int32_t)(lscopeid & 0xffffffffUL);
1018 if (errno == 0 && ep && *ep == '\0' && *scopeid == lscopeid)
1019 return 0;
1020 else
1021 return -1;
1022}
1023#endif
1024
1025/* code duplicate with gethnamaddr.c */
1026
1027static const char AskedForGot[] =
1028 "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
1029static FILE *hostf = NULL;
1030
1031static struct addrinfo *
1032getanswer(answer, anslen, qname, qtype, pai)
1033 const querybuf *answer;
1034 int anslen;
1035 const char *qname;
1036 int qtype;
1037 const struct addrinfo *pai;
1038{
1039 struct addrinfo sentinel, *cur;
1040 struct addrinfo ai;
1041 const struct afd *afd;
1042 char *canonname;
1043 const HEADER *hp;
1044 const u_char *cp;
1045 int n;
1046 const u_char *eom;
1047 char *bp, *ep;
1048 int type, class, ancount, qdcount;
1049 int haveanswer, had_error;
1050 char tbuf[MAXDNAME];
1051 int (*name_ok)(const char *);
1052 char hostbuf[8*1024];
1053
1054 memset(&sentinel, 0, sizeof(sentinel));
1055 cur = &sentinel;
1056
1057 canonname = NULL;
1058 eom = answer->buf + anslen;
1059 switch (qtype) {
1060 case T_A:
1061 case T_AAAA:
1062 case T_ANY: /*use T_ANY only for T_A/T_AAAA lookup*/
1063 name_ok = res_hnok;
1064 break;
1065 default:
1066 return (NULL); /* XXX should be abort() -- but that is illegal */
1067 }
1068 /*
1069 * find first satisfactory answer
1070 */
1071 hp = &answer->hdr;
1072 ancount = ntohs(hp->ancount);
1073 qdcount = ntohs(hp->qdcount);
1074 bp = hostbuf;
1075 ep = hostbuf + sizeof hostbuf;
1076 cp = answer->buf + HFIXEDSZ;
1077 if (qdcount != 1) {
1078 h_errno = NO_RECOVERY;
1079 return (NULL);
1080 }
1081 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
1082 if ((n < 0) || !(*name_ok)(bp)) {
1083 h_errno = NO_RECOVERY;
1084 return (NULL);
1085 }
1086 cp += n + QFIXEDSZ;
1087 if (qtype == T_A || qtype == T_AAAA || qtype == T_ANY) {
1088 /* res_send() has already verified that the query name is the
1089 * same as the one we sent; this just gets the expanded name
1090 * (i.e., with the succeeding search-domain tacked on).
1091 */
1092 n = strlen(bp) + 1; /* for the \0 */
1093 if (n >= MAXHOSTNAMELEN) {
1094 h_errno = NO_RECOVERY;
1095 return (NULL);
1096 }
1097 canonname = bp;
1098 bp += n;
1099 /* The qname can be abbreviated, but h_name is now absolute. */
1100 qname = canonname;
1101 }
1102 haveanswer = 0;
1103 had_error = 0;
1104 while (ancount-- > 0 && cp < eom && !had_error) {
1105 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
1106 if ((n < 0) || !(*name_ok)(bp)) {
1107 had_error++;
1108 continue;
1109 }
1110 cp += n; /* name */
1111 type = _getshort(cp);
1112 cp += INT16SZ; /* type */
1113 class = _getshort(cp);
1114 cp += INT16SZ + INT32SZ; /* class, TTL */
1115 n = _getshort(cp);
1116 cp += INT16SZ; /* len */
1117 if (class != C_IN) {
1118 /* XXX - debug? syslog? */
1119 cp += n;
1120 continue; /* XXX - had_error++ ? */
1121 }
1122 if ((qtype == T_A || qtype == T_AAAA || qtype == T_ANY) &&
1123 type == T_CNAME) {
1124 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
1125 if ((n < 0) || !(*name_ok)(tbuf)) {
1126 had_error++;
1127 continue;
1128 }
1129 cp += n;
1130 /* Get canonical name. */
1131 n = strlen(tbuf) + 1; /* for the \0 */
1132 if (n > ep - bp || n >= MAXHOSTNAMELEN) {
1133 had_error++;
1134 continue;
1135 }
1136 strcpy(bp, tbuf);
1137 canonname = bp;
1138 bp += n;
1139 continue;
1140 }
1141 if (qtype == T_ANY) {
1142 if (!(type == T_A || type == T_AAAA)) {
1143 cp += n;
1144 continue;
1145 }
1146 } else if (type != qtype) {
1147 if (type != T_KEY && type != T_SIG)
1148 syslog(LOG_NOTICE|LOG_AUTH,
1149 "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
1150 qname, p_class(C_IN), p_type(qtype),
1151 p_type(type));
1152 cp += n;
1153 continue; /* XXX - had_error++ ? */
1154 }
1155 switch (type) {
1156 case T_A:
1157 case T_AAAA:
1158 if (strcasecmp(canonname, bp) != 0) {
1159 syslog(LOG_NOTICE|LOG_AUTH,
1160 AskedForGot, canonname, bp);
1161 cp += n;
1162 continue; /* XXX - had_error++ ? */
1163 }
1164 if (type == T_A && n != INADDRSZ) {
1165 cp += n;
1166 continue;
1167 }
1168 if (type == T_AAAA && n != IN6ADDRSZ) {
1169 cp += n;
1170 continue;
1171 }
1172 if (type == T_AAAA) {
1173 struct in6_addr in6;
1174 memcpy(&in6, cp, IN6ADDRSZ);
1175 if (IN6_IS_ADDR_V4MAPPED(&in6)) {
1176 cp += n;
1177 continue;
1178 }
1179 }
1180 if (!haveanswer) {
1181 int nn;
1182
1183 canonname = bp;
1184 nn = strlen(bp) + 1; /* for the \0 */
1185 bp += nn;
1186 }
1187
1188 /* don't overwrite pai */
1189 ai = *pai;
1190 ai.ai_family = (type == T_A) ? AF_INET : AF_INET6;
1191 afd = find_afd(ai.ai_family);
1192 if (afd == NULL) {
1193 cp += n;
1194 continue;
1195 }
1196 cur->ai_next = get_ai(&ai, afd, (const char *)cp);
1197 if (cur->ai_next == NULL)
1198 had_error++;
1199 while (cur && cur->ai_next)
1200 cur = cur->ai_next;
1201 cp += n;
1202 break;
1203 default:
1204 abort(); /* XXX abort illegal in library */
1205 }
1206 if (!had_error)
1207 haveanswer++;
1208 }
1209 if (haveanswer) {
1210 if (!canonname)
1211 (void)get_canonname(pai, sentinel.ai_next, qname);
1212 else
1213 (void)get_canonname(pai, sentinel.ai_next, canonname);
1214 h_errno = NETDB_SUCCESS;
1215 return sentinel.ai_next;
1216 }
1217
1218 h_errno = NO_RECOVERY;
1219 return NULL;
1220}
1221
1222/*ARGSUSED*/
1223static struct addrinfo *
1224_dns_getaddrinfo(name, pai)
1225 const char *name;
1226 const struct addrinfo *pai;
1227{
1228 struct addrinfo *ai;
1229 querybuf *buf, *buf2;
1230 struct addrinfo sentinel, *cur;
1231 struct res_target q, q2;
1232
1233 memset(&q, 0, sizeof(q2));
1234 memset(&q2, 0, sizeof(q2));
1235 memset(&sentinel, 0, sizeof(sentinel));
1236 cur = &sentinel;
1237
1238 buf = malloc(sizeof(*buf));
1239 if (buf == NULL) {
1240 h_errno = NETDB_INTERNAL;
1241 return NULL;
1242 }
1243 buf2 = malloc(sizeof(*buf2));
1244 if (buf2 == NULL) {
1245 free(buf);
1246 h_errno = NETDB_INTERNAL;
1247 return NULL;
1248 }
1249
1250 switch (pai->ai_family) {
1251 case AF_UNSPEC:
1252 /* prefer IPv6 */
1253 q.qclass = C_IN;
1254 q.qtype = T_AAAA;
1255 q.answer = buf->buf;
1256 q.anslen = sizeof(buf->buf);
1257 q.next = &q2;
1258 q2.qclass = C_IN;
1259 q2.qtype = T_A;
1260 q2.answer = buf2->buf;
1261 q2.anslen = sizeof(buf2->buf);
1262 break;
1263 case AF_INET:
1264 q.qclass = C_IN;
1265 q.qtype = T_A;
1266 q.answer = buf->buf;
1267 q.anslen = sizeof(buf->buf);
1268 break;
1269 case AF_INET6:
1270 q.qclass = C_IN;
1271 q.qtype = T_AAAA;
1272 q.answer = buf->buf;
1273 q.anslen = sizeof(buf->buf);
1274 break;
1275 default:
1276 free(buf);
1277 free(buf2);
1278 return NULL;
1279 }
1280 if (res_searchN(name, &q) < 0) {
1281 free(buf);
1282 free(buf2);
1283 return NULL;
1284 }
1285 ai = getanswer(buf, q.n, q.name, q.qtype, pai);
1286 if (ai) {
1287 cur->ai_next = ai;
1288 while (cur && cur->ai_next)
1289 cur = cur->ai_next;
1290 }
1291 if (q.next) {
1292 ai = getanswer(buf2, q2.n, q2.name, q2.qtype, pai);
1293 if (ai)
1294 cur->ai_next = ai;
1295 }
1296 free(buf);
1297 free(buf2);
1298 return sentinel.ai_next;
1299}
1300
1301static FILE *hostf;
1302
1303static void
1304_sethtent()
1305{
1306 if (!hostf)
1307 hostf = fopen(_PATH_HOSTS, "r" );
1308 else
1309 rewind(hostf);
1310}
1311
1312static void
1313_endhtent()
1314{
1315 if (hostf) {
1316 (void) fclose(hostf);
1317 hostf = NULL;
1318 }
1319}
1320
1321static struct addrinfo *
1322_gethtent(name, pai)
1323 const char *name;
1324 const struct addrinfo *pai;
1325{
1326 char *p;
1327 char *cp, *tname, *cname;
1328 struct addrinfo hints, *res0, *res;
1329 int error;
1330 const char *addr;
1331 char hostbuf[8*1024];
1332
1333 if (!hostf && !(hostf = fopen(_PATH_HOSTS, "r" )))
1334 return (NULL);
1335 again:
1336 if (!(p = fgets(hostbuf, sizeof hostbuf, hostf)))
1337 return (NULL);
1338 if (*p == '#')
1339 goto again;
1340 if (!(cp = strpbrk(p, "#\n")))
1341 goto again;
1342 *cp = '\0';
1343 if (!(cp = strpbrk(p, " \t")))
1344 goto again;
1345 *cp++ = '\0';
1346 addr = p;
1347 /* if this is not something we're looking for, skip it. */
1348 cname = NULL;
1349 while (cp && *cp) {
1350 if (*cp == ' ' || *cp == '\t') {
1351 cp++;
1352 continue;
1353 }
1354 if (!cname)
1355 cname = cp;
1356 tname = cp;
1357 if ((cp = strpbrk(cp, " \t")) != NULL)
1358 *cp++ = '\0';
1359 if (strcasecmp(name, tname) == 0)
1360 goto found;
1361 }
1362 goto again;
1363
1364found:
1365 hints = *pai;
1366 hints.ai_flags = AI_NUMERICHOST;
1367 error = getaddrinfo(addr, NULL, &hints, &res0);
1368 if (error)
1369 goto again;
1370 for (res = res0; res; res = res->ai_next) {
1371 /* cover it up */
1372 res->ai_flags = pai->ai_flags;
1373
1374 if (pai->ai_flags & AI_CANONNAME) {
1375 if (get_canonname(pai, res, cname) != 0) {
1376 freeaddrinfo(res0);
1377 goto again;
1378 }
1379 }
1380 }
1381 return res0;
1382}
1383
1384/*ARGSUSED*/
1385static struct addrinfo *
1386_files_getaddrinfo(name, pai)
1387 const char *name;
1388 const struct addrinfo *pai;
1389{
1390 struct addrinfo sentinel, *cur;
1391 struct addrinfo *p;
1392
1393 memset(&sentinel, 0, sizeof(sentinel));
1394 cur = &sentinel;
1395
1396 _sethtent();
1397 while ((p = _gethtent(name, pai)) != NULL) {
1398 cur->ai_next = p;
1399 while (cur && cur->ai_next)
1400 cur = cur->ai_next;
1401 }
1402 _endhtent();
1403
1404 return sentinel.ai_next;
1405}
1406
1407#ifdef YP
1408static char *__ypdomain;
1409
1410/*ARGSUSED*/
1411static struct addrinfo *
1412_yphostent(line, pai)
1413 char *line;
1414 const struct addrinfo *pai;
1415{
1416 struct addrinfo sentinel, *cur;
1417 struct addrinfo hints, *res, *res0;
1418 int error;
1419 char *p = line;
1420 const char *addr, *canonname;
1421 char *nextline;
1422 char *cp;
1423
1424 addr = canonname = NULL;
1425
1426 memset(&sentinel, 0, sizeof(sentinel));
1427 cur = &sentinel;
1428
1429nextline:
1430 /* terminate line */
1431 cp = strchr(p, '\n');
1432 if (cp) {
1433 *cp++ = '\0';
1434 nextline = cp;
1435 } else
1436 nextline = NULL;
1437
1438 cp = strpbrk(p, " \t");
1439 if (cp == NULL) {
1440 if (canonname == NULL)
1441 return (NULL);
1442 else
1443 goto done;
1444 }
1445 *cp++ = '\0';
1446
1447 addr = p;
1448
1449 while (cp && *cp) {
1450 if (*cp == ' ' || *cp == '\t') {
1451 cp++;
1452 continue;
1453 }
1454 if (!canonname)
1455 canonname = cp;
1456 if ((cp = strpbrk(cp, " \t")) != NULL)
1457 *cp++ = '\0';
1458 }
1459
1460 hints = *pai;
1461 hints.ai_flags = AI_NUMERICHOST;
1462 error = getaddrinfo(addr, NULL, &hints, &res0);
1463 if (error == 0) {
1464 for (res = res0; res; res = res->ai_next) {
1465 /* cover it up */
1466 res->ai_flags = pai->ai_flags;
1467
1468 if (pai->ai_flags & AI_CANONNAME)
1469 (void)get_canonname(pai, res, canonname);
1470 }
1471 } else
1472 res0 = NULL;
1473 if (res0) {
1474 cur->ai_next = res0;
1475 while (cur && cur->ai_next)
1476 cur = cur->ai_next;
1477 }
1478
1479 if (nextline) {
1480 p = nextline;
1481 goto nextline;
1482 }
1483
1484done:
1485 return sentinel.ai_next;
1486}
1487
1488/*ARGSUSED*/
1489static struct addrinfo *
1490_yp_getaddrinfo(name, pai)
1491 const char *name;
1492 const struct addrinfo *pai;
1493{
1494 struct addrinfo sentinel, *cur;
1495 struct addrinfo *ai = NULL;
1496 static char *__ypcurrent;
1497 int __ypcurrentlen, r;
1498
1499 memset(&sentinel, 0, sizeof(sentinel));
1500 cur = &sentinel;
1501
1502 if (!__ypdomain) {
1503 if (_yp_check(&__ypdomain) == 0)
1504 return NULL;
1505 }
1506 if (__ypcurrent)
1507 free(__ypcurrent);
1508 __ypcurrent = NULL;
1509
1510 /* hosts.byname is only for IPv4 (Solaris8) */
1511 if (pai->ai_family == PF_UNSPEC || pai->ai_family == PF_INET) {
1512 r = yp_match(__ypdomain, "hosts.byname", name,
1513 (int)strlen(name), &__ypcurrent, &__ypcurrentlen);
1514 if (r == 0) {
1515 struct addrinfo ai4;
1516
1517 ai4 = *pai;
1518 ai4.ai_family = AF_INET;
1519 ai = _yphostent(__ypcurrent, &ai4);
1520 if (ai) {
1521 cur->ai_next = ai;
1522 while (cur && cur->ai_next)
1523 cur = cur->ai_next;
1524 }
1525 }
1526 }
1527
1528 /* ipnodes.byname can hold both IPv4/v6 */
1529 r = yp_match(__ypdomain, "ipnodes.byname", name,
1530 (int)strlen(name), &__ypcurrent, &__ypcurrentlen);
1531 if (r == 0) {
1532 ai = _yphostent(__ypcurrent, pai);
1533 if (ai) {
1534 cur->ai_next = ai;
1535 while (cur && cur->ai_next)
1536 cur = cur->ai_next;
1537 }
1538 }
1539
1540 return sentinel.ai_next;
1541}
1542#endif
1543
1544
1545/* resolver logic */
1546
1547extern const char *__hostalias(const char *);
1548extern int h_errno;
1549extern int res_opt(int, u_char *, int, int);
1550
1551/*
1552 * Formulate a normal query, send, and await answer.
1553 * Returned answer is placed in supplied buffer "answer".
1554 * Perform preliminary check of answer, returning success only
1555 * if no error is indicated and the answer count is nonzero.
1556 * Return the size of the response on success, -1 on error.
1557 * Error number is left in h_errno.
1558 *
1559 * Caller must parse answer and determine whether it answers the question.
1560 */
1561static int
1562res_queryN(name, target)
1563 const char *name; /* domain name */
1564 struct res_target *target;
1565{
1566 u_char buf[MAXPACKET];
1567 HEADER *hp;
1568 int n;
1569 struct res_target *t;
1570 int rcode;
1571 int ancount;
1572
1573 rcode = NOERROR;
1574 ancount = 0;
1575
1576 if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
1577 h_errno = NETDB_INTERNAL;
1578 return (-1);
1579 }
1580
1581 for (t = target; t; t = t->next) {
1582 int class, type;
1583 u_char *answer;
1584 int anslen;
1585
1586 hp = (HEADER *)(void *)t->answer;
1587 hp->rcode = NOERROR; /* default */
1588
1589 /* make it easier... */
1590 class = t->qclass;
1591 type = t->qtype;
1592 answer = t->answer;
1593 anslen = t->anslen;
1594#ifdef DEBUG
1595 if (_res.options & RES_DEBUG)
1596 printf(";; res_query(%s, %d, %d)\n", name, class, type);
1597#endif
1598
1599 n = res_mkquery(QUERY, name, class, type, NULL, 0, NULL,
1600 buf, sizeof(buf));
1601 if (n > 0 && (_res.options & RES_USE_EDNS0) != 0)
1602 n = res_opt(n, buf, sizeof(buf), anslen);
1603 if (n <= 0) {
1604#ifdef DEBUG
1605 if (_res.options & RES_DEBUG)
1606 printf(";; res_query: mkquery failed\n");
1607#endif
1608 h_errno = NO_RECOVERY;
1609 return (n);
1610 }
1611 n = res_send(buf, n, answer, anslen);
1612#if 0
1613 if (n < 0) {
1614#ifdef DEBUG
1615 if (_res.options & RES_DEBUG)
1616 printf(";; res_query: send error\n");
1617#endif
1618 h_errno = TRY_AGAIN;
1619 return (n);
1620 }
1621#endif
1622
1623 if (n < 0 || hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
1624 rcode = hp->rcode; /* record most recent error */
1625#ifdef DEBUG
1626 if (_res.options & RES_DEBUG)
1627 printf(";; rcode = %u, ancount=%u\n", hp->rcode,
1628 ntohs(hp->ancount));
1629#endif
1630 continue;
1631 }
1632
1633 ancount += ntohs(hp->ancount);
1634
1635 t->n = n;
1636 }
1637
1638 if (ancount == 0) {
1639 switch (rcode) {
1640 case NXDOMAIN:
1641 h_errno = HOST_NOT_FOUND;
1642 break;
1643 case SERVFAIL:
1644 h_errno = TRY_AGAIN;
1645 break;
1646 case NOERROR:
1647 h_errno = NO_DATA;
1648 break;
1649 case FORMERR:
1650 case NOTIMP:
1651 case REFUSED:
1652 default:
1653 h_errno = NO_RECOVERY;
1654 break;
1655 }
1656 return (-1);
1657 }
1658 return (ancount);
1659}
1660
1661/*
1662 * Formulate a normal query, send, and retrieve answer in supplied buffer.
1663 * Return the size of the response on success, -1 on error.
1664 * If enabled, implement search rules until answer or unrecoverable failure
1665 * is detected. Error code, if any, is left in h_errno.
1666 */
1667static int
1668res_searchN(name, target)
1669 const char *name; /* domain name */
1670 struct res_target *target;
1671{
1672 const char *cp, * const *domain;
1673 HEADER *hp = (HEADER *)(void *)target->answer; /*XXX*/
1674 u_int dots;
1675 int trailing_dot, ret, saved_herrno;
1676 int got_nodata = 0, got_servfail = 0, tried_as_is = 0;
1677
1678 if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
1679 h_errno = NETDB_INTERNAL;
1680 return (-1);
1681 }
1682
1683 errno = 0;
1684 h_errno = HOST_NOT_FOUND; /* default, if we never query */
1685 dots = 0;
1686 for (cp = name; *cp; cp++)
1687 dots += (*cp == '.');
1688 trailing_dot = 0;
1689 if (cp > name && *--cp == '.')
1690 trailing_dot++;
1691
1692 /*
1693 * if there aren't any dots, it could be a user-level alias
1694 */
1695 if (!dots && (cp = __hostalias(name)) != NULL)
1696 return (res_queryN(cp, target));
1697
1698 /*
1699 * If there are dots in the name already, let's just give it a try
1700 * 'as is'. The threshold can be set with the "ndots" option.
1701 */
1702 saved_herrno = -1;
1703 if (dots >= _res.ndots) {
1704 ret = res_querydomainN(name, NULL, target);
1705 if (ret > 0)
1706 return (ret);
1707 saved_herrno = h_errno;
1708 tried_as_is++;
1709 }
1710
1711 /*
1712 * We do at least one level of search if
1713 * - there is no dot and RES_DEFNAME is set, or
1714 * - there is at least one dot, there is no trailing dot,
1715 * and RES_DNSRCH is set.
1716 */
1717 if ((!dots && (_res.options & RES_DEFNAMES)) ||
1718 (dots && !trailing_dot && (_res.options & RES_DNSRCH))) {
1719 int done = 0;
1720
1721 for (domain = (const char * const *)_res.dnsrch;
1722 *domain && !done;
1723 domain++) {
1724
1725 ret = res_querydomainN(name, *domain, target);
1726 if (ret > 0)
1727 return (ret);
1728
1729 /*
1730 * If no server present, give up.
1731 * If name isn't found in this domain,
1732 * keep trying higher domains in the search list
1733 * (if that's enabled).
1734 * On a NO_DATA error, keep trying, otherwise
1735 * a wildcard entry of another type could keep us
1736 * from finding this entry higher in the domain.
1737 * If we get some other error (negative answer or
1738 * server failure), then stop searching up,
1739 * but try the input name below in case it's
1740 * fully-qualified.
1741 */
1742 if (errno == ECONNREFUSED) {
1743 h_errno = TRY_AGAIN;
1744 return (-1);
1745 }
1746
1747 switch (h_errno) {
1748 case NO_DATA:
1749 got_nodata++;
1750 /* FALLTHROUGH */
1751 case HOST_NOT_FOUND:
1752 /* keep trying */
1753 break;
1754 case TRY_AGAIN:
1755 if (hp->rcode == SERVFAIL) {
1756 /* try next search element, if any */
1757 got_servfail++;
1758 break;
1759 }
1760 /* FALLTHROUGH */
1761 default:
1762 /* anything else implies that we're done */
1763 done++;
1764 }
1765 /*
1766 * if we got here for some reason other than DNSRCH,
1767 * we only wanted one iteration of the loop, so stop.
1768 */
1769 if (!(_res.options & RES_DNSRCH))
1770 done++;
1771 }
1772 }
1773
1774 /*
1775 * if we have not already tried the name "as is", do that now.
1776 * note that we do this regardless of how many dots were in the
1777 * name or whether it ends with a dot.
1778 */
1779 if (!tried_as_is) {
1780 ret = res_querydomainN(name, NULL, target);
1781 if (ret > 0)
1782 return (ret);
1783 }
1784
1785 /*
1786 * if we got here, we didn't satisfy the search.
1787 * if we did an initial full query, return that query's h_errno
1788 * (note that we wouldn't be here if that query had succeeded).
1789 * else if we ever got a nodata, send that back as the reason.
1790 * else send back meaningless h_errno, that being the one from
1791 * the last DNSRCH we did.
1792 */
1793 if (saved_herrno != -1)
1794 h_errno = saved_herrno;
1795 else if (got_nodata)
1796 h_errno = NO_DATA;
1797 else if (got_servfail)
1798 h_errno = TRY_AGAIN;
1799 return (-1);
1800}
1801
1802/*
1803 * Perform a call on res_query on the concatenation of name and domain,
1804 * removing a trailing dot from name if domain is NULL.
1805 */
1806static int
1807res_querydomainN(name, domain, target)
1808 const char *name, *domain;
1809 struct res_target *target;
1810{
1811 char nbuf[MAXDNAME];
1812 const char *longname = nbuf;
1813 size_t n, d;
1814
1815 if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
1816 h_errno = NETDB_INTERNAL;
1817 return (-1);
1818 }
1819#ifdef DEBUG
1820 if (_res.options & RES_DEBUG)
1821 printf(";; res_querydomain(%s, %s)\n",
1822 name, domain?domain:"<Nil>");
1823#endif
1824 if (domain == NULL) {
1825 /*
1826 * Check for trailing '.';
1827 * copy without '.' if present.
1828 */
1829 n = strlen(name);
1830 if (n >= MAXDNAME) {
1831 h_errno = NO_RECOVERY;
1832 return (-1);
1833 }
1834 if (n > 0 && name[--n] == '.') {
1835 strlcpy(nbuf, name, n + 1);
1836 } else
1837 longname = name;
1838 } else {
1839 n = strlen(name);
1840 d = strlen(domain);
1841 if (n + d + 1 >= MAXDNAME) {
1842 h_errno = NO_RECOVERY;
1843 return (-1);
1844 }
1845 snprintf(nbuf, sizeof(nbuf), "%s.%s", name, domain);
1846 }
1847 return (res_queryN(longname, target));
1848}
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..909ce573b7 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.53 2002/08/27 08:53:13 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,108 @@ 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 register const HEADER *hp;
126 register u_char *cp; 164 register const u_char *cp;
127 register int n; 165 register int n;
128 u_char *eom; 166 const u_char *eom;
129 char *bp, **ap; 167 char *bp, **ap, **hap, *ep;
130 int type, class, buflen, ancount, qdcount; 168 int type, class, ancount, qdcount;
131 int haveanswer, getclass = C_ANY; 169 int haveanswer, had_error;
132 char **hap; 170 int toobig = 0;
171 char tbuf[MAXDNAME];
172 const char *tname;
173 int (*name_ok)(const char *);
133 174
175 tname = qname;
176 host.h_name = NULL;
134 eom = answer->buf + anslen; 177 eom = answer->buf + anslen;
178 switch (qtype) {
179 case T_A:
180 case T_AAAA:
181#ifdef USE_RESOLV_NAME_OK
182 name_ok = res_hnok;
183 break;
184#endif
185 case T_PTR:
186#ifdef USE_RESOLV_NAME_OK
187 name_ok = res_dnok;
188#else
189 name_ok = _hokchar;
190#endif
191 break;
192 default:
193 return (NULL);
194 }
135 /* 195 /*
136 * find first satisfactory answer 196 * find first satisfactory answer
137 */ 197 */
@@ -139,31 +199,28 @@ getanswer(answer, anslen, iquery)
139 ancount = ntohs(hp->ancount); 199 ancount = ntohs(hp->ancount);
140 qdcount = ntohs(hp->qdcount); 200 qdcount = ntohs(hp->qdcount);
141 bp = hostbuf; 201 bp = hostbuf;
142 buflen = sizeof(hostbuf); 202 ep = hostbuf + sizeof hostbuf;
143 cp = answer->buf + sizeof(HEADER); 203 cp = answer->buf + HFIXEDSZ;
144 if (qdcount) { 204 if (qdcount != 1) {
145 if (iquery) { 205 h_errno = NO_RECOVERY;
146 if ((n = dn_expand((u_char *)answer->buf, 206 return (NULL);
147 (u_char *)eom, (u_char *)cp, (u_char *)bp, 207 }
148 buflen)) < 0) { 208 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
149 h_errno = NO_RECOVERY; 209 if ((n < 0) || !(*name_ok)(bp)) {
150 return ((struct hostent *) NULL); 210 h_errno = NO_RECOVERY;
151 } 211 return (NULL);
152 cp += n + QFIXEDSZ; 212 }
153 host.h_name = bp; 213 cp += n + QFIXEDSZ;
154 n = strlen(bp) + 1; 214 if (qtype == T_A || qtype == T_AAAA) {
155 bp += n; 215 /* res_send() has already verified that the query name is the
156 buflen -= n; 216 * same as the one we sent; this just gets the expanded name
157 } else 217 * (i.e., with the succeeding search-domain tacked on).
158 cp += __dn_skipname(cp, eom) + QFIXEDSZ; 218 */
159 while (--qdcount > 0) 219 n = strlen(bp) + 1; /* for the \0 */
160 cp += __dn_skipname(cp, eom) + QFIXEDSZ; 220 host.h_name = bp;
161 } else if (iquery) { 221 bp += n;
162 if (hp->aa) 222 /* The qname can be abbreviated, but h_name is now absolute. */
163 h_errno = HOST_NOT_FOUND; 223 qname = host.h_name;
164 else
165 h_errno = TRY_AGAIN;
166 return ((struct hostent *) NULL);
167 } 224 }
168 ap = host_aliases; 225 ap = host_aliases;
169 *ap = NULL; 226 *ap = NULL;
@@ -172,104 +229,327 @@ getanswer(answer, anslen, iquery)
172 *hap = NULL; 229 *hap = NULL;
173 host.h_addr_list = h_addr_ptrs; 230 host.h_addr_list = h_addr_ptrs;
174 haveanswer = 0; 231 haveanswer = 0;
175 while (--ancount >= 0 && cp < eom) { 232 had_error = 0;
176 if ((n = dn_expand((u_char *)answer->buf, (u_char *)eom, 233 while (ancount-- > 0 && cp < eom && !had_error) {
177 (u_char *)cp, (u_char *)bp, buflen)) < 0) 234 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
178 break; 235 if ((n < 0) || !(*name_ok)(bp)) {
179 cp += n; 236 had_error++;
237 continue;
238 }
239 cp += n; /* name */
180 type = _getshort(cp); 240 type = _getshort(cp);
181 cp += sizeof(u_int16_t); 241 cp += INT16SZ; /* type */
182 class = _getshort(cp); 242 class = _getshort(cp);
183 cp += sizeof(u_int16_t) + sizeof(u_int32_t); 243 cp += INT16SZ + INT32SZ; /* class, TTL */
184 n = _getshort(cp); 244 n = _getshort(cp);
185 cp += sizeof(u_int16_t); 245 cp += INT16SZ; /* len */
186 if (type == T_CNAME) { 246 if (type == T_SIG) {
247 /* XXX - ignore signatures as we don't use them yet */
248 cp += n;
249 continue;
250 }
251 if (class != C_IN) {
252 /* XXX - debug? syslog? */
187 cp += n; 253 cp += n;
254 continue; /* XXX - had_error++ ? */
255 }
256 if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) {
188 if (ap >= &host_aliases[MAXALIASES-1]) 257 if (ap >= &host_aliases[MAXALIASES-1])
189 continue; 258 continue;
259 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
260 if ((n < 0) || !(*name_ok)(tbuf)) {
261 had_error++;
262 continue;
263 }
264 cp += n;
265 /* Store alias. */
190 *ap++ = bp; 266 *ap++ = bp;
191 n = strlen(bp) + 1; 267 n = strlen(bp) + 1; /* for the \0 */
192 bp += n; 268 bp += n;
193 buflen -= n; 269 /* Get canonical name. */
194 continue; 270 n = strlen(tbuf) + 1; /* for the \0 */
195 } 271 if (n > ep - bp) {
196 if (iquery && type == T_PTR) { 272 had_error++;
197 if ((n = dn_expand((u_char *)answer->buf, 273 continue;
198 (u_char *)eom, (u_char *)cp, (u_char *)bp, 274 }
199 buflen)) < 0) 275 strlcpy(bp, tbuf, ep - bp);
200 break;
201 cp += n;
202 host.h_name = bp; 276 host.h_name = bp;
203 return(&host); 277 bp += n;
278 continue;
204 } 279 }
205 if (iquery || type != T_A) { 280 if (qtype == T_PTR && type == T_CNAME) {
206#ifdef DEBUG 281 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
207 if (_res.options & RES_DEBUG) 282#ifdef USE_RESOLV_NAME_OK
208 printf("unexpected answer type %d, size %d\n", 283 if ((n < 0) || !res_hnok(tbuf)) {
209 type, n); 284#else
285 if ((n < 0) || !_hokchar(tbuf)) {
210#endif 286#endif
287 had_error++;
288 continue;
289 }
211 cp += n; 290 cp += n;
291 /* Get canonical name. */
292 n = strlen(tbuf) + 1; /* for the \0 */
293 if (n > ep - bp) {
294 had_error++;
295 continue;
296 }
297 strlcpy(bp, tbuf, ep - bp);
298 tname = bp;
299 bp += n;
212 continue; 300 continue;
213 } 301 }
214 if (haveanswer) { 302 if (type != qtype) {
215 if (n != host.h_length) { 303 syslog(LOG_NOTICE|LOG_AUTH,
304 "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
305 qname, p_class(C_IN), p_type(qtype),
306 p_type(type));
307 cp += n;
308 continue; /* XXX - had_error++ ? */
309 }
310 switch (type) {
311 case T_PTR:
312 if (strcasecmp(tname, bp) != 0) {
313 syslog(LOG_NOTICE|LOG_AUTH,
314 AskedForGot, qname, bp);
216 cp += n; 315 cp += n;
217 continue; 316 continue; /* XXX - had_error++ ? */
317 }
318 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
319#ifdef USE_RESOLV_NAME_OK
320 if ((n < 0) || !res_hnok(bp)) {
321#else
322 if ((n < 0) || !_hokchar(bp)) {
323#endif
324 had_error++;
325 break;
326 }
327#if MULTI_PTRS_ARE_ALIASES
328 cp += n;
329 if (!haveanswer)
330 host.h_name = bp;
331 else if (ap < &host_aliases[MAXALIASES-1])
332 *ap++ = bp;
333 else
334 n = -1;
335 if (n != -1) {
336 n = strlen(bp) + 1; /* for the \0 */
337 bp += n;
218 } 338 }
219 if (class != getclass) { 339 break;
340#else
341 host.h_name = bp;
342 if (_res.options & RES_USE_INET6) {
343 n = strlen(bp) + 1; /* for the \0 */
344 bp += n;
345 map_v4v6_hostent(&host, &bp, ep);
346 }
347 h_errno = NETDB_SUCCESS;
348 return (&host);
349#endif
350 case T_A:
351 case T_AAAA:
352 if (strcasecmp(host.h_name, bp) != 0) {
353 syslog(LOG_NOTICE|LOG_AUTH,
354 AskedForGot, host.h_name, bp);
355 cp += n;
356 continue; /* XXX - had_error++ ? */
357 }
358 if (n != host.h_length) {
220 cp += n; 359 cp += n;
221 continue; 360 continue;
222 } 361 }
223 } else { 362 if (type == T_AAAA) {
224 host.h_length = n; 363 struct in6_addr in6;
225 getclass = class; 364 memcpy(&in6, cp, IN6ADDRSZ);
226 host.h_addrtype = (class == C_IN) ? AF_INET : AF_UNSPEC; 365 if (IN6_IS_ADDR_V4MAPPED(&in6)) {
227 if (!iquery) { 366 cp += n;
367 continue;
368 }
369 }
370 if (!haveanswer) {
371 register int nn;
372
228 host.h_name = bp; 373 host.h_name = bp;
229 bp += strlen(bp) + 1; 374 nn = strlen(bp) + 1; /* for the \0 */
375 bp += nn;
230 } 376 }
231 }
232 377
233 bp += sizeof(align) - ((u_long)bp % sizeof(align)); 378 bp += sizeof(align) - ((u_long)bp % sizeof(align));
234 379
235 if (bp + n >= &hostbuf[sizeof(hostbuf)]) { 380 if (bp + n >= &hostbuf[sizeof hostbuf]) {
236#ifdef DEBUG 381#ifdef DEBUG
237 if (_res.options & RES_DEBUG) 382 if (_res.options & RES_DEBUG)
238 printf("size (%d) too big\n", n); 383 printf("size (%d) too big\n", n);
239#endif 384#endif
385 had_error++;
386 continue;
387 }
388 if (hap >= &h_addr_ptrs[MAXADDRS-1]) {
389 if (!toobig++)
390#ifdef DEBUG
391 if (_res.options & RES_DEBUG)
392 printf("Too many addresses (%d)\n", MAXADDRS);
393#endif
394 cp += n;
395 continue;
396 }
397 bcopy(cp, *hap++ = bp, n);
398 bp += n;
399 cp += n;
240 break; 400 break;
241 } 401 }
242 bcopy(cp, *hap++ = bp, n); 402 if (!had_error)
243 bp +=n; 403 haveanswer++;
244 cp += n;
245 haveanswer++;
246 } 404 }
247 if (haveanswer) { 405 if (haveanswer) {
248 *ap = NULL; 406 *ap = NULL;
249 *hap = NULL; 407 *hap = NULL;
250 if (_res.nsort) { 408# if defined(RESOLVSORT)
251 qsort(host.h_addr_list, haveanswer, 409 /*
252 sizeof(struct in_addr), 410 * Note: we sort even if host can take only one address
253 (int (*)__P((const void *, const void *)))qcomp); 411 * in its return structures - should give it the "best"
412 * address in that case, not some random one
413 */
414 if (_res.nsort && haveanswer > 1 && qtype == T_A)
415 addrsort(h_addr_ptrs, haveanswer);
416# endif /*RESOLVSORT*/
417 if (!host.h_name) {
418 n = strlen(qname) + 1; /* for the \0 */
419 if (n > ep - bp)
420 goto try_again;
421 strlcpy(bp, qname, ep - bp);
422 host.h_name = bp;
423 bp += n;
254 } 424 }
425 if (_res.options & RES_USE_INET6)
426 map_v4v6_hostent(&host, &bp, ep);
427 h_errno = NETDB_SUCCESS;
255 return (&host); 428 return (&host);
256 } else {
257 h_errno = TRY_AGAIN;
258 return ((struct hostent *) NULL);
259 } 429 }
430 try_again:
431 h_errno = TRY_AGAIN;
432 return (NULL);
433}
434
435#ifdef notyet
436/*
437 * XXX This is an extremely bogus implementation.
438 *
439 * FreeBSD has this interface:
440 * int gethostbyaddr_r(const char *addr, int len, int type,
441 * struct hostent *result, struct hostent_data *buffer)
442 */
443
444struct hostent *
445gethostbyname_r(name, hp, buf, buflen, errorp)
446 const char * name;
447 struct hostent * hp;
448 char * buf;
449 int buflen;
450 int * errorp;
451{
452 struct hostent *res;
453
454 res = gethostbyname(name);
455 *errorp = h_errno;
456 if (res == NULL)
457 return NULL;
458 memcpy(hp, res, sizeof *hp); /* XXX not sufficient */
459 return hp;
460}
461
462/*
463 * XXX This is an extremely bogus implementation.
464 */
465struct hostent *
466gethostbyaddr_r(addr, len, af, he, buf, buflen, errorp)
467 const char *addr; /* XXX should have been def'd as u_char! */
468 int len, af;
469 struct hostent * he;
470 char * buf;
471 int buflen;
472 int * errorp;
473{
474 struct hostent * res;
475
476 res = gethostbyaddr(addr, len, af);
477 *errorp = h_errno;
478 if (res == NULL)
479 return NULL;
480 memcpy(he, res, sizeof *he); /* XXX not sufficient */
481 return he;
260} 482}
261 483
484/* XXX RFC2133 expects a gethostbyname2_r() -- unimplemented */
485#endif
486
487_THREAD_PRIVATE_MUTEX(gethostnamadr);
488
262struct hostent * 489struct hostent *
263gethostbyname(name) 490gethostbyname(name)
264 const char *name; 491 const char *name;
265{ 492{
266 querybuf buf; 493 struct hostent *hp;
494 extern struct hostent *_gethtbyname2();
495
496 _THREAD_PRIVATE_MUTEX_LOCK(gethostnamadr);
497 if ((_res.options & RES_INIT) == 0 && res_init() == -1)
498 hp = _gethtbyname2(name, AF_INET);
499
500 else if (_res.options & RES_USE_INET6) {
501 hp = gethostbyname2(name, AF_INET6);
502 if (hp == NULL)
503 hp = gethostbyname2(name, AF_INET);
504 }
505 else
506 hp = gethostbyname2(name, AF_INET);
507 _THREAD_PRIVATE_MUTEX_UNLOCK(gethostnamadr);
508 return hp;
509}
510
511struct hostent *
512gethostbyname2(name, af)
513 const char *name;
514 int af;
515{
516 querybuf *buf;
267 register const char *cp; 517 register const char *cp;
268 int n, i; 518 char *bp, *ep;
269 extern struct hostent *_gethtbyname(), *_yp_gethtbyname(); 519 int n, size, type, i;
520 extern struct hostent *_gethtbyname2(), *_yp_gethtbyname();
270 register struct hostent *hp; 521 register struct hostent *hp;
271 char lookups[MAXDNSLUS]; 522 char lookups[MAXDNSLUS];
272 523
524 if ((_res.options & RES_INIT) == 0 && res_init() == -1)
525 return (_gethtbyname2(name, af));
526
527 switch (af) {
528 case AF_INET:
529 size = INADDRSZ;
530 type = T_A;
531 break;
532 case AF_INET6:
533 size = IN6ADDRSZ;
534 type = T_AAAA;
535 break;
536 default:
537 h_errno = NETDB_INTERNAL;
538 errno = EAFNOSUPPORT;
539 return (NULL);
540 }
541
542 host.h_addrtype = af;
543 host.h_length = size;
544
545 /*
546 * if there aren't any dots, it could be a user-level alias.
547 * this is also done in res_query() since we are not the only
548 * function that looks up host names.
549 */
550 if (!strchr(name, '.') && (cp = __hostalias(name)))
551 name = cp;
552
273 /* 553 /*
274 * disallow names consisting only of digits/dots, unless 554 * disallow names consisting only of digits/dots, unless
275 * they end in a dot. 555 * they end in a dot.
@@ -284,116 +564,227 @@ gethostbyname(name)
284 * Fake up a hostent as if we'd actually 564 * Fake up a hostent as if we'd actually
285 * done a lookup. 565 * done a lookup.
286 */ 566 */
287 if (!inet_aton(name, &host_addr)) { 567 if (inet_pton(af, name, host_addr) <= 0) {
288 h_errno = HOST_NOT_FOUND; 568 h_errno = HOST_NOT_FOUND;
289 return((struct hostent *) NULL); 569 return (NULL);
290 } 570 }
291 host.h_name = (char *)name; 571 strlcpy(hostbuf, name, MAXHOSTNAMELEN);
572 bp = hostbuf + MAXHOSTNAMELEN;
573 ep = hostbuf + sizeof(hostbuf);
574 host.h_name = hostbuf;
292 host.h_aliases = host_aliases; 575 host.h_aliases = host_aliases;
293 host_aliases[0] = NULL; 576 host_aliases[0] = NULL;
294 host.h_addrtype = AF_INET; 577 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; 578 h_addr_ptrs[1] = NULL;
298 host.h_addr_list = h_addr_ptrs; 579 host.h_addr_list = h_addr_ptrs;
580 if (_res.options & RES_USE_INET6)
581 map_v4v6_hostent(&host, &bp, ep);
582 h_errno = NETDB_SUCCESS;
299 return (&host); 583 return (&host);
300 } 584 }
301 if (!isdigit(*cp) && *cp != '.') 585 if (!isdigit(*cp) && *cp != '.')
302 break; 586 break;
303 } 587 }
304 588 if ((isxdigit(name[0]) && strchr(name, ':') != NULL) ||
305 if ((_res.options & RES_INIT) == 0 && res_init() == -1) 589 name[0] == ':')
306 return (_gethtbyname(name)); 590 for (cp = name;; ++cp) {
591 if (!*cp) {
592 if (*--cp == '.')
593 break;
594 /*
595 * All-IPv6-legal, no dot at the end.
596 * Fake up a hostent as if we'd actually
597 * done a lookup.
598 */
599 if (inet_pton(af, name, host_addr) <= 0) {
600 h_errno = HOST_NOT_FOUND;
601 return (NULL);
602 }
603 strlcpy(hostbuf, name, MAXHOSTNAMELEN);
604 bp = hostbuf + MAXHOSTNAMELEN;
605 ep = hostbuf + sizeof(hostbuf);
606 host.h_name = hostbuf;
607 host.h_aliases = host_aliases;
608 host_aliases[0] = NULL;
609 h_addr_ptrs[0] = (char *)host_addr;
610 h_addr_ptrs[1] = NULL;
611 host.h_addr_list = h_addr_ptrs;
612 h_errno = NETDB_SUCCESS;
613 return (&host);
614 }
615 if (!isxdigit(*cp) && *cp != ':' && *cp != '.')
616 break;
617 }
307 618
308 bcopy(_res.lookups, lookups, sizeof lookups); 619 bcopy(_res.lookups, lookups, sizeof lookups);
309 if (lookups[0] == '\0') 620 if (lookups[0] == '\0')
310 strncpy(lookups, "bf", sizeof lookups); 621 strlcpy(lookups, "bf", sizeof lookups);
311 622
312 hp = (struct hostent *)NULL; 623 hp = (struct hostent *)NULL;
313 for (i = 0; i < MAXDNSLUS && hp == NULL && lookups[i]; i++) { 624 for (i = 0; i < MAXDNSLUS && hp == NULL && lookups[i]; i++) {
314 switch (lookups[i]) { 625 switch (lookups[i]) {
315#ifdef YP 626#ifdef YP
316 case 'y': 627 case 'y':
317 hp = _yp_gethtbyname(name); 628 /* YP only supports AF_INET. */
629 if (af == AF_INET)
630 hp = _yp_gethtbyname(name);
318 break; 631 break;
319#endif 632#endif
320 case 'b': 633 case 'b':
321 if ((n = res_search(name, C_IN, T_A, buf.buf, 634 buf = malloc(sizeof(*buf));
322 sizeof(buf))) < 0) { 635 if (buf == NULL)
636 break;
637 if ((n = res_search(name, C_IN, type, buf->buf,
638 sizeof(buf->buf))) < 0) {
639 free(buf);
323#ifdef DEBUG 640#ifdef DEBUG
324 if (_res.options & RES_DEBUG) 641 if (_res.options & RES_DEBUG)
325 printf("res_search failed\n"); 642 printf("res_search failed\n");
326#endif 643#endif
327 break; 644 break;
328 } 645 }
329 hp = getanswer(&buf, n, 0); 646 hp = getanswer(buf, n, name, type);
647 free(buf);
330 break; 648 break;
331 case 'f': 649 case 'f':
332 hp = _gethtbyname(name); 650 hp = _gethtbyname2(name, af);
333 break; 651 break;
334 } 652 }
335 } 653 }
654 /* XXX h_errno not correct in all cases... */
336 return (hp); 655 return (hp);
337} 656}
338 657
339struct hostent * 658struct hostent *
340gethostbyaddr(addr, len, type) 659gethostbyaddr(addr, len, af)
341 const char *addr; 660 const char *addr; /* XXX should have been def'd as u_char! */
342 int len, type; 661 int len, af;
343{ 662{
344 int n, i; 663 const u_char *uaddr = (const u_char *)addr;
345 querybuf buf; 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;
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 _THREAD_PRIVATE_MUTEX_LOCK(gethostnamadr);
352 return ((struct hostent *) NULL); 673 if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
353 (void)sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa", 674 res = _gethtbyaddr(addr, len, af);
354 ((unsigned)addr[3] & 0xff), 675 _THREAD_PRIVATE_MUTEX_UNLOCK(gethostnamadr);
355 ((unsigned)addr[2] & 0xff), 676 return (res);
356 ((unsigned)addr[1] & 0xff), 677 }
357 ((unsigned)addr[0] & 0xff));
358 678
359 if ((_res.options & RES_INIT) == 0 && res_init() == -1) 679 if (af == AF_INET6 && len == IN6ADDRSZ &&
360 return (_gethtbyaddr(addr, len, type)); 680 (IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)uaddr) ||
681 IN6_IS_ADDR_SITELOCAL((struct in6_addr *)uaddr))) {
682 h_errno = HOST_NOT_FOUND;
683 return (NULL);
684 }
685 if (af == AF_INET6 && len == IN6ADDRSZ &&
686 (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)uaddr) ||
687 IN6_IS_ADDR_V4COMPAT((struct in6_addr *)uaddr))) {
688 /* Unmap. */
689 addr += IN6ADDRSZ - INADDRSZ;
690 uaddr += IN6ADDRSZ - INADDRSZ;
691 af = AF_INET;
692 len = INADDRSZ;
693 }
694 switch (af) {
695 case AF_INET:
696 size = INADDRSZ;
697 break;
698 case AF_INET6:
699 size = IN6ADDRSZ;
700 break;
701 default:
702 errno = EAFNOSUPPORT;
703 h_errno = NETDB_INTERNAL;
704 _THREAD_PRIVATE_MUTEX_UNLOCK(gethostnamadr);
705 return (NULL);
706 }
707 if (size != len) {
708 errno = EINVAL;
709 h_errno = NETDB_INTERNAL;
710 _THREAD_PRIVATE_MUTEX_UNLOCK(gethostnamadr);
711 return (NULL);
712 }
713 switch (af) {
714 case AF_INET:
715 (void) snprintf(qbuf, sizeof qbuf, "%u.%u.%u.%u.in-addr.arpa",
716 (uaddr[3] & 0xff), (uaddr[2] & 0xff),
717 (uaddr[1] & 0xff), (uaddr[0] & 0xff));
718 break;
719 case AF_INET6:
720 qp = qbuf;
721 for (n = IN6ADDRSZ - 1; n >= 0; n--) {
722 qp += sprintf(qp, "%x.%x.",
723 uaddr[n] & 0xf, (uaddr[n] >> 4) & 0xf);
724 }
725 break;
726 }
361 727
362 bcopy(_res.lookups, lookups, sizeof lookups); 728 bcopy(_res.lookups, lookups, sizeof lookups);
363 if (lookups[0] == '\0') 729 if (lookups[0] == '\0')
364 strncpy(lookups, "bf", sizeof lookups); 730 strlcpy(lookups, "bf", sizeof lookups);
365 731
366 hp = (struct hostent *)NULL; 732 hp = (struct hostent *)NULL;
367 for (i = 0; i < MAXDNSLUS && hp == NULL && lookups[i]; i++) { 733 for (i = 0; i < MAXDNSLUS && hp == NULL && lookups[i]; i++) {
368 switch (lookups[i]) { 734 switch (lookups[i]) {
369#ifdef YP 735#ifdef YP
370 case 'y': 736 case 'y':
371 hp = _yp_gethtbyaddr(addr, len, type); 737 /* YP only supports AF_INET. */
738 if (af == AF_INET)
739 hp = _yp_gethtbyaddr(addr);
372 break; 740 break;
373#endif 741#endif
374 case 'b': 742 case 'b':
375 n = res_query(qbuf, C_IN, T_PTR, (char *)&buf, sizeof(buf)); 743 if (af == AF_INET6)
744 strcpy(qp, "ip6.arpa");
745 buf = malloc(sizeof(*buf));
746 if (!buf)
747 break;
748 n = res_query(qbuf, C_IN, T_PTR, buf->buf,
749 sizeof(buf->buf));
750 if (n < 0 && af == AF_INET6) {
751 strcpy(qp, "ip6.int");
752 n = res_query(qbuf, C_IN, T_PTR,
753 buf->buf, sizeof(buf->buf));
754 }
376 if (n < 0) { 755 if (n < 0) {
756 free(buf);
377#ifdef DEBUG 757#ifdef DEBUG
378 if (_res.options & RES_DEBUG) 758 if (_res.options & RES_DEBUG)
379 printf("res_query failed\n"); 759 printf("res_query failed\n");
380#endif 760#endif
381 break; 761 break;
382 } 762 }
383 hp = getanswer(&buf, n, 1); 763 if (!(hp = getanswer(buf, n, qbuf, T_PTR))) {
384 if (hp == NULL) 764 free(buf);
385 break; 765 break;
386 hp->h_addrtype = type; 766 }
767 free(buf);
768 hp->h_addrtype = af;
387 hp->h_length = len; 769 hp->h_length = len;
388 h_addr_ptrs[0] = (char *)&host_addr; 770 bcopy(addr, host_addr, len);
389 h_addr_ptrs[1] = (char *)0; 771 h_addr_ptrs[0] = (char *)host_addr;
390 host_addr = *(struct in_addr *)addr; 772 h_addr_ptrs[1] = NULL;
773 if (af == AF_INET && (_res.options & RES_USE_INET6)) {
774 map_v4v6_address((char*)host_addr,
775 (char*)host_addr);
776 hp->h_addrtype = AF_INET6;
777 hp->h_length = IN6ADDRSZ;
778 }
779 h_errno = NETDB_SUCCESS;
391 break; 780 break;
392 case 'f': 781 case 'f':
393 hp = _gethtbyaddr(addr, len, type); 782 hp = _gethtbyaddr(addr, len, af);
394 break; 783 break;
395 } 784 }
396 } 785 }
786 _THREAD_PRIVATE_MUTEX_UNLOCK(gethostnamadr);
787 /* XXX h_errno not correct in all cases... */
397 return (hp); 788 return (hp);
398} 789}
399 790
@@ -422,35 +813,61 @@ _gethtent()
422{ 813{
423 char *p; 814 char *p;
424 register char *cp, **q; 815 register char *cp, **q;
816 int af;
817 size_t len;
425 818
426 if (hostf == NULL && (hostf = fopen(_PATH_HOSTS, "r" )) == NULL) 819 if (!hostf && !(hostf = fopen(_PATH_HOSTS, "r" ))) {
820 h_errno = NETDB_INTERNAL;
427 return (NULL); 821 return (NULL);
428again: 822 }
429 if ((p = fgets(hostbuf, BUFSIZ, hostf)) == NULL) 823 again:
824 if ((p = fgetln(hostf, &len)) == NULL) {
825 h_errno = HOST_NOT_FOUND;
430 return (NULL); 826 return (NULL);
827 }
828 if (p[len-1] == '\n')
829 len--;
830 if (len >= sizeof(hostbuf) || len == 0)
831 goto again;
832 p = memcpy(hostbuf, p, len);
833 hostbuf[len] = '\0';
431 if (*p == '#') 834 if (*p == '#')
432 goto again; 835 goto again;
433 cp = strpbrk(p, "#\n"); 836 if ((cp = strchr(p, '#')))
434 if (cp == NULL) 837 *cp = '\0';
435 goto again; 838 if (!(cp = strpbrk(p, " \t")))
436 *cp = '\0';
437 cp = strpbrk(p, " \t");
438 if (cp == NULL)
439 goto again; 839 goto again;
440 *cp++ = '\0'; 840 *cp++ = '\0';
441 /* THIS STUFF IS INTERNET SPECIFIC */ 841 if (inet_pton(AF_INET6, p, host_addr) > 0) {
442 h_addr_ptrs[0] = (char *)&host_addr; 842 af = AF_INET6;
843 len = IN6ADDRSZ;
844 } else if (inet_pton(AF_INET, p, host_addr) > 0) {
845 if (_res.options & RES_USE_INET6) {
846 map_v4v6_address((char*)host_addr, (char*)host_addr);
847 af = AF_INET6;
848 len = IN6ADDRSZ;
849 } else {
850 af = AF_INET;
851 len = INADDRSZ;
852 }
853 } else {
854 goto again;
855 }
856 /* if this is not something we're looking for, skip it. */
857 if (host.h_addrtype != af)
858 goto again;
859 if (host.h_length != len)
860 goto again;
861 h_addr_ptrs[0] = (char *)host_addr;
443 h_addr_ptrs[1] = NULL; 862 h_addr_ptrs[1] = NULL;
444 (void) inet_aton(p, &host_addr);
445 host.h_addr_list = h_addr_ptrs; 863 host.h_addr_list = h_addr_ptrs;
446 host.h_length = sizeof(u_int32_t); 864 host.h_length = len;
447 host.h_addrtype = AF_INET; 865 host.h_addrtype = af;
448 while (*cp == ' ' || *cp == '\t') 866 while (*cp == ' ' || *cp == '\t')
449 cp++; 867 cp++;
450 host.h_name = cp; 868 host.h_name = cp;
451 q = host.h_aliases = host_aliases; 869 q = host.h_aliases = host_aliases;
452 cp = strpbrk(cp, " \t"); 870 if ((cp = strpbrk(cp, " \t")))
453 if (cp != NULL)
454 *cp++ = '\0'; 871 *cp++ = '\0';
455 while (cp && *cp) { 872 while (cp && *cp) {
456 if (*cp == ' ' || *cp == '\t') { 873 if (*cp == ' ' || *cp == '\t') {
@@ -459,70 +876,76 @@ again:
459 } 876 }
460 if (q < &host_aliases[MAXALIASES - 1]) 877 if (q < &host_aliases[MAXALIASES - 1])
461 *q++ = cp; 878 *q++ = cp;
462 cp = strpbrk(cp, " \t"); 879 if ((cp = strpbrk(cp, " \t")))
463 if (cp != NULL)
464 *cp++ = '\0'; 880 *cp++ = '\0';
465 } 881 }
466 *q = NULL; 882 *q = NULL;
883 if (_res.options & RES_USE_INET6) {
884 char *bp = hostbuf;
885 char *ep = hostbuf + sizeof hostbuf;
886
887 map_v4v6_hostent(&host, &bp, ep);
888 }
889 h_errno = NETDB_SUCCESS;
467 return (&host); 890 return (&host);
468} 891}
469 892
470struct hostent * 893struct hostent *
471_gethtbyname(name) 894_gethtbyname(name)
472 char *name; 895 const char *name;
896{
897 extern struct hostent *_gethtbyname2();
898 struct hostent *hp;
899
900 if (_res.options & RES_USE_INET6) {
901 hp = _gethtbyname2(name, AF_INET6);
902 if (hp)
903 return (hp);
904 }
905 return (_gethtbyname2(name, AF_INET));
906}
907
908struct hostent *
909_gethtbyname2(name, af)
910 const char *name;
911 int af;
473{ 912{
474 register struct hostent *p; 913 register struct hostent *p;
475 register char **cp; 914 register char **cp;
476 915
477 _sethtent(0); 916 _sethtent(0);
478 while (p = _gethtent()) { 917 while ((p = _gethtent())) {
918 if (p->h_addrtype != af)
919 continue;
479 if (strcasecmp(p->h_name, name) == 0) 920 if (strcasecmp(p->h_name, name) == 0)
480 break; 921 break;
481 for (cp = p->h_aliases; *cp != 0; cp++) 922 for (cp = p->h_aliases; *cp != 0; cp++)
482 if (strcasecmp(*cp, name) == 0) 923 if (strcasecmp(*cp, name) == 0)
483 goto found; 924 goto found;
484 } 925 }
485found: 926 found:
486 _endhtent(); 927 _endhtent();
487 if (p==NULL)
488 h_errno = HOST_NOT_FOUND;
489 return (p); 928 return (p);
490} 929}
491 930
492struct hostent * 931struct hostent *
493_gethtbyaddr(addr, len, type) 932_gethtbyaddr(addr, len, af)
494 const char *addr; 933 const char *addr;
495 int len, type; 934 int len, af;
496{ 935{
497 register struct hostent *p; 936 register struct hostent *p;
498 937
938 host.h_length = len;
939 host.h_addrtype = af;
940
499 _sethtent(0); 941 _sethtent(0);
500 while (p = _gethtent()) 942 while ((p = _gethtent()))
501 if (p->h_addrtype == type && !bcmp(p->h_addr, addr, len)) 943 if (p->h_addrtype == af && !bcmp(p->h_addr, addr, len))
502 break; 944 break;
503 _endhtent(); 945 _endhtent();
504 if (p==NULL)
505 h_errno = HOST_NOT_FOUND;
506 return (p); 946 return (p);
507} 947}
508 948
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 949#ifdef YP
527struct hostent * 950struct hostent *
528_yphostent(line) 951_yphostent(line)
@@ -537,21 +960,21 @@ _yphostent(line)
537 960
538 host.h_name = NULL; 961 host.h_name = NULL;
539 host.h_addr_list = h_addr_ptrs; 962 host.h_addr_list = h_addr_ptrs;
540 host.h_length = sizeof(u_int32_t); 963 host.h_length = INADDRSZ;
541 host.h_addrtype = AF_INET; 964 host.h_addrtype = AF_INET;
542 hap = h_addr_ptrs; 965 hap = h_addr_ptrs;
543 buf = host_addrs; 966 buf = host_addrs;
544 q = host.h_aliases = host_aliases; 967 q = host.h_aliases = host_aliases;
545 968
546nextline: 969nextline:
970 /* check for host_addrs overflow */
971 if (buf >= &host_addrs[sizeof(host_addrs) / sizeof(host_addrs[0])])
972 goto done;
973
547 more = 0; 974 more = 0;
548 cp = strpbrk(p, " \t"); 975 cp = strpbrk(p, " \t");
549 if (cp == NULL) { 976 if (cp == NULL)
550 if (host.h_name == NULL) 977 goto done;
551 return (NULL);
552 else
553 goto done;
554 }
555 *cp++ = '\0'; 978 *cp++ = '\0';
556 979
557 *hap++ = (char *)buf; 980 *hap++ = (char *)buf;
@@ -592,30 +1015,29 @@ nextline:
592 *cp++ = '\0'; 1015 *cp++ = '\0';
593 } 1016 }
594done: 1017done:
1018 if (host.h_name == NULL)
1019 return (NULL);
595 *q = NULL; 1020 *q = NULL;
596 *hap = NULL; 1021 *hap = NULL;
597 return (&host); 1022 return (&host);
598} 1023}
599 1024
600struct hostent * 1025struct hostent *
601_yp_gethtbyaddr(addr, len, type) 1026_yp_gethtbyaddr(addr)
602 const char *addr; 1027 const char *addr;
603 int len, type;
604{ 1028{
605 struct hostent *hp = (struct hostent *)NULL; 1029 struct hostent *hp = (struct hostent *)NULL;
606 static char *__ypcurrent; 1030 static char *__ypcurrent;
607 int __ypcurrentlen, r; 1031 int __ypcurrentlen, r;
608 char name[sizeof("xxx.xxx.xxx.xxx") + 1]; 1032 char name[sizeof("xxx.xxx.xxx.xxx")];
609 1033
610 if (!__ypdomain) { 1034 if (!__ypdomain) {
611 if (_yp_check(&__ypdomain) == 0) 1035 if (_yp_check(&__ypdomain) == 0)
612 return (hp); 1036 return (hp);
613 } 1037 }
614 sprintf(name, "%u.%u.%u.%u", 1038 snprintf(name, sizeof name, "%u.%u.%u.%u",
615 ((unsigned)addr[0] & 0xff), 1039 ((unsigned)addr[0] & 0xff), ((unsigned)addr[1] & 0xff),
616 ((unsigned)addr[1] & 0xff), 1040 ((unsigned)addr[2] & 0xff), ((unsigned)addr[3] & 0xff));
617 ((unsigned)addr[2] & 0xff),
618 ((unsigned)addr[3] & 0xff));
619 if (__ypcurrent) 1041 if (__ypcurrent)
620 free(__ypcurrent); 1042 free(__ypcurrent);
621 __ypcurrent = NULL; 1043 __ypcurrent = NULL;
@@ -636,6 +1058,8 @@ _yp_gethtbyname(name)
636 static char *__ypcurrent; 1058 static char *__ypcurrent;
637 int __ypcurrentlen, r; 1059 int __ypcurrentlen, r;
638 1060
1061 if (strlen(name) >= MAXHOSTNAMELEN)
1062 return (NULL);
639 if (!__ypdomain) { 1063 if (!__ypdomain) {
640 if (_yp_check(&__ypdomain) == 0) 1064 if (_yp_check(&__ypdomain) == 0)
641 return (hp); 1065 return (hp);
@@ -645,10 +1069,107 @@ _yp_gethtbyname(name)
645 __ypcurrent = NULL; 1069 __ypcurrent = NULL;
646 r = yp_match(__ypdomain, "hosts.byname", name, 1070 r = yp_match(__ypdomain, "hosts.byname", name,
647 strlen(name), &__ypcurrent, &__ypcurrentlen); 1071 strlen(name), &__ypcurrent, &__ypcurrentlen);
648 if (r==0) 1072 if (r == 0)
649 hp = _yphostent(__ypcurrent); 1073 hp = _yphostent(__ypcurrent);
650 if (hp==NULL) 1074 if (hp == NULL)
651 h_errno = HOST_NOT_FOUND; 1075 h_errno = HOST_NOT_FOUND;
652 return (hp); 1076 return (hp);
653} 1077}
654#endif 1078#endif
1079
1080static void
1081map_v4v6_address(src, dst)
1082 const char *src;
1083 char *dst;
1084{
1085 u_char *p = (u_char *)dst;
1086 char tmp[INADDRSZ];
1087 int i;
1088
1089 /* Stash a temporary copy so our caller can update in place. */
1090 bcopy(src, tmp, INADDRSZ);
1091 /* Mark this ipv6 addr as a mapped ipv4. */
1092 for (i = 0; i < 10; i++)
1093 *p++ = 0x00;
1094 *p++ = 0xff;
1095 *p++ = 0xff;
1096 /* Retrieve the saved copy and we're done. */
1097 bcopy(tmp, (void*)p, INADDRSZ);
1098}
1099
1100static void
1101map_v4v6_hostent(hp, bpp, ep)
1102 struct hostent *hp;
1103 char **bpp;
1104 char *ep;
1105{
1106 char **ap;
1107
1108 if (hp->h_addrtype != AF_INET || hp->h_length != INADDRSZ)
1109 return;
1110 hp->h_addrtype = AF_INET6;
1111 hp->h_length = IN6ADDRSZ;
1112 for (ap = hp->h_addr_list; *ap; ap++) {
1113 int i = sizeof(align) - ((u_long)*bpp % sizeof(align));
1114
1115 if (ep - *bpp < (i + IN6ADDRSZ)) {
1116 /* Out of memory. Truncate address list here. XXX */
1117 *ap = NULL;
1118 return;
1119 }
1120 *bpp += i;
1121 map_v4v6_address(*ap, *bpp);
1122 *ap = *bpp;
1123 *bpp += IN6ADDRSZ;
1124 }
1125}
1126
1127struct hostent *
1128gethostent()
1129{
1130 return (_gethtent());
1131}
1132
1133#ifdef RESOLVSORT
1134static void
1135addrsort(ap, num)
1136 char **ap;
1137 int num;
1138{
1139 int i, j;
1140 char **p;
1141 short aval[MAXADDRS];
1142 int needsort = 0;
1143
1144 p = ap;
1145 for (i = 0; i < num; i++, p++) {
1146 for (j = 0 ; (unsigned)j < _res.nsort; j++)
1147 if (_res.sort_list[j].addr.s_addr ==
1148 (((struct in_addr *)(*p))->s_addr & _res.sort_list[j].mask))
1149 break;
1150 aval[i] = j;
1151 if (needsort == 0 && i > 0 && j < aval[i-1])
1152 needsort = i;
1153 }
1154 if (!needsort)
1155 return;
1156
1157 while (needsort < num) {
1158 for (j = needsort - 1; j >= 0; j--) {
1159 if (aval[j] > aval[j+1]) {
1160 char *hp;
1161
1162 i = aval[j];
1163 aval[j] = aval[j+1];
1164 aval[j+1] = i;
1165
1166 hp = ap[j];
1167 ap[j] = ap[j+1];
1168 ap[j+1] = hp;
1169 } else
1170 break;
1171 }
1172 needsort++;
1173 }
1174}
1175#endif
diff --git a/src/lib/libc/net/getifaddrs.3 b/src/lib/libc/net/getifaddrs.3
new file mode 100644
index 0000000000..2743bf6fc2
--- /dev/null
+++ b/src/lib/libc/net/getifaddrs.3
@@ -0,0 +1,159 @@
1.\" $OpenBSD: getifaddrs.3,v 1.8 2002/01/02 06:08:55 nordin 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..76c6449906
--- /dev/null
+++ b/src/lib/libc/net/getnameinfo.3
@@ -0,0 +1,297 @@
1.\" $OpenBSD: getnameinfo.3,v 1.17 2001/11/15 06:53:09 itojun 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 with
60.Xr gethostbyaddr 3
61and
62.Xr getservbyport 3
63in 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 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 numeric hostname, and service name,
191for given socket address.
192Observe that there is no hardcoded reference to 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 getaddrinfo
284function is defined 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 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..2311eba7a0
--- /dev/null
+++ b/src/lib/libc/net/getnameinfo.c
@@ -0,0 +1,361 @@
1/* $OpenBSD: getnameinfo.c,v 1.25 2002/06/27 09:24:28 itojun 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
62static const struct afd {
63 int a_af;
64 int a_addrlen;
65 int a_socklen;
66 int a_off;
67} afdl [] = {
68#ifdef INET6
69 {PF_INET6, sizeof(struct in6_addr), sizeof(struct sockaddr_in6),
70 offsetof(struct sockaddr_in6, sin6_addr)},
71#endif
72 {PF_INET, sizeof(struct in_addr), sizeof(struct sockaddr_in),
73 offsetof(struct sockaddr_in, sin_addr)},
74 {0, 0, 0},
75};
76
77struct sockinet {
78 u_char si_len;
79 u_char si_family;
80 u_short si_port;
81};
82
83#ifdef INET6
84static int ip6_parsenumeric(const struct sockaddr *, const char *, char *,
85 size_t, int);
86static int ip6_sa2str(const struct sockaddr_in6 *, char *, size_t, int);
87#endif
88
89int
90getnameinfo(sa, salen, host, hostlen, serv, servlen, flags)
91 const struct sockaddr *sa;
92 socklen_t salen;
93 char *host;
94 size_t hostlen;
95 char *serv;
96 size_t servlen;
97 int flags;
98{
99 const struct afd *afd;
100 struct servent *sp;
101 struct hostent *hp;
102 u_short port;
103 int family, i;
104 const char *addr;
105 u_int32_t v4a;
106 int h_error;
107 char numserv[512];
108 char numaddr[512];
109
110 if (sa == NULL)
111 return EAI_FAIL;
112
113 if (sa->sa_len != salen)
114 return EAI_FAIL;
115
116 family = sa->sa_family;
117 for (i = 0; afdl[i].a_af; i++)
118 if (afdl[i].a_af == family) {
119 afd = &afdl[i];
120 goto found;
121 }
122 return EAI_FAMILY;
123
124 found:
125 if (salen != afd->a_socklen)
126 return EAI_FAIL;
127
128 /* network byte order */
129 port = ((const struct sockinet *)sa)->si_port;
130 addr = (const char *)sa + afd->a_off;
131
132 if (serv == NULL || servlen == 0) {
133 /*
134 * do nothing in this case.
135 * in case you are wondering if "&&" is more correct than
136 * "||" here: rfc2553bis-03 says that serv == NULL OR
137 * servlen == 0 means that the caller does not want the result.
138 */
139 } else {
140 if (flags & NI_NUMERICSERV)
141 sp = NULL;
142 else {
143 sp = getservbyport(port,
144 (flags & NI_DGRAM) ? "udp" : "tcp");
145 }
146 if (sp) {
147 if (strlen(sp->s_name) + 1 > servlen)
148 return EAI_MEMORY;
149 strlcpy(serv, sp->s_name, servlen);
150 } else {
151 snprintf(numserv, sizeof(numserv), "%u", ntohs(port));
152 if (strlen(numserv) + 1 > servlen)
153 return EAI_MEMORY;
154 strlcpy(serv, numserv, servlen);
155 }
156 }
157
158 switch (sa->sa_family) {
159 case AF_INET:
160 v4a = (u_int32_t)
161 ntohl(((const struct sockaddr_in *)sa)->sin_addr.s_addr);
162 if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
163 flags |= NI_NUMERICHOST;
164 v4a >>= IN_CLASSA_NSHIFT;
165 if (v4a == 0)
166 flags |= NI_NUMERICHOST;
167 break;
168#ifdef INET6
169 case AF_INET6:
170 {
171 const struct sockaddr_in6 *sin6;
172 sin6 = (const struct sockaddr_in6 *)sa;
173 switch (sin6->sin6_addr.s6_addr[0]) {
174 case 0x00:
175 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr))
176 ;
177 else if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr))
178 ;
179 else
180 flags |= NI_NUMERICHOST;
181 break;
182 default:
183 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
184 flags |= NI_NUMERICHOST;
185 }
186 else if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
187 flags |= NI_NUMERICHOST;
188 break;
189 }
190 }
191 break;
192#endif
193 }
194 if (host == NULL || hostlen == 0) {
195 /*
196 * do nothing in this case.
197 * in case you are wondering if "&&" is more correct than
198 * "||" here: rfc2553bis-03 says that host == NULL or
199 * hostlen == 0 means that the caller does not want the result.
200 */
201 } else if (flags & NI_NUMERICHOST) {
202 int numaddrlen;
203
204 /* NUMERICHOST and NAMEREQD conflicts with each other */
205 if (flags & NI_NAMEREQD)
206 return EAI_NONAME;
207
208 switch(afd->a_af) {
209#ifdef INET6
210 case AF_INET6:
211 {
212 int error;
213
214 if ((error = ip6_parsenumeric(sa, addr, host,
215 hostlen, flags)) != 0)
216 return(error);
217 break;
218 }
219#endif
220 default:
221 if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
222 == NULL)
223 return EAI_SYSTEM;
224 numaddrlen = strlen(numaddr);
225 if (numaddrlen + 1 > hostlen) /* don't forget terminator */
226 return EAI_MEMORY;
227 strlcpy(host, numaddr, hostlen);
228 break;
229 }
230 } else {
231 hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af);
232 h_error = h_errno;
233
234 if (hp) {
235#if 0
236 /*
237 * commented out, since "for local host" is not
238 * implemented here - see RFC2553 p30
239 */
240 if (flags & NI_NOFQDN) {
241 char *p;
242 p = strchr(hp->h_name, '.');
243 if (p)
244 *p = '\0';
245 }
246#endif
247 if (strlen(hp->h_name) + 1 > hostlen) {
248 return EAI_MEMORY;
249 }
250 strlcpy(host, hp->h_name, hostlen);
251 } else {
252 if (flags & NI_NAMEREQD)
253 return EAI_NONAME;
254 switch(afd->a_af) {
255#ifdef INET6
256 case AF_INET6:
257 {
258 int error;
259
260 if ((error = ip6_parsenumeric(sa, addr, host,
261 hostlen,
262 flags)) != 0)
263 return(error);
264 break;
265 }
266#endif
267 default:
268 if (inet_ntop(afd->a_af, addr, host,
269 hostlen) == NULL)
270 return EAI_SYSTEM;
271 break;
272 }
273 }
274 }
275 return(0);
276}
277
278#ifdef INET6
279static int
280ip6_parsenumeric(sa, addr, host, hostlen, flags)
281 const struct sockaddr *sa;
282 const char *addr;
283 char *host;
284 size_t hostlen;
285 int flags;
286{
287 int numaddrlen;
288 char numaddr[512];
289
290 if (inet_ntop(AF_INET6, addr, numaddr, sizeof(numaddr)) == NULL)
291 return EAI_SYSTEM;
292
293 numaddrlen = strlen(numaddr);
294 if (numaddrlen + 1 > hostlen) /* don't forget terminator */
295 return EAI_MEMORY;
296 strlcpy(host, numaddr, hostlen);
297
298 if (((const struct sockaddr_in6 *)sa)->sin6_scope_id) {
299 char zonebuf[MAXHOSTNAMELEN];
300 int zonelen;
301
302 zonelen = ip6_sa2str(
303 (const struct sockaddr_in6 *)(const void *)sa,
304 zonebuf, sizeof(zonebuf), flags);
305 if (zonelen < 0)
306 return EAI_MEMORY;
307 if (zonelen + 1 + numaddrlen + 1 > hostlen)
308 return EAI_MEMORY;
309
310 /* construct <numeric-addr><delim><zoneid> */
311 memcpy(host + numaddrlen + 1, zonebuf,
312 (size_t)zonelen);
313 host[numaddrlen] = SCOPE_DELIMITER;
314 host[numaddrlen + 1 + zonelen] = '\0';
315 }
316
317 return 0;
318}
319
320/* ARGSUSED */
321static int
322ip6_sa2str(sa6, buf, bufsiz, flags)
323 const struct sockaddr_in6 *sa6;
324 char *buf;
325 size_t bufsiz;
326 int flags;
327{
328 unsigned int ifindex;
329 const struct in6_addr *a6;
330 int n;
331
332 ifindex = (unsigned int)sa6->sin6_scope_id;
333 a6 = &sa6->sin6_addr;
334
335#ifdef notdef
336 if ((flags & NI_NUMERICSCOPE) != 0) {
337 n = snprintf(buf, bufsiz, "%u", sa6->sin6_scope_id);
338 if (n < 0 || n >= bufsiz)
339 return -1;
340 else
341 return n;
342 }
343#endif
344
345 /* if_indextoname() does not take buffer size. not a good api... */
346 if ((IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6)) &&
347 bufsiz >= IF_NAMESIZE) {
348 char *p = if_indextoname(ifindex, buf);
349 if (p) {
350 return(strlen(p));
351 }
352 }
353
354 /* last resort */
355 n = snprintf(buf, bufsiz, "%u", sa6->sin6_scope_id);
356 if (n < 0 || n >= bufsiz)
357 return -1;
358 else
359 return n;
360}
361#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..abbfdbd64c
--- /dev/null
+++ b/src/lib/libc/net/getnetnamadr.c
@@ -0,0 +1,391 @@
1/* $OpenBSD: getnetnamadr.c,v 1.18 2002/08/27 08:53:13 itojun 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.18 2002/08/27 08:53:13 itojun 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
99extern int h_errno;
100
101struct netent *_getnetbyaddr(in_addr_t net, int type);
102struct netent *_getnetbyname(const char *name);
103
104int _hokchar(const char *);
105
106#define BYADDR 0
107#define BYNAME 1
108#define MAXALIASES 35
109
110#define MAXPACKET (64*1024)
111
112typedef union {
113 HEADER hdr;
114 u_char buf[MAXPACKET];
115} querybuf;
116
117typedef union {
118 long al;
119 char ac;
120} align;
121
122static struct netent *
123getnetanswer(answer, anslen, net_i)
124 querybuf *answer;
125 int anslen;
126 int net_i;
127{
128
129 register HEADER *hp;
130 register u_char *cp;
131 register int n;
132 u_char *eom;
133 int type, class, ancount, qdcount, haveanswer, i, nchar;
134 char aux1[MAXHOSTNAMELEN], aux2[MAXHOSTNAMELEN], ans[MAXHOSTNAMELEN];
135 char *in, *st, *pauxt, *bp, **ap, *ep;
136 char *paux1 = &aux1[0], *paux2 = &aux2[0], flag = 0;
137 static struct netent net_entry;
138 static char *net_aliases[MAXALIASES], netbuf[BUFSIZ+1];
139
140 /*
141 * find first satisfactory answer
142 *
143 * answer --> +------------+ ( MESSAGE )
144 * | Header |
145 * +------------+
146 * | Question | the question for the name server
147 * +------------+
148 * | Answer | RRs answering the question
149 * +------------+
150 * | Authority | RRs pointing toward an authority
151 * | Additional | RRs holding additional information
152 * +------------+
153 */
154 eom = answer->buf + anslen;
155 hp = &answer->hdr;
156 ancount = ntohs(hp->ancount); /* #/records in the answer section */
157 qdcount = ntohs(hp->qdcount); /* #/entries in the question section */
158 bp = netbuf;
159 ep = netbuf + sizeof(netbuf);
160 cp = answer->buf + HFIXEDSZ;
161 if (!qdcount) {
162 if (hp->aa)
163 h_errno = HOST_NOT_FOUND;
164 else
165 h_errno = TRY_AGAIN;
166 return (NULL);
167 }
168 while (qdcount-- > 0)
169 cp += __dn_skipname(cp, eom) + QFIXEDSZ;
170 ap = net_aliases;
171 *ap = NULL;
172 net_entry.n_aliases = net_aliases;
173 haveanswer = 0;
174 while (--ancount >= 0 && cp < eom) {
175 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
176#ifdef USE_RESOLV_NAME_OK
177 if ((n < 0) || !res_dnok(bp))
178#else
179 if ((n < 0) || !_hokchar(bp))
180#endif
181 break;
182 cp += n;
183 ans[0] = '\0';
184 strlcpy(&ans[0], bp, sizeof ans);
185 GETSHORT(type, cp);
186 GETSHORT(class, cp);
187 cp += INT32SZ; /* TTL */
188 GETSHORT(n, cp);
189 if (class == C_IN && type == T_PTR) {
190 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
191#ifdef USE_RESOLV_NAME_OK
192 if ((n < 0) || !res_hnok(bp))
193#else
194 if ((n < 0) || !_hokchar(bp))
195#endif
196 {
197 cp += n;
198 return (NULL);
199 }
200 cp += n;
201 *ap++ = bp;
202 bp += strlen(bp) + 1;
203 net_entry.n_addrtype =
204 (class == C_IN) ? AF_INET : AF_UNSPEC;
205 haveanswer++;
206 }
207 }
208 if (haveanswer) {
209 *ap = NULL;
210 switch (net_i) {
211 case BYADDR:
212 net_entry.n_name = *net_entry.n_aliases;
213 net_entry.n_net = 0L;
214 break;
215 case BYNAME:
216 in = *net_entry.n_aliases;
217 net_entry.n_name = &ans[0];
218 aux2[0] = '\0';
219 for (i = 0; i < 4; i++) {
220 for (st = in, nchar = 0;
221 *st != '.';
222 st++, nchar++)
223 ;
224 if (nchar != 1 || *in != '0' || flag) {
225 flag = 1;
226 strlcpy(paux1,
227 (i==0) ? in : in-1,
228 (i==0) ? nchar+1 : nchar+2);
229 pauxt = paux2;
230 paux2 = strcat(paux1, paux2);
231 paux1 = pauxt;
232 }
233 in = ++st;
234 }
235 net_entry.n_net = inet_network(paux2);
236 break;
237 }
238 net_entry.n_aliases++;
239 return (&net_entry);
240 }
241 h_errno = TRY_AGAIN;
242 return (NULL);
243}
244
245struct netent *
246getnetbyaddr(net, net_type)
247 register in_addr_t net;
248 register int net_type;
249{
250 unsigned int netbr[4];
251 int nn, anslen;
252 querybuf *buf;
253 char qbuf[MAXDNAME];
254 in_addr_t net2;
255 struct netent *net_entry = NULL;
256 char lookups[MAXDNSLUS];
257 int i;
258
259 if ((_res.options & RES_INIT) == 0 && res_init() == -1)
260 return(_getnetbyaddr(net, net_type));
261
262 bcopy(_res.lookups, lookups, sizeof lookups);
263 if (lookups[0] == '\0')
264 strlcpy(lookups, "bf", sizeof lookups);
265
266 for (i = 0; i < MAXDNSLUS && lookups[i]; i++) {
267 switch (lookups[i]) {
268#ifdef YP
269 case 'y':
270 /* There is no YP support. */
271 break;
272#endif /* YP */
273 case 'b':
274 if (net_type != AF_INET)
275 break; /* DNS only supports AF_INET? */
276
277 for (nn = 4, net2 = net; net2; net2 >>= 8)
278 netbr[--nn] = net2 & 0xff;
279 switch (nn) {
280 case 3: /* Class A */
281 snprintf(qbuf, sizeof(qbuf),
282 "0.0.0.%u.in-addr.arpa", netbr[3]);
283 break;
284 case 2: /* Class B */
285 snprintf(qbuf, sizeof(qbuf),
286 "0.0.%u.%u.in-addr.arpa",
287 netbr[3], netbr[2]);
288 break;
289 case 1: /* Class C */
290 snprintf(qbuf, sizeof(qbuf),
291 "0.%u.%u.%u.in-addr.arpa",
292 netbr[3], netbr[2], netbr[1]);
293 break;
294 case 0: /* Class D - E */
295 snprintf(qbuf, sizeof(qbuf),
296 "%u.%u.%u.%u.in-addr.arpa",
297 netbr[3], netbr[2], netbr[1], netbr[0]);
298 break;
299 }
300 buf = malloc(sizeof(*buf));
301 if (buf == NULL)
302 break;
303 anslen = res_query(qbuf, C_IN, T_PTR, buf->buf,
304 sizeof(buf->buf));
305 if (anslen < 0) {
306 free(buf);
307#ifdef DEBUG
308 if (_res.options & RES_DEBUG)
309 printf("res_query failed\n");
310#endif
311 break;
312 }
313 net_entry = getnetanswer(buf, anslen, BYADDR);
314 free(buf);
315 if (net_entry != NULL) {
316 unsigned u_net = net; /* maybe net should be unsigned ? */
317
318 /* Strip trailing zeros */
319 while ((u_net & 0xff) == 0 && u_net != 0)
320 u_net >>= 8;
321 net_entry->n_net = u_net;
322 return (net_entry);
323 }
324 break;
325 case 'f':
326 net_entry = _getnetbyaddr(net, net_type);
327 if (net_entry != NULL)
328 return (net_entry);
329 }
330 }
331
332 /* Nothing matched. */
333 return (NULL);
334}
335
336struct netent *
337getnetbyname(net)
338 register const char *net;
339{
340 int anslen;
341 querybuf *buf;
342 char qbuf[MAXDNAME];
343 struct netent *net_entry = NULL;
344 char lookups[MAXDNSLUS];
345 int i;
346
347 if ((_res.options & RES_INIT) == 0 && res_init() == -1)
348 return (_getnetbyname(net));
349
350 bcopy(_res.lookups, lookups, sizeof lookups);
351 if (lookups[0] == '\0')
352 strlcpy(lookups, "bf", sizeof lookups);
353
354 for (i = 0; i < MAXDNSLUS && lookups[i]; i++) {
355 switch (lookups[i]) {
356#ifdef YP
357 case 'y':
358 /* There is no YP support. */
359 break;
360#endif /* YP */
361 case 'b':
362 strlcpy(qbuf, net, sizeof qbuf);
363 buf = malloc(sizeof(*buf));
364 if (buf == NULL)
365 break;
366 anslen = res_search(qbuf, C_IN, T_PTR, buf->buf,
367 sizeof(buf->buf));
368 if (anslen < 0) {
369 free(buf);
370#ifdef DEBUG
371 if (_res.options & RES_DEBUG)
372 printf("res_query failed\n");
373#endif
374 break;
375 }
376 net_entry = getnetanswer(buf, anslen, BYNAME);
377 free(buf);
378 if (net_entry != NULL)
379 return (net_entry);
380 break;
381 case 'f':
382 net_entry = _getnetbyname(net);
383 if (net_entry != NULL)
384 return (net_entry);
385 break;
386 }
387 }
388
389 /* Nothing matched. */
390 return (NULL);
391}
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..50cadfd372
--- /dev/null
+++ b/src/lib/libc/net/getrrsetbyname.3
@@ -0,0 +1,166 @@
1.\" $OpenBSD: getrrsetbyname.3,v 1.7 2002/06/09 05:03:59 deraadt 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 Oct 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
105u lib/libc/sys/lseek.2
106structure.
107Memory allocated for the dynamically allocated structures created by
108a successful call to
109.Fn getrrsetbyname
110is released by
111.Fn freerrset .
112.Li rrset
113is a pointer to a
114.Li struct rrset
115created by a call to
116.Fn getrrsetbyname .
117.Pp
118If the EDNS0 option is activated in
119.Xr resolv.conf 3 ,
120.Fn getrrsetbyname
121will request DNSSEC authentication using the EDNS0 DNSSEC OK (DO) bit.
122.Sh "RETURN VALUES"
123.Fn getrrsetbyname
124returns zero on success, and one of the following error
125codes if an error occurred:
126.Pp
127.Bl -tag -width ERRSET_NOMEMORY -compact
128.It Dv ERRSET_NONAME
129the name does not exist
130.It Dv ERRSET_NODATA
131the name exists, but does not have data of the desired type
132.It Dv ERRSET_NOMEMORY
133memory could not be allocated
134.It Dv ERRSET_INVAL
135a parameter is invalid
136.It Dv ERRSET_FAIL
137other failure
138.El
139.Sh SEE ALSO
140.Xr resolver 3 ,
141.Xr resolv.conf 5 ,
142.Xr named 8
143.Sh AUTHORS
144Jakob Schlyter
145.Aq jakob@openbsd.org
146.Sh HISTORY
147.Fn getrrsetbyname
148first appeared in
149.Ox 3.0 .
150The API first appeared in ISC BIND version 9.
151.Sh BUGS
152The data in
153.Li *rdi_data
154should be returned in uncompressed wire format.
155Currently, the data is in compressed format and the caller can't
156uncompress since it doesn't have the full message.
157.Sh CAVEATS
158The
159.Dv RRSET_VALIDATED
160flag in
161.Li rri_flags
162is set if the AD (autenticated data) bit in the DNS answer is
163set. This 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..1ec60486b3
--- /dev/null
+++ b/src/lib/libc/net/getrrsetbyname.c
@@ -0,0 +1,508 @@
1/* $OpenBSD: getrrsetbyname.c,v 1.5 2002/09/07 20:54:04 jakob 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#define ANSWER_BUFFER_SIZE 1024*64
55
56struct dns_query {
57 char *name;
58 u_int16_t type;
59 u_int16_t class;
60 struct dns_query *next;
61};
62
63struct dns_rr {
64 char *name;
65 u_int16_t type;
66 u_int16_t class;
67 u_int16_t ttl;
68 u_int16_t size;
69 void *rdata;
70 struct dns_rr *next;
71};
72
73struct dns_response {
74 HEADER header;
75 struct dns_query *query;
76 struct dns_rr *answer;
77 struct dns_rr *authority;
78 struct dns_rr *additional;
79};
80
81static struct dns_response *parse_dns_response(const u_char *, int);
82static struct dns_query *parse_dns_qsection(const u_char *, int,
83 const u_char **, int);
84static struct dns_rr *parse_dns_rrsection(const u_char *, int, const u_char **,
85 int);
86
87static void free_dns_query(struct dns_query *);
88static void free_dns_rr(struct dns_rr *);
89static void free_dns_response(struct dns_response *);
90
91static int count_dns_rr(struct dns_rr *, u_int16_t, u_int16_t);
92
93int
94getrrsetbyname(const char *hostname, unsigned int rdclass,
95 unsigned int rdtype, unsigned int flags,
96 struct rrsetinfo **res)
97{
98 int result;
99 struct rrsetinfo *rrset = NULL;
100 struct dns_response *response;
101 struct dns_rr *rr;
102 struct rdatainfo *rdata;
103 unsigned int length, index_ans, index_sig;
104 u_char answer[ANSWER_BUFFER_SIZE];
105
106 /* check for invalid class and type */
107 if (rdclass > 0xffff || rdtype > 0xffff) {
108 result = ERRSET_INVAL;
109 goto fail;
110 }
111
112 /* don't allow queries of class or type ANY */
113 if (rdclass == 0xff || rdtype == 0xff) {
114 result = ERRSET_INVAL;
115 goto fail;
116 }
117
118 /* don't allow flags yet, unimplemented */
119 if (flags) {
120 result = ERRSET_INVAL;
121 goto fail;
122 }
123
124 /* initialize resolver */
125 if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
126 result = ERRSET_FAIL;
127 goto fail;
128 }
129
130#ifdef DEBUG
131 _res.options |= RES_DEBUG;
132#endif /* DEBUG */
133
134#ifdef RES_USE_DNSSEC
135 /* turn on DNSSEC if EDNS0 is configured */
136 if (_res.options & RES_USE_EDNS0)
137 _res.options |= RES_USE_DNSSEC;
138#endif /* RES_USE_DNSEC */
139
140 /* make query */
141 length = res_query(hostname, (signed int) rdclass, (signed int) rdtype,
142 answer, sizeof(answer));
143 if (length < 0) {
144 switch(h_errno) {
145 case HOST_NOT_FOUND:
146 result = ERRSET_NONAME;
147 goto fail;
148 case NO_DATA:
149 result = ERRSET_NODATA;
150 goto fail;
151 default:
152 result = ERRSET_FAIL;
153 goto fail;
154 }
155 }
156
157 /* parse result */
158 response = parse_dns_response(answer, length);
159 if (response == NULL) {
160 result = ERRSET_FAIL;
161 goto fail;
162 }
163
164 if (response->header.qdcount != 1) {
165 result = ERRSET_FAIL;
166 goto fail;
167 }
168
169 /* initialize rrset */
170 rrset = calloc(1, sizeof(struct rrsetinfo));
171 if (rrset == NULL) {
172 result = ERRSET_NOMEMORY;
173 goto fail;
174 }
175 rrset->rri_rdclass = response->query->class;
176 rrset->rri_rdtype = response->query->type;
177 rrset->rri_ttl = response->answer->ttl;
178 rrset->rri_nrdatas = response->header.ancount;
179
180 /* check for authenticated data */
181 if (response->header.ad == 1)
182 rrset->rri_flags |= RRSET_VALIDATED;
183
184 /* copy name from answer section */
185 length = strlen(response->answer->name);
186 rrset->rri_name = malloc(length + 1);
187 if (rrset->rri_name == NULL) {
188 result = ERRSET_NOMEMORY;
189 goto fail;
190 }
191 strlcpy(rrset->rri_name, response->answer->name, length + 1);
192
193 /* count answers */
194 rrset->rri_nrdatas = count_dns_rr(response->answer, rrset->rri_rdclass,
195 rrset->rri_rdtype);
196 rrset->rri_nsigs = count_dns_rr(response->answer, rrset->rri_rdclass,
197 T_SIG);
198
199 /* allocate memory for answers */
200 rrset->rri_rdatas = calloc(rrset->rri_nrdatas,
201 sizeof(struct rdatainfo));
202 if (rrset->rri_rdatas == NULL) {
203 result = ERRSET_NOMEMORY;
204 goto fail;
205 }
206
207 /* allocate memory for signatures */
208 rrset->rri_sigs = calloc(rrset->rri_nsigs, sizeof(struct rdatainfo));
209 if (rrset->rri_sigs == NULL) {
210 result = ERRSET_NOMEMORY;
211 goto fail;
212 }
213
214 /* copy answers & signatures */
215 for (rr = response->answer, index_ans = 0, index_sig = 0;
216 rr; rr = rr->next) {
217
218 rdata = NULL;
219
220 if (rr->class == rrset->rri_rdclass &&
221 rr->type == rrset->rri_rdtype)
222 rdata = &rrset->rri_rdatas[index_ans++];
223
224 if (rr->class == rrset->rri_rdclass &&
225 rr->type == T_SIG)
226 rdata = &rrset->rri_sigs[index_sig++];
227
228 if (rdata) {
229 rdata->rdi_length = rr->size;
230 rdata->rdi_data = malloc(rr->size);
231
232 if (rdata->rdi_data == NULL) {
233 result = ERRSET_NOMEMORY;
234 goto fail;
235 }
236 memcpy(rdata->rdi_data, rr->rdata, rr->size);
237 }
238 }
239
240 *res = rrset;
241 return (ERRSET_SUCCESS);
242
243fail:
244 if (rrset != NULL)
245 freerrset(rrset);
246 return (result);
247}
248
249void
250freerrset(struct rrsetinfo *rrset)
251{
252 u_int16_t i;
253
254 if (rrset == NULL)
255 return;
256
257 if (rrset->rri_rdatas) {
258 for (i = 0; i < rrset->rri_nrdatas; i++) {
259 if (rrset->rri_rdatas[i].rdi_data == NULL)
260 break;
261 free(rrset->rri_rdatas[i].rdi_data);
262 }
263 free(rrset->rri_rdatas);
264 }
265
266 if (rrset->rri_sigs) {
267 for (i = 0; i < rrset->rri_nsigs; i++) {
268 if (rrset->rri_sigs[i].rdi_data == NULL)
269 break;
270 free(rrset->rri_sigs[i].rdi_data);
271 }
272 free(rrset->rri_sigs);
273 }
274
275 if (rrset->rri_name)
276 free(rrset->rri_name);
277 free(rrset);
278}
279
280/*
281 * DNS response parsing routines
282 */
283static struct dns_response *
284parse_dns_response(const u_char *answer, int size)
285{
286 struct dns_response *resp;
287 const u_char *cp;
288
289 /* allocate memory for the response */
290 resp = calloc(1, sizeof(*resp));
291 if (resp == NULL)
292 return (NULL);
293
294 /* initialize current pointer */
295 cp = answer;
296
297 /* copy header */
298 memcpy(&resp->header, cp, HFIXEDSZ);
299 cp += HFIXEDSZ;
300
301 /* fix header byte order */
302 resp->header.qdcount = ntohs(resp->header.qdcount);
303 resp->header.ancount = ntohs(resp->header.ancount);
304 resp->header.nscount = ntohs(resp->header.nscount);
305 resp->header.arcount = ntohs(resp->header.arcount);
306
307 /* there must be at least one query */
308 if (resp->header.qdcount < 1) {
309 free_dns_response(resp);
310 return (NULL);
311 }
312
313 /* parse query section */
314 resp->query = parse_dns_qsection(answer, size, &cp,
315 resp->header.qdcount);
316 if (resp->header.qdcount && resp->query == NULL) {
317 free_dns_response(resp);
318 return (NULL);
319 }
320
321 /* parse answer section */
322 resp->answer = parse_dns_rrsection(answer, size, &cp,
323 resp->header.ancount);
324 if (resp->header.ancount && resp->answer == NULL) {
325 free_dns_response(resp);
326 return (NULL);
327 }
328
329 /* parse authority section */
330 resp->authority = parse_dns_rrsection(answer, size, &cp,
331 resp->header.nscount);
332 if (resp->header.nscount && resp->authority == NULL) {
333 free_dns_response(resp);
334 return (NULL);
335 }
336
337 /* parse additional section */
338 resp->additional = parse_dns_rrsection(answer, size, &cp,
339 resp->header.arcount);
340 if (resp->header.arcount && resp->additional == NULL) {
341 free_dns_response(resp);
342 return (NULL);
343 }
344
345 return (resp);
346}
347
348static struct dns_query *
349parse_dns_qsection(const u_char *answer, int size, const u_char **cp, int count)
350{
351 struct dns_query *head, *curr, *prev;
352 int i, length;
353 char name[MAXDNAME];
354
355 for (i = 1, head = NULL, prev = NULL; i <= count; i++, prev = curr) {
356
357 /* allocate and initialize struct */
358 curr = calloc(1, sizeof(struct dns_query));
359 if (curr == NULL) {
360 free_dns_query(head);
361 return (NULL);
362 }
363 if (head == NULL)
364 head = curr;
365 if (prev != NULL)
366 prev->next = curr;
367
368 /* name */
369 length = dn_expand(answer, answer + size, *cp, name,
370 sizeof(name));
371 if (length < 0) {
372 free_dns_query(head);
373 return (NULL);
374 }
375 curr->name = strdup(name);
376 if (curr->name == NULL) {
377 free_dns_query(head);
378 return (NULL);
379 }
380 *cp += length;
381
382 /* type */
383 curr->type = _getshort(*cp);
384 *cp += INT16SZ;
385
386 /* class */
387 curr->class = _getshort(*cp);
388 *cp += INT16SZ;
389 }
390
391 return (head);
392}
393
394static struct dns_rr *
395parse_dns_rrsection(const u_char *answer, int size, const u_char **cp, int count)
396{
397 struct dns_rr *head, *curr, *prev;
398 int i, length;
399 char name[MAXDNAME];
400
401 for (i = 1, head = NULL, prev = NULL; i <= count; i++, prev = curr) {
402
403 /* allocate and initialize struct */
404 curr = calloc(1, sizeof(struct dns_rr));
405 if (curr == NULL) {
406 free_dns_rr(head);
407 return (NULL);
408 }
409 if (head == NULL)
410 head = curr;
411 if (prev != NULL)
412 prev->next = curr;
413
414 /* name */
415 length = dn_expand(answer, answer + size, *cp, name,
416 sizeof(name));
417 if (length < 0) {
418 free_dns_rr(head);
419 return (NULL);
420 }
421 curr->name = strdup(name);
422 if (curr->name == NULL) {
423 free_dns_rr(head);
424 return (NULL);
425 }
426 *cp += length;
427
428 /* type */
429 curr->type = _getshort(*cp);
430 *cp += INT16SZ;
431
432 /* class */
433 curr->class = _getshort(*cp);
434 *cp += INT16SZ;
435
436 /* ttl */
437 curr->ttl = _getlong(*cp);
438 *cp += INT32SZ;
439
440 /* rdata size */
441 curr->size = _getshort(*cp);
442 *cp += INT16SZ;
443
444 /* rdata itself */
445 curr->rdata = malloc(curr->size);
446 if (curr->rdata == NULL) {
447 free_dns_rr(head);
448 return (NULL);
449 }
450 memcpy(curr->rdata, *cp, curr->size);
451 *cp += curr->size;
452 }
453
454 return (head);
455}
456
457static void
458free_dns_query(struct dns_query *p)
459{
460 if (p == NULL)
461 return;
462
463 if (p->name)
464 free(p->name);
465 free_dns_query(p->next);
466 free(p);
467}
468
469static void
470free_dns_rr(struct dns_rr *p)
471{
472 if (p == NULL)
473 return;
474
475 if (p->name)
476 free(p->name);
477 if (p->rdata)
478 free(p->rdata);
479 free_dns_rr(p->next);
480 free(p);
481}
482
483static void
484free_dns_response(struct dns_response *p)
485{
486 if (p == NULL)
487 return;
488
489 free_dns_query(p->query);
490 free_dns_rr(p->answer);
491 free_dns_rr(p->authority);
492 free_dns_rr(p->additional);
493 free(p);
494}
495
496static int
497count_dns_rr(struct dns_rr *p, u_int16_t class, u_int16_t type)
498{
499 int n = 0;
500
501 while(p) {
502 if (p->class == class && p->type == type)
503 n++;
504 p = p->next;
505 }
506
507 return (n);
508}
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..62f526c09d 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.13 2001/02/17 23:13:26 pjanzen 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,42 @@
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
49.Fd #include <sys/socket.h> 52.Fd #include <sys/socket.h>
50.Fd #include <netinet/in.h> 53.Fd #include <netinet/in.h>
51.Fd #include <arpa/inet.h> 54.Fd #include <arpa/inet.h>
52.Ft int 55.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" 56.Fn inet_addr "const char *cp"
56.Ft unsigned long 57.Ft int
58.Fn inet_aton "const char *cp" "struct in_addr *addr"
59.Ft in_addr_t
60.Fn inet_lnaof "struct in_addr in"
61.Ft struct in_addr
62.Fn inet_makeaddr "unsigned long net" "unsigned long lna"
63.Ft in_addr_t
64.Fn inet_netof "struct in_addr in"
65.Ft in_addr_t
57.Fn inet_network "const char *cp" 66.Fn inet_network "const char *cp"
58.Ft char * 67.Ft char *
59.Fn inet_ntoa "struct in_addr in" 68.Fn inet_ntoa "struct in_addr in"
60.Ft struct in_addr 69.Ft const char *
61.Fn inet_makeaddr "int net" "int lna" 70.Fn inet_ntop "int af" "const void *src" "char *dst" "size_t size"
62.Ft unsigned long 71.Ft int
63.Fn inet_lnaof "struct in_addr in" 72.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 73.Sh DESCRIPTION
67The routines 74The routines
68.Fn inet_aton , 75.Fn inet_aton ,
@@ -74,11 +81,26 @@ numbers expressed in the Internet standard
74.Ql \&. 81.Ql \&.
75notation. 82notation.
76The 83The
84.Fn inet_pton
85function converts a presentation format address (that is, printable form
86as held in a character string) to network format (usually a
87.Li struct in_addr
88or some other internal binary representation, in network byte order).
89It returns 1 if the address was valid for the specified address family, or
900 if the address wasn't parseable in the specified address family, or \-1
91if some system error occurred (in which case
92.Va errno
93will have been set).
94This function is presently valid for
95.Dv AF_INET
96and
97.Dv AF_INET6 .
98The
77.Fn inet_aton 99.Fn inet_aton
78routine interprets the specified character string as an Internet address, 100routine interprets the specified character string as an Internet address,
79placing the address into the structure provided. 101placing the address into the structure provided.
80It returns 1 if the string was successfully interpreted, 102It returns 1 if the string was successfully interpreted,
81or 0 if the string is invalid. 103or 0 if the string was invalid.
82The 104The
83.Fn inet_addr 105.Fn inet_addr
84and 106and
@@ -86,17 +108,32 @@ and
86functions return numbers suitable for use 108functions return numbers suitable for use
87as Internet addresses and Internet network 109as Internet addresses and Internet network
88numbers, respectively. 110numbers, respectively.
111.Pp
112The function
113.Fn inet_ntop
114converts an address from network format (usually a
115.Li struct in_addr
116or some other binary form, in network byte order) to presentation format
117(suitable for external display purposes).
118It returns
119.Dv NULL
120if a system
121error occurs (in which case,
122.Va errno
123will have been set), or it returns a pointer to the destination string.
89The routine 124The routine
90.Fn inet_ntoa 125.Fn inet_ntoa
91takes an Internet address and returns an 126takes an Internet address and returns an
92.Tn ASCII 127.Tn ASCII
93string representing the address in 128string representing the address in
94.Ql \&. 129.Ql \&.
95notation. The routine 130notation.
131The routine
96.Fn inet_makeaddr 132.Fn inet_makeaddr
97takes an Internet network number and a local 133takes an Internet network number and a local
98network address and constructs an Internet address 134network address and constructs an Internet address
99from it. The routines 135from it.
136The routines
100.Fn inet_netof 137.Fn inet_netof
101and 138and
102.Fn inet_lnaof 139.Fn inet_lnaof
@@ -108,7 +145,7 @@ All Internet addresses are returned in network
108order (bytes ordered from left to right). 145order (bytes ordered from left to right).
109All network numbers and local address parts are 146All network numbers and local address parts are
110returned as machine format integer values. 147returned as machine format integer values.
111.Sh INTERNET ADDRESSES 148.Sh INTERNET ADDRESSES (IP VERSION 4)
112Values specified using the 149Values specified using the
113.Ql \&. 150.Ql \&.
114notation take one 151notation take one
@@ -122,28 +159,27 @@ a
122.Pp 159.Pp
123When four parts are specified, each is interpreted 160When four parts are specified, each is interpreted
124as a byte of data and assigned, from left to right, 161as a byte of data and assigned, from left to right,
125to the four bytes of an Internet address. Note 162to the four bytes of an Internet address.
126that when an Internet address is viewed as a 32-bit 163Note that when an Internet address is viewed as a 32-bit
127integer quantity on the 164integer quantity on a system that uses little-endian
128.Tn VAX 165byte order (such as the
129the bytes referred to 166.Tn Intel 386, 486
130above appear as 167and
168.Tn Pentium
169processors) the bytes referred to above appear as
131.Dq Li d.c.b.a . 170.Dq Li d.c.b.a .
132That is, 171That is, little-endian bytes are ordered from right to left.
133.Tn VAX
134bytes are
135ordered from right to left.
136.Pp 172.Pp
137When a three part address is specified, the last 173When a three part address is specified, the last
138part is interpreted as a 16-bit quantity and placed 174part is interpreted as a 16-bit quantity and placed
139in the right-most two bytes of the network address. 175in the rightmost two bytes of the network address.
140This makes the three part address format convenient 176This makes the three part address format convenient
141for specifying Class B network addresses as 177for specifying Class B network addresses as
142.Dq Li 128.net.host . 178.Dq Li 128.net.host .
143.Pp 179.Pp
144When a two part address is supplied, the last part 180When a two part address is supplied, the last part
145is interpreted as a 24-bit quantity and placed in 181is interpreted as a 24-bit quantity and placed in
146the right most three bytes of the network address. 182the rightmost three bytes of the network address.
147This makes the two part address format convenient 183This makes the two part address format convenient
148for specifying Class A network addresses as 184for specifying Class A network addresses as
149.Dq Li net.host . 185.Dq Li net.host .
@@ -155,12 +191,90 @@ rearrangement.
155All numbers supplied as 191All numbers supplied as
156.Dq parts 192.Dq parts
157in a 193in a
158.Ql \&. 194.Ql \&.
159notation 195notation
160may be decimal, octal, or hexadecimal, as specified 196may be decimal, octal, or hexadecimal, as specified
161in the C language (i.e., a leading 0x or 0X implies 197in the C language (i.e., a leading 0x or 0X implies
162hexadecimal; otherwise, a leading 0 implies octal; 198hexadecimal; otherwise, a leading 0 implies octal;
163otherwise, the number is interpreted as decimal). 199otherwise, the number is interpreted as decimal).
200.Sh INTERNET ADDRESSES (IP VERSION 6)
201In order to support scoped IPv6 addresses,
202.Xr getaddrinfo 3
203and
204.Xr getnameinfo 3
205are recommended rather than the functions presented here.
206.Pp
207The presentation format of an IPv6 address is given in [RFC1884 2.2]:
208.Pp
209There are three conventional forms for representing IPv6 addresses as
210text strings:
211.Bl -enum
212.It
213The preferred form is x:x:x:x:x:x:x:x, where the 'x's are the
214hexadecimal values of the eight 16-bit pieces of the address.
215Examples:
216.Bd -literal -offset indent
217FEDC:BA98:7654:3210:FEDC:BA98:7654:3210
2181080:0:0:0:8:800:200C:417A
219.Ed
220.Pp
221Note that it is not necessary to write the leading zeros in an
222individual field, but there must be at least one numeral in
223every field (except for the case described in 2.).
224.It
225Due to the method of allocating certain styles of IPv6
226addresses, it will be common for addresses to contain long
227strings of zero bits.
228In order to make writing addresses
229.Pp
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 conforms 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..73419d5239
--- /dev/null
+++ b/src/lib/libc/net/inet6_option_space.3
@@ -0,0 +1,452 @@
1.\" $OpenBSD: inet6_option_space.3,v 1.8 2001/06/23 05:57:04 deraadt 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 constranints, 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 Li 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.Po
251The
252.Fn inet6_option_append
253function does not need a data length argument
254since the option data length must already be stored by the caller.
255.Pc
256.Pp
257.Fa multx
258is the value
259.Li x
260in the alignment term
261.Dq Li xn + y .
262It must have a value of
263.Li 1 ,
264.Li 2 ,
265.Li 4 ,
266or
267.Li 8 .
268.Pp
269.Fa plusy
270is the value
271.Li y
272in the alignment term
273.Dq Li xn + y .
274It must have a value between
275.Li 0
276and
277.Li 7 ,
278inclusive.
279.\"
280.Ss inet6_option_next
281This function processes the next Hop-by-Hop option or Destination
282option in an ancillary data object.
283If another option remains to be
284processed, the return value of the function is
285.Li 0
286and
287.Fa *tptrp
288points to
289the 8-bit option type field
290.Po
291which is followed by the 8-bit option
292data length, followed by the option data
293.Pc .
294If no more options remain
295to be processed, the return value is
296.Li -1
297and
298.Fa *tptrp
299is
300.Dv NULL .
301If an error occurs, the return value is
302.Li -1
303and
304.Fa *tptrp
305is not
306.Dv NULL .
307.Pp
308.Fa cmsg
309is a pointer to
310.Li cmsghdr
311structure of which
312.Li cmsg_level
313equals
314.Dv IPPROTO_IPV6
315and
316.Li cmsg_type
317equals either
318.Dv IPV6_HOPOPTS
319or
320.Dv IPV6_DSTOPTS .
321.Pp
322.Fa tptrp
323is a pointer to a pointer to an 8-bit byte and
324.Fa *tptrp
325is used
326by the function to remember its place in the ancillary data object
327each time the function is called.
328The first time this function is
329called for a given ancillary data object,
330.Fa *tptrp
331must be set to
332.Dv NULL .
333.Pp
334Each time this function returns success,
335.Fa *tptrp
336points to the 8-bit
337option type field for the next option to be processed.
338.\"
339.Ss inet6_option_find
340This function is similar to the previously described
341.Fn inet6_option_next
342function, except this function lets the caller
343specify the option type to be searched for, instead of always
344returning the next option in the ancillary data object.
345.Fa cmsg
346is a
347pointer to
348.Li cmsghdr
349structure of which
350.Li cmsg_level
351equals
352.Dv IPPROTO_IPV6
353and
354.Li cmsg_type
355equals either
356.Dv IPV6_HOPOPTS
357or
358.Dv IPV6_DSTOPTS .
359.Pp
360.Fa tptrp
361is a pointer to a pointer to an 8-bit byte and
362.Fa *tptrp
363is used
364by the function to remember its place in the ancillary data object
365each time the function is called.
366The first time this function is
367called for a given ancillary data object,
368.Fa *tptrp
369must be set to
370.Dv NULL .
371.Pa
372This function starts searching for an option of the specified type
373beginning after the value of
374.Fa *tptrp .
375If an option of the specified
376type is located, this function returns
377.Li 0
378and
379.Fa *tptrp
380points to the 8-
381bit option type field for the option of the specified type.
382If an
383option of the specified type is not located, the return value is
384.Li -1
385and
386.Fa *tptrp
387is
388.Dv NULL .
389If an error occurs, the return value is
390.Li -1
391and
392.Fa *tptrp
393is not
394.Dv NULL .
395.\"
396.Sh DIAGNOSTICS
397.Fn inet6_option_init
398and
399.Fn inet6_option_append
400return
401.Li 0
402on success or
403.Li -1
404on an error.
405.Pp
406.Fn inet6_option_alloc
407returns
408.Dv NULL
409on an error.
410.Pp
411On errors,
412.Fn inet6_option_next
413and
414.Fn inet6_option_find
415return
416.Li -1
417setting
418.Fa *tptrp
419to non
420.Dv NULL
421value.
422.\"
423.Sh EXAMPLES
424RFC2292 gives comprehensive examples in chapter 6.
425.\"
426.Sh SEE ALSO
427.Rs
428.%A W. Stevens
429.%A M. Thomas
430.%T "Advanced Sockets API for IPv6"
431.%N RFC2292
432.%D February 1998
433.Re
434.Rs
435.%A S. Deering
436.%A R. Hinden
437.%T "Internet Protocol, Version 6 (IPv6) Specification"
438.%N RFC2460
439.%D December 1998
440.Re
441.\"
442.Sh HISTORY
443The implementation first appeared in KAME advanced networking kit.
444.\"
445.Sh STANDARDS
446The functions
447are documented in
448.Dq Advanced Sockets API for IPv6
449.Pq RFC2292 .
450.\"
451.Sh BUGS
452The 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..cafe0d2645
--- /dev/null
+++ b/src/lib/libc/net/inet6_rthdr_space.3
@@ -0,0 +1,325 @@
1.\" $OpenBSD: inet6_rthdr_space.3,v 1.8 2001/06/23 05:57:04 deraadt 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 Li 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.Po
238which must have a value between 1 and the value returned by
239.Fn inet6_rthdr_segments
240.Pc
241in the Routing header described by
242.Fa cmsg .
243An
244application should first call
245.Fn inet6_rthdr_segments
246to obtain the number of segments in the Routing header.
247.Pp
248Upon an error the return value of the function is
249.Dv NULL .
250.\"
251.Ss inet6_rthdr_getflags
252This function returns the flags value specified by
253.Fa index
254.Po
255which must
256have a value between 0 and the value returned by
257.Fn inet6_rthdr_segments
258.Pc
259in the Routing header described by
260.Fa cmsg .
261For an IPv6 Type 0 Routing header the return value will be either
262.Dv IPV6_RTHDR_LOOSE
263or
264.Dv IPV6_RTHDR_STRICT .
265.Pp
266Upon an error the return value of the function is -1.
267.Pp
268Note: Addresses are indexed starting at 1, and flags starting at 0,
269to maintain consistency with the terminology and figures in RFC2460.
270.\"
271.Sh DIAGNOSTICS
272.Fn inet6_rthdr_space
273returns 0 on errors.
274.Pp
275.Fn inet6_rthdr_add ,
276.Fn inet6_rthdr_lasthop
277and
278.Fn inet6_rthdr_reverse
279return 0 on success, and returns -1 on error.
280.Pp
281.Fn inet6_rthdr_init
282and
283.Fn inet6_rthdr_getaddr
284return
285.Dv NULL
286on error.
287.Pp
288.Fn inet6_rthdr_segments
289and
290.Fn inet6_rthdr_getflags
291return -1 on error.
292.\"
293.Sh EXAMPLES
294RFC2292 gives comprehensive examples in chapter 8.
295.\"
296.Sh SEE ALSO
297.Rs
298.%A W. Stevens
299.%A M. Thomas
300.%T "Advanced Sockets API for IPv6"
301.%N RFC2292
302.%D February 1998
303.Re
304.Rs
305.%A S. Deering
306.%A R. Hinden
307.%T "Internet Protocol, Version 6 (IPv6) Specification"
308.%N RFC2460
309.%D December 1998
310.Re
311.\"
312.Sh HISTORY
313The implementation first appeared in KAME advanced networking kit.
314.\"
315.Sh STANDARDS
316The functions
317are documented in
318.Dq Advanced Sockets API for IPv6
319.Pq RFC2292 .
320.\"
321.Sh BUGS
322The text was shamelessly copied from RFC2292.
323.Pp
324.Fn inet6_rthdr_reverse
325is 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..5c32aecd86
--- /dev/null
+++ b/src/lib/libc/net/inet_net.3
@@ -0,0 +1,148 @@
1.\" $OpenBSD: inet_net.3,v 1.6 2000/04/21 15:38:17 aaron 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
85The only value for
86.Fa af
87currently supported is
88.Dv AF_INET .
89.Fa size
90is the size of the result buffer
91.Fa dst .
92.Sh NETWORK NUMBERS (IP VERSION 4)
93Internet network numbers may be specified in one of the following forms:
94.Bd -literal -offset indent
95a.b.c.d/bits
96a.b.c.d
97a.b.c
98a.b
99a
100.Ed
101.Pp
102When four parts are specified, each is interpreted
103as a byte of data and assigned, from left to right,
104to the four bytes of an Internet network number.
105Note that when an Internet network number is viewed as a 32-bit
106integer quantity on a system that uses little-endian
107byte order (such as the Intel 386, 486, and Pentium processors)
108the bytes referred to above appear as
109.Dq Li d.c.b.a .
110That is, little-endian bytes are ordered from right to left.
111.Pp
112When a three part number is specified, the last
113part is interpreted as a 16-bit quantity and placed
114in the rightmost two bytes of the Internet network number.
115This makes the three part number format convenient
116for specifying Class B network numbers as
117.Dq Li 128.net.host .
118.Pp
119When a two part number is supplied, the last part
120is interpreted as a 24-bit quantity and placed in
121the rightmost three bytes of the Internet network number.
122This makes the two part number format convenient
123for specifying Class A network numbers as
124.Dq Li net.host .
125.Pp
126When only one part is given, the value is stored
127directly in the Internet network number without any byte
128rearrangement.
129.Pp
130All numbers supplied as
131.Dq parts
132in a
133.Ql \&.
134notation
135may be decimal, octal, or hexadecimal, as specified
136in the C language (i.e., a leading 0x or 0X implies
137hexadecimal; otherwise, a leading 0 implies octal;
138otherwise, the number is interpreted as decimal).
139.Sh SEE ALSO
140.Xr byteorder 3 ,
141.Xr inet 3 ,
142.Xr networks 5
143.Sh HISTORY
144The
145.Nm inet_net_ntop
146and
147.Nm inet_net_pton
148functions 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..932531eb5d
--- /dev/null
+++ b/src/lib/libc/net/inet_net_pton.c
@@ -0,0 +1,206 @@
1/* $OpenBSD: inet_net_pton.c,v 1.2 2002/02/17 19:42:23 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 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.2 2002/02/17 19:42:23 millert 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 >= 8 && 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..21c57a355d
--- /dev/null
+++ b/src/lib/libc/net/ipx.3
@@ -0,0 +1,127 @@
1.\" $OpenBSD: ipx.3,v 1.8 2001/08/02 20:37:35 hugh 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 is 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..14e234c347 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.7 2001/08/02 20:37:35 hugh 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 is 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..5ff410e28a 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,35 +32,31 @@
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.10 2002/07/25 21:12:47 deraadt 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();
60 53
61 net.net_e = addr.x_net; 54 net.net_e = addr.x_net;
62 sprintf(obuf, "%lx", ntohl(net.long_e)); 55 snprintf(obuf, sizeof obuf, "%x", ntohl(net.long_e));
63 cp = spectHex(obuf); 56 cp = spectHex(obuf);
64 cp2 = cp + 1; 57 cp2 = cp + 1;
65 while (*up==0 && up < uplim) up++; 58 while (*up==0 && up < uplim)
59 up++;
66 if (up == uplim) { 60 if (up == uplim) {
67 if (port) { 61 if (port) {
68 sprintf(cp, ".0"); 62 sprintf(cp, ".0");
@@ -71,7 +65,8 @@ ns_ntoa(addr)
71 } else { 65 } else {
72 sprintf(cp, ".%x", *up++); 66 sprintf(cp, ".%x", *up++);
73 while (up < uplim) { 67 while (up < uplim) {
74 while (*cp) cp++; 68 while (*cp)
69 cp++;
75 sprintf(cp, "%02x", *up++); 70 sprintf(cp, "%02x", *up++);
76 } 71 }
77 cp = spectHex(cp2); 72 cp = spectHex(cp2);
@@ -84,23 +79,26 @@ ns_ntoa(addr)
84} 79}
85 80
86static char * 81static char *
87spectHex(p0) 82spectHex(char *p0)
88 char *p0;
89{ 83{
90 int ok = 0; 84 int ok = 0, nonzero = 0;
91 int nonzero = 0; 85 char *p = p0;
92 register char *p = p0;
93 for (; *p; p++) switch (*p) {
94 86
95 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': 87 for (; *p; p++) {
96 *p += ('A' - 'a'); 88 switch (*p) {
97 /* fall into . . . */ 89 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': 90 *p += ('A' - 'a');
99 ok = 1; 91 /* fall into . . . */
100 case '1': case '2': case '3': case '4': case '5': 92 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
101 case '6': case '7': case '8': case '9': 93 ok = 1;
102 nonzero = 1; 94 case '1': case '2': case '3': case '4': case '5':
95 case '6': case '7': case '8': case '9':
96 nonzero = 1;
97 }
98 }
99 if (nonzero && !ok) {
100 *p++ = 'H';
101 *p = 0;
103 } 102 }
104 if (nonzero && !ok) { *p++ = 'H'; *p = 0; }
105 return (p); 103 return (p);
106} 104}
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..7cf5af9519 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.24 2002/05/06 23:34:33 millert 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"
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..d3d2d751b5 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.44 2002/09/06 18:35:12 deraadt 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
@@ -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/stdlib/calloc.3 b/src/lib/libc/net/rcmdsh.3
index d0754b46a0..e0c59efb85 100644
--- a/src/lib/libc/stdlib/calloc.3
+++ b/src/lib/libc/net/rcmdsh.3
@@ -1,9 +1,7 @@
1.\" Copyright (c) 1991 The Regents of the University of California. 1.\" $OpenBSD: rcmdsh.3,v 1.8 2000/12/24 00:30:56 aaron Exp $
2.\" All rights reserved.
3.\" 2.\"
4.\" This code is derived from software contributed to Berkeley by 3.\" Copyright (c) 1983, 1991, 1993
5.\" the American National Standards Committee X3, on Information 4.\" The Regents of the University of California. All rights reserved.
6.\" Processing Systems.
7.\" 5.\"
8.\" Redistribution and use in source and binary forms, with or without 6.\" Redistribution and use in source and binary forms, with or without
9.\" modification, are permitted provided that the following conditions 7.\" modification, are permitted provided that the following conditions
@@ -33,39 +31,67 @@
33.\" 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
34.\" SUCH DAMAGE. 32.\" SUCH DAMAGE.
35.\" 33.\"
36.\" from: @(#)calloc.3 5.2 (Berkeley) 6/29/91 34.Dd September 1, 1996
37.\" $Id: calloc.3,v 1.1.1.1 1995/10/18 08:42:17 deraadt Exp $ 35.Dt RCMDSH 3
38.\"
39.Dd June 29, 1991
40.Dt CALLOC 3
41.Os 36.Os
42.Sh NAME 37.Sh NAME
43.Nm calloc 38.Nm rcmdsh
44.Nd allocate clean memory (zero initialized space) 39.Nd return a stream to a remote command without superuser
45.Sh SYNOPSIS 40.Sh SYNOPSIS
46.Fd #include <stdlib.h> 41.Fd #include <unistd.h>
47.Ft void * 42.Ft int
48.Fn calloc "size_t nmemb" "size_t size" 43.Fn rcmdsh "char **ahost" "int inport" "const char *locuser" "const char *remuser" "const char *cmd" "char *rshprog"
49.Sh DESCRIPTION 44.Sh DESCRIPTION
50The 45The
51.Fn calloc 46.Fn rcmdsh
52function allocates space for an array of 47function is used by normal users to execute a command on a remote machine
53.Fa nmemb 48using an authentication scheme based on reserved port numbers using
54objects, each of whose size is 49.Xr rshd 8
55.Fa size . 50or the value of
56The space is initialized to all bits zero. 51.Fa rshprog
57.Sh RETURN VALUES 52(if non-null).
53.Pp
54The
55.Fn rcmdsh
56function looks up the host
57.Fa *ahost
58using
59.Xr gethostbyname 3 ,
60returning \-1 if the host does not exist.
61Otherwise
62.Fa *ahost
63is set to the standard name of the host and a connection is established to
64a server residing at the well-known Internet port
65.Li shell/tcp
66(or whatever port is used by
67.Fa rshprog ) .
68The parameter
69.Fa inport
70is ignored; it is only included to provide an interface similar to
71.Xr rcmd 3 .
72.Pp
73If the connection succeeds, a socket in the
74.Tn UNIX
75domain of type
76.Dv SOCK_STREAM
77is returned to the caller, and given to the remote
78command as stdin and stdout, and stderr.
79.Sh DIAGNOSTICS
58The 80The
59.Fn calloc 81.Fn rcmdsh
60function returns 82function returns a valid socket descriptor on success.
61a pointer to the 83It returns \-1 on error and prints a diagnostic message on the standard error.
62the allocated space if successful; otherwise a null pointer is returned.
63.Sh SEE ALSO 84.Sh SEE ALSO
64.Xr malloc 3 , 85.Xr rsh 1 ,
65.Xr realloc 3 , 86.Xr socketpair 2 ,
66.Xr free 3 87.Xr rcmd 3 ,
67.Sh STANDARDS 88.Xr rshd 8
89.Sh BUGS
90If
91.Xr rsh 1
92encounters an error, a file descriptor is still returned instead of \-1.
93.Sh HISTORY
68The 94The
69.Fn calloc 95.Fn rcmdsh
70function conforms to 96function first appeared in
71.St -ansiC . 97.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..a1c7e7d6b8
--- /dev/null
+++ b/src/lib/libc/net/rcmdsh.c
@@ -0,0 +1,153 @@
1/* $OpenBSD: rcmdsh.c,v 1.7 2002/03/12 00:05:44 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.7 2002/03/12 00:05:44 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 <string.h>
48#include <pwd.h>
49#include <paths.h>
50#include <unistd.h>
51
52/*
53 * This is a replacement rcmd() function that uses the rsh(1)
54 * program in place of a direct rcmd(3) function call so as to
55 * avoid having to be root. Note that rport is ignored.
56 */
57/* ARGSUSED */
58int
59rcmdsh(ahost, rport, locuser, remuser, cmd, rshprog)
60 char **ahost;
61 int rport;
62 const char *locuser, *remuser, *cmd;
63 char *rshprog;
64{
65 struct hostent *hp;
66 int sp[2];
67 pid_t cpid;
68 char *p;
69 struct passwd *pw;
70
71 /* What rsh/shell to use. */
72 if (rshprog == NULL)
73 rshprog = _PATH_RSH;
74
75 /* locuser must exist on this host. */
76 if ((pw = getpwnam(locuser)) == NULL) {
77 (void) fprintf(stderr, "rcmdsh: unknown user: %s\n", locuser);
78 return(-1);
79 }
80
81 /* Validate remote hostname. */
82 if (strcmp(*ahost, "localhost") != 0) {
83 if ((hp = gethostbyname(*ahost)) == NULL) {
84 herror(*ahost);
85 return(-1);
86 }
87 *ahost = hp->h_name;
88 }
89
90 /* Get a socketpair we'll use for stdin and stdout. */
91 if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, sp) < 0) {
92 perror("rcmdsh: socketpair");
93 return(-1);
94 }
95
96 cpid = fork();
97 if (cpid < 0) {
98 perror("rcmdsh: fork failed");
99 return(-1);
100 } else if (cpid == 0) {
101 /*
102 * Child. We use sp[1] to be stdin/stdout, and close sp[0].
103 */
104 (void) close(sp[0]);
105 if (dup2(sp[1], 0) < 0 || dup2(0, 1) < 0) {
106 perror("rcmdsh: dup2 failed");
107 _exit(255);
108 }
109 /* Fork again to lose parent. */
110 cpid = fork();
111 if (cpid < 0) {
112 perror("rcmdsh: fork to lose parent failed");
113 _exit(255);
114 }
115 if (cpid > 0)
116 _exit(0);
117
118 /* In grandchild here. Become local user for rshprog. */
119 if (setuid(pw->pw_uid)) {
120 (void) fprintf(stderr, "rcmdsh: setuid(%u): %s\n",
121 pw->pw_uid, strerror(errno));
122 _exit(255);
123 }
124
125 /*
126 * If remote host is "localhost" and local and remote user
127 * are the same, avoid running remote shell for efficiency.
128 */
129 if (!strcmp(*ahost, "localhost") && !strcmp(locuser, remuser)) {
130 if (pw->pw_shell[0] == '\0')
131 rshprog = _PATH_BSHELL;
132 else
133 rshprog = pw->pw_shell;
134 p = strrchr(rshprog, '/');
135 execlp(rshprog, p ? p+1 : rshprog, "-c", cmd,
136 (char *) NULL);
137 } else {
138 p = strrchr(rshprog, '/');
139 execlp(rshprog, p ? p+1 : rshprog, *ahost, "-l",
140 remuser, cmd, (char *) NULL);
141 }
142 (void) fprintf(stderr, "rcmdsh: execlp %s failed: %s\n",
143 rshprog, strerror(errno));
144 _exit(255);
145 } else {
146 /* Parent. close sp[1], return sp[0]. */
147 (void) close(sp[1]);
148 /* Reap child. */
149 (void) wait(NULL);
150 return(sp[0]);
151 }
152 /* NOTREACHED */
153}
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..2ea9173fe9 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.14 2002/07/25 21:55:30 deraadt 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,191 @@
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.14 2002/07/25 21:55:30 deraadt 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>
70#include <string.h> 100#include <time.h>
71 101
72void __fp_query(); 102#include <stdlib.h>
73char *__p_class(), *__p_time(), *__p_type(); 103#include <string.h>
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 104
96char *_res_resultcodes[] = { 105extern const char *_res_opcodes[];
97 "NOERROR", 106extern 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 107
115static char retbuf[16]; 108static const char *loc_ntoal(const u_char *binary, char *ascii, int ascii_len);
116 109
117static char * 110/* XXX: we should use getservbyport() instead. */
111static const char *
118dewks(wks) 112dewks(wks)
119 int wks; 113 int wks;
120{ 114{
115 static char nbuf[20];
116
121 switch (wks) { 117 switch (wks) {
122 case 5: return("rje"); 118 case 5: return "rje";
123 case 7: return("echo"); 119 case 7: return "echo";
124 case 9: return("discard"); 120 case 9: return "discard";
125 case 11: return("systat"); 121 case 11: return "systat";
126 case 13: return("daytime"); 122 case 13: return "daytime";
127 case 15: return("netstat"); 123 case 15: return "netstat";
128 case 17: return("qotd"); 124 case 17: return "qotd";
129 case 19: return("chargen"); 125 case 19: return "chargen";
130 case 20: return("ftp-data"); 126 case 20: return "ftp-data";
131 case 21: return("ftp"); 127 case 21: return "ftp";
132 case 23: return("telnet"); 128 case 23: return "telnet";
133 case 25: return("smtp"); 129 case 25: return "smtp";
134 case 37: return("time"); 130 case 37: return "time";
135 case 39: return("rlp"); 131 case 39: return "rlp";
136 case 42: return("name"); 132 case 42: return "name";
137 case 43: return("whois"); 133 case 43: return "whois";
138 case 53: return("domain"); 134 case 53: return "domain";
139 case 57: return("apts"); 135 case 57: return "apts";
140 case 59: return("apfs"); 136 case 59: return "apfs";
141 case 67: return("bootps"); 137 case 67: return "bootps";
142 case 68: return("bootpc"); 138 case 68: return "bootpc";
143 case 69: return("tftp"); 139 case 69: return "tftp";
144 case 77: return("rje"); 140 case 77: return "rje";
145 case 79: return("finger"); 141 case 79: return "finger";
146 case 87: return("link"); 142 case 87: return "link";
147 case 95: return("supdup"); 143 case 95: return "supdup";
148 case 100: return("newacct"); 144 case 100: return "newacct";
149 case 101: return("hostnames"); 145 case 101: return "hostnames";
150 case 102: return("iso-tsap"); 146 case 102: return "iso-tsap";
151 case 103: return("x400"); 147 case 103: return "x400";
152 case 104: return("x400-snd"); 148 case 104: return "x400-snd";
153 case 105: return("csnet-ns"); 149 case 105: return "csnet-ns";
154 case 109: return("pop-2"); 150 case 109: return "pop-2";
155 case 111: return("sunrpc"); 151 case 111: return "sunrpc";
156 case 113: return("auth"); 152 case 113: return "auth";
157 case 115: return("sftp"); 153 case 115: return "sftp";
158 case 117: return("uucp-path"); 154 case 117: return "uucp-path";
159 case 119: return("nntp"); 155 case 119: return "nntp";
160 case 121: return("erpc"); 156 case 121: return "erpc";
161 case 123: return("ntp"); 157 case 123: return "ntp";
162 case 133: return("statsrv"); 158 case 133: return "statsrv";
163 case 136: return("profile"); 159 case 136: return "profile";
164 case 144: return("NeWS"); 160 case 144: return "NeWS";
165 case 161: return("snmp"); 161 case 161: return "snmp";
166 case 162: return("snmp-trap"); 162 case 162: return "snmp-trap";
167 case 170: return("print-srv"); 163 case 170: return "print-srv";
168 default: (void) sprintf(retbuf, "%d", wks); return(retbuf); 164 default:
165 (void) snprintf(nbuf, sizeof nbuf, "%d", wks);
166 return (nbuf);
169 } 167 }
170} 168}
171 169
172static char * 170/* XXX: we should use getprotobynumber() instead. */
171static const char *
173deproto(protonum) 172deproto(protonum)
174 int protonum; 173 int protonum;
175{ 174{
175 static char nbuf[20];
176
176 switch (protonum) { 177 switch (protonum) {
177 case 1: return("icmp"); 178 case 1: return "icmp";
178 case 2: return("igmp"); 179 case 2: return "igmp";
179 case 3: return("ggp"); 180 case 3: return "ggp";
180 case 5: return("st"); 181 case 5: return "st";
181 case 6: return("tcp"); 182 case 6: return "tcp";
182 case 7: return("ucl"); 183 case 7: return "ucl";
183 case 8: return("egp"); 184 case 8: return "egp";
184 case 9: return("igp"); 185 case 9: return "igp";
185 case 11: return("nvp-II"); 186 case 11: return "nvp-II";
186 case 12: return("pup"); 187 case 12: return "pup";
187 case 16: return("chaos"); 188 case 16: return "chaos";
188 case 17: return("udp"); 189 case 17: return "udp";
189 default: (void) sprintf(retbuf, "%d", protonum); return(retbuf); 190 default:
191 (void) snprintf(nbuf, sizeof nbuf, "%d", protonum);
192 return (nbuf);
190 } 193 }
191} 194}
192 195
193static char * 196static const u_char *
194do_rrset(msg, cp, cnt, pflag, file, hs) 197do_rrset(msg, len, cp, cnt, pflag, file, hs)
195 int cnt, pflag; 198 int cnt, pflag, len;
196 char *cp,*msg, *hs; 199 const u_char *cp, *msg;
200 const char *hs;
197 FILE *file; 201 FILE *file;
198{ 202{
199 int n; 203 int n;
200 int sflag; 204 int sflag;
205
201 /* 206 /*
202 * Print answer records 207 * Print answer records.
203 */ 208 */
204 sflag = (_res.pfcode & pflag); 209 sflag = (_res.pfcode & pflag);
205 if (n = ntohs(cnt)) { 210 if ((n = ntohs(cnt))) {
206 if ((!_res.pfcode) || ((sflag) && (_res.pfcode & RES_PRF_HEAD1))) 211 if ((!_res.pfcode) ||
207 fprintf(file, hs); 212 ((sflag) && (_res.pfcode & RES_PRF_HEAD1)))
213 fprintf(file, "%s", hs);
208 while (--n >= 0) { 214 while (--n >= 0) {
209 cp = p_rr(cp, msg, file); 215 if ((!_res.pfcode) || sflag) {
210 if ((cp-msg) > PACKETSZ) 216 cp = p_rr(cp, msg, file);
217 } else {
218 unsigned int dlen;
219 cp += __dn_skipname(cp, cp + MAXCDNAME);
220 cp += INT16SZ;
221 cp += INT16SZ;
222 cp += INT32SZ;
223 dlen = _getshort((u_char*)cp);
224 cp += INT16SZ;
225 cp += dlen;
226 }
227 if ((cp - msg) > len)
211 return (NULL); 228 return (NULL);
212 } 229 }
213 if ((!_res.pfcode) || ((sflag) && (_res.pfcode & RES_PRF_HEAD1))) 230 if ((!_res.pfcode) ||
231 ((sflag) && (_res.pfcode & RES_PRF_HEAD1)))
214 putc('\n', file); 232 putc('\n', file);
215 } 233 }
216 return(cp); 234 return (cp);
217} 235}
218 236
237void
219__p_query(msg) 238__p_query(msg)
220 char *msg; 239 const u_char *msg;
221{ 240{
222 __fp_query(msg, stdout); 241 __fp_query(msg, stdout);
223} 242}
@@ -231,15 +250,14 @@ __fp_resstat(statp, file)
231 struct __res_state *statp; 250 struct __res_state *statp;
232 FILE *file; 251 FILE *file;
233{ 252{
234 int bit; 253 register u_long mask;
235 254
236 fprintf(file, ";; res options:"); 255 fprintf(file, ";; res options:");
237 if (!statp) 256 if (!statp)
238 statp = &_res; 257 statp = &_res;
239 for (bit = 0; bit < 32; bit++) { /* XXX 32 - bad assumption! */ 258 for (mask = 1; mask != 0; mask <<= 1)
240 if (statp->options & (1<<bit)) 259 if (statp->options & mask)
241 fprintf(file, " %s", p_option(1<<bit)); 260 fprintf(file, " %s", p_option(mask));
242 }
243 putc('\n', file); 261 putc('\n', file);
244} 262}
245 263
@@ -248,109 +266,151 @@ __fp_resstat(statp, file)
248 * This is intended to be primarily a debugging routine. 266 * This is intended to be primarily a debugging routine.
249 */ 267 */
250void 268void
251__fp_query(msg,file) 269__fp_nquery(msg, len, file)
252 char *msg; 270 const u_char *msg;
271 int len;
253 FILE *file; 272 FILE *file;
254{ 273{
255 register char *cp; 274 register const u_char *cp, *endMark;
256 register HEADER *hp; 275 register const HEADER *hp;
257 register int n; 276 register int n;
258 277
278 if ((_res.options & RES_INIT) == 0 && res_init() == -1)
279 return;
280
281#define TruncTest(x) if (x > endMark) goto trunc
282#define ErrorTest(x) if (x == NULL) goto error
283
259 /* 284 /*
260 * Print header fields. 285 * Print header fields.
261 */ 286 */
262 hp = (HEADER *)msg; 287 hp = (HEADER *)msg;
263 cp = msg + sizeof(HEADER); 288 cp = msg + HFIXEDSZ;
289 endMark = msg + len;
264 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEADX) || hp->rcode) { 290 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEADX) || hp->rcode) {
265 fprintf(file,";; ->>HEADER<<- opcode: %s, status: %s, id: %d", 291 fprintf(file, ";; ->>HEADER<<- opcode: %s, status: %s, id: %u",
266 _res_opcodes[hp->opcode], 292 _res_opcodes[hp->opcode],
267 _res_resultcodes[hp->rcode], 293 _res_resultcodes[hp->rcode],
268 ntohs(hp->id)); 294 ntohs(hp->id));
269 putc('\n', file); 295 putc('\n', file);
270 } 296 }
271 putc(';', file); 297 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEADX))
298 putc(';', file);
272 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD2)) { 299 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD2)) {
273 fprintf(file,"; flags:"); 300 fprintf(file, "; flags:");
274 if (hp->qr) 301 if (hp->qr)
275 fprintf(file," qr"); 302 fprintf(file, " qr");
276 if (hp->aa) 303 if (hp->aa)
277 fprintf(file," aa"); 304 fprintf(file, " aa");
278 if (hp->tc) 305 if (hp->tc)
279 fprintf(file," tc"); 306 fprintf(file, " tc");
280 if (hp->rd) 307 if (hp->rd)
281 fprintf(file," rd"); 308 fprintf(file, " rd");
282 if (hp->ra) 309 if (hp->ra)
283 fprintf(file," ra"); 310 fprintf(file, " ra");
284 if (hp->pr) 311 if (hp->unused)
285 fprintf(file," pr"); 312 fprintf(file, " UNUSED-BIT-ON");
313 if (hp->ad)
314 fprintf(file, " ad");
315 if (hp->cd)
316 fprintf(file, " cd");
286 } 317 }
287 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD1)) { 318 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD1)) {
288 fprintf(file,"; Ques: %d", ntohs(hp->qdcount)); 319 fprintf(file, "; Ques: %u", ntohs(hp->qdcount));
289 fprintf(file,", Ans: %d", ntohs(hp->ancount)); 320 fprintf(file, ", Ans: %u", ntohs(hp->ancount));
290 fprintf(file,", Auth: %d", ntohs(hp->nscount)); 321 fprintf(file, ", Auth: %u", ntohs(hp->nscount));
291 fprintf(file,", Addit: %d\n", ntohs(hp->arcount)); 322 fprintf(file, ", Addit: %u", ntohs(hp->arcount));
292 } 323 }
293#if 0 324 if ((!_res.pfcode) || (_res.pfcode &
294 if (_res.pfcode & (RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1)) { 325 (RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) {
295 putc('\n',file); 326 putc('\n',file);
296 } 327 }
297#endif
298 /* 328 /*
299 * Print question records. 329 * Print question records.
300 */ 330 */
301 if (n = ntohs(hp->qdcount)) { 331 if ((n = ntohs(hp->qdcount))) {
302 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES)) 332 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
303 fprintf(file,";; QUESTIONS:\n"); 333 fprintf(file, ";; QUESTIONS:\n");
304 while (--n >= 0) { 334 while (--n >= 0) {
305 fprintf(file,";;\t"); 335 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
306 cp = p_cdname(cp, msg, file); 336 fprintf(file, ";;\t");
307 if (cp == NULL) 337 TruncTest(cp);
308 return; 338 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
339 cp = p_cdnname(cp, msg, len, file);
340 else {
341 int n;
342 char name[MAXDNAME];
343
344 if ((n = dn_expand(msg, msg+len, cp, name,
345 sizeof name)) < 0)
346 cp = NULL;
347 else
348 cp += n;
349 }
350 ErrorTest(cp);
351 TruncTest(cp);
309 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES)) 352 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
310 fprintf(file, ", type = %s", 353 fprintf(file, ", type = %s",
311 __p_type(_getshort(cp))); 354 __p_type(_getshort((u_char*)cp)));
312 cp += sizeof(u_int16_t); 355 cp += INT16SZ;
356 TruncTest(cp);
313 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES)) 357 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
314 fprintf(file, ", class = %s\n\n", 358 fprintf(file, ", class = %s\n",
315 __p_class(_getshort(cp))); 359 __p_class(_getshort((u_char*)cp)));
316 cp += sizeof(u_int16_t); 360 cp += INT16SZ;
361 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
362 putc('\n', file);
317 } 363 }
318 } 364 }
319 /* 365 /*
320 * Print authoritative answer records 366 * Print authoritative answer records
321 */ 367 */
322 cp = do_rrset(msg, cp, hp->ancount, RES_PRF_ANS, file, 368 TruncTest(cp);
369 cp = do_rrset(msg, len, cp, hp->ancount, RES_PRF_ANS, file,
323 ";; ANSWERS:\n"); 370 ";; ANSWERS:\n");
324 if (cp == NULL) 371 ErrorTest(cp);
325 return;
326 372
327 /* 373 /*
328 * print name server records 374 * print name server records
329 */ 375 */
330 cp = do_rrset(msg, cp, hp->nscount, RES_PRF_AUTH, file, 376 TruncTest(cp);
377 cp = do_rrset(msg, len, cp, hp->nscount, RES_PRF_AUTH, file,
331 ";; AUTHORITY RECORDS:\n"); 378 ";; AUTHORITY RECORDS:\n");
332 if (!cp) 379 ErrorTest(cp);
333 return;
334 380
381 TruncTest(cp);
335 /* 382 /*
336 * print additional records 383 * print additional records
337 */ 384 */
338 cp = do_rrset(msg, cp, hp->arcount, RES_PRF_ADD, file, 385 cp = do_rrset(msg, len, cp, hp->arcount, RES_PRF_ADD, file,
339 ";; ADDITIONAL RECORDS:\n"); 386 ";; ADDITIONAL RECORDS:\n");
340 if (!cp) 387 ErrorTest(cp);
341 return; 388 return;
389 trunc:
390 fprintf(file, "\n;; ...truncated\n");
391 return;
392 error:
393 fprintf(file, "\n;; ...malformed\n");
342} 394}
343 395
344char * 396void
345p_cdname(cp, msg, file) 397__fp_query(msg, file)
346 char *cp, *msg; 398 const u_char *msg;
399 FILE *file;
400{
401 fp_nquery(msg, PACKETSZ, file);
402}
403
404const u_char *
405__p_cdnname(cp, msg, len, file)
406 const u_char *cp, *msg;
407 int len;
347 FILE *file; 408 FILE *file;
348{ 409{
349 char name[MAXDNAME]; 410 char name[MAXDNAME];
350 int n; 411 int n;
351 412
352 if ((n = dn_expand((u_char *)msg, (u_char *)cp + MAXCDNAME, 413 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); 414 return (NULL);
355 if (name[0] == '\0') 415 if (name[0] == '\0')
356 putc('.', file); 416 putc('.', file);
@@ -359,54 +419,94 @@ p_cdname(cp, msg, file)
359 return (cp + n); 419 return (cp + n);
360} 420}
361 421
362char * 422const u_char *
363p_fqname(cp, msg, file) 423__p_cdname(cp, msg, file)
364 char *cp, *msg; 424 const u_char *cp, *msg;
365 FILE *file; 425 FILE *file;
366{ 426{
367 char name[MAXDNAME]; 427 return (p_cdnname(cp, msg, PACKETSZ, file));
368 int n, len; 428}
429
369 430
370 if ((n = dn_expand((u_char *)msg, (u_char *)cp + MAXCDNAME, 431/* Return a fully-qualified domain name from a compressed name (with
371 (u_char *)cp, (u_char *)name, sizeof(name))) < 0) 432 length supplied). */
433
434const u_char *
435__p_fqnname(cp, msg, msglen, name, namelen)
436 const u_char *cp, *msg;
437 int msglen;
438 char *name;
439 int namelen;
440{
441 int n, newlen;
442
443 if ((n = dn_expand(msg, cp + msglen, cp, name, namelen)) < 0)
372 return (NULL); 444 return (NULL);
373 if (name[0] == '\0') { 445 newlen = strlen(name);
374 putc('.', file); 446 if (newlen == 0 || name[newlen - 1] != '.') {
375 } else { 447 if (newlen+1 >= namelen) /* Lack space for final dot */
376 fputs(name, file); 448 return (NULL);
377 if (name[strlen(name) - 1] != '.') 449 else
378 putc('.', file); 450 strcpy(name + newlen, ".");
379 } 451 }
380 return (cp + n); 452 return (cp + n);
381} 453}
382 454
455/* XXX: the rest of these functions need to become length-limited, too. (vix)
456 */
457
458const u_char *
459__p_fqname(cp, msg, file)
460 const u_char *cp, *msg;
461 FILE *file;
462{
463 char name[MAXDNAME];
464 const u_char *n;
465
466 n = __p_fqnname(cp, msg, MAXCDNAME, name, sizeof name);
467 if (n == NULL)
468 return (NULL);
469 fputs(name, file);
470 return (n);
471}
472
383/* 473/*
384 * Print resource record fields in human readable form. 474 * Print resource record fields in human readable form.
385 */ 475 */
386char * 476const u_char *
387p_rr(cp, msg, file) 477__p_rr(cp, msg, file)
388 char *cp, *msg; 478 const u_char *cp, *msg;
389 FILE *file; 479 FILE *file;
390{ 480{
391 int type, class, dlen, n, c; 481 int type, class, dlen, n, c;
392 struct in_addr inaddr; 482 struct in_addr inaddr;
393 char *cp1, *cp2; 483 const u_char *cp1, *cp2;
394 u_int32_t tmpttl, t; 484 u_int32_t tmpttl, t;
395 int lcnt; 485 int lcnt;
486 u_int16_t keyflags;
487 char rrname[MAXDNAME]; /* The fqdn of this RR */
488 char base64_key[MAX_KEY_BASE64];
396 489
397 if ((cp = p_fqname(cp, msg, file)) == NULL) 490 if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
491 h_errno = NETDB_INTERNAL;
492 return (NULL);
493 }
494 cp = __p_fqnname(cp, msg, MAXCDNAME, rrname, sizeof rrname);
495 if (!cp)
398 return (NULL); /* compression error */ 496 return (NULL); /* compression error */
399 type = _getshort(cp); 497 fputs(rrname, file);
400 cp += sizeof(u_int16_t); 498
401 class = _getshort(cp); 499 type = _getshort((u_char*)cp);
402 cp += sizeof(u_int16_t); 500 cp += INT16SZ;
403 tmpttl = _getlong(cp); 501 class = _getshort((u_char*)cp);
404 cp += sizeof(u_int32_t); 502 cp += INT16SZ;
405 dlen = _getshort(cp); 503 tmpttl = _getlong((u_char*)cp);
406 cp += sizeof(u_int16_t); 504 cp += INT32SZ;
505 dlen = _getshort((u_char*)cp);
506 cp += INT16SZ;
407 cp1 = cp; 507 cp1 = cp;
408 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_TTLID)) 508 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_TTLID))
409 fprintf(file, "\t%lu", tmpttl); 509 fprintf(file, "\t%lu", (u_long)tmpttl);
410 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_CLASS)) 510 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_CLASS))
411 fprintf(file, "\t%s", __p_class(class)); 511 fprintf(file, "\t%s", __p_class(class));
412 fprintf(file, "\t%s", __p_type(type)); 512 fprintf(file, "\t%s", __p_type(type));
@@ -418,22 +518,22 @@ p_rr(cp, msg, file)
418 switch (class) { 518 switch (class) {
419 case C_IN: 519 case C_IN:
420 case C_HS: 520 case C_HS:
421 bcopy(cp, (char *)&inaddr, sizeof(inaddr)); 521 bcopy(cp, (char *)&inaddr, INADDRSZ);
422 if (dlen == 4) { 522 if (dlen == 4) {
423 fprintf(file,"\t%s", inet_ntoa(inaddr)); 523 fprintf(file, "\t%s", inet_ntoa(inaddr));
424 cp += dlen; 524 cp += dlen;
425 } else if (dlen == 7) { 525 } else if (dlen == 7) {
426 char *address; 526 char *address;
427 u_char protocol; 527 u_char protocol;
428 u_short port; 528 in_port_t port;
429 529
430 address = inet_ntoa(inaddr); 530 address = inet_ntoa(inaddr);
431 cp += sizeof(inaddr); 531 cp += INADDRSZ;
432 protocol = *(u_char*)cp; 532 protocol = *(u_char*)cp;
433 cp += sizeof(u_char); 533 cp += sizeof (u_char);
434 port = _getshort(cp); 534 port = _getshort((u_char*)cp);
435 cp += sizeof(u_int16_t); 535 cp += INT16SZ;
436 fprintf(file, "\t%s\t; proto %d, port %d", 536 fprintf(file, "\t%s\t; proto %u, port %u",
437 address, protocol, port); 537 address, protocol, port);
438 } 538 }
439 break; 539 break;
@@ -448,98 +548,205 @@ p_rr(cp, msg, file)
448 case T_NS: 548 case T_NS:
449 case T_PTR: 549 case T_PTR:
450 putc('\t', file); 550 putc('\t', file);
451 cp = p_fqname(cp, msg, file); 551 if ((cp = p_fqname(cp, msg, file)) == NULL)
552 return (NULL);
452 break; 553 break;
453 554
454 case T_HINFO: 555 case T_HINFO:
455 if (n = *cp++) { 556 case T_ISDN:
456 fprintf(file,"\t%.*s", n, cp); 557 cp2 = cp + dlen;
457 cp += n; 558 (void) fputs("\t\"", file);
559 if ((n = (unsigned char) *cp++) != 0) {
560 for (c = n; c > 0 && cp < cp2; c--) {
561 if (strchr("\n\"\\", *cp))
562 (void) putc('\\', file);
563 (void) putc(*cp++, file);
564 }
458 } 565 }
459 if (n = *cp++) { 566 putc('"', file);
460 fprintf(file,"\t%.*s", n, cp); 567 if (cp < cp2 && (n = (unsigned char) *cp++) != 0) {
461 cp += n; 568 (void) fputs ("\t\"", file);
569 for (c = n; c > 0 && cp < cp2; c--) {
570 if (strchr("\n\"\\", *cp))
571 (void) putc('\\', file);
572 (void) putc(*cp++, file);
573 }
574 putc('"', file);
575 } else if (type == T_HINFO) {
576 (void) fputs("\"?\"", file);
577 fprintf(file, "\n;; *** Warning *** OS-type missing");
462 } 578 }
463 break; 579 break;
464 580
465 case T_SOA: 581 case T_SOA:
466 putc('\t', file); 582 putc('\t', file);
467 cp = p_fqname(cp, msg, file); /* origin */ 583 if ((cp = p_fqname(cp, msg, file)) == NULL)
584 return (NULL);
468 putc(' ', file); 585 putc(' ', file);
469 cp = p_fqname(cp, msg, file); /* mail addr */ 586 if ((cp = p_fqname(cp, msg, file)) == NULL)
587 return (NULL);
470 fputs(" (\n", file); 588 fputs(" (\n", file);
471 t = _getlong(cp); cp += sizeof(u_int32_t); 589 t = _getlong((u_char*)cp); cp += INT32SZ;
472 fprintf(file,"\t\t\t%lu\t; serial\n", t); 590 fprintf(file, "\t\t\t%lu\t; serial\n", (u_long)t);
473 t = _getlong(cp); cp += sizeof(u_int32_t); 591 t = _getlong((u_char*)cp); cp += INT32SZ;
474 fprintf(file,"\t\t\t%lu\t; refresh (%s)\n", t, __p_time(t)); 592 fprintf(file, "\t\t\t%lu\t; refresh (%s)\n",
475 t = _getlong(cp); cp += sizeof(u_int32_t); 593 (u_long)t, __p_time(t));
476 fprintf(file,"\t\t\t%lu\t; retry (%s)\n", t, __p_time(t)); 594 t = _getlong((u_char*)cp); cp += INT32SZ;
477 t = _getlong(cp); cp += sizeof(u_int32_t); 595 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)); 596 (u_long)t, __p_time(t));
479 t = _getlong(cp); cp += sizeof(u_int32_t); 597 t = _getlong((u_char*)cp); cp += INT32SZ;
480 fprintf(file,"\t\t\t%lu )\t; minimum (%s)", t, __p_time(t)); 598 fprintf(file, "\t\t\t%lu\t; expire (%s)\n",
599 (u_long)t, __p_time(t));
600 t = _getlong((u_char*)cp); cp += INT32SZ;
601 fprintf(file, "\t\t\t%lu )\t; minimum (%s)",
602 (u_long)t, __p_time(t));
481 break; 603 break;
482 604
483 case T_MX: 605 case T_MX:
484 case T_AFSDB: 606 case T_AFSDB:
485 fprintf(file,"\t%d ", _getshort(cp)); 607 case T_RT:
486 cp += sizeof(u_int16_t); 608 fprintf(file, "\t%u ", _getshort((u_char*)cp));
487 cp = p_fqname(cp, msg, file); 609 cp += INT16SZ;
610 if ((cp = p_fqname(cp, msg, file)) == NULL)
611 return (NULL);
488 break; 612 break;
489 613
490 case T_TXT: 614 case T_PX:
615 fprintf(file, "\t%u ", _getshort((u_char*)cp));
616 cp += INT16SZ;
617 if ((cp = p_fqname(cp, msg, file)) == NULL)
618 return (NULL);
619 putc(' ', file);
620 if ((cp = p_fqname(cp, msg, file)) == NULL)
621 return (NULL);
622 break;
623
624 case T_X25:
625 cp2 = cp + dlen;
491 (void) fputs("\t\"", file); 626 (void) fputs("\t\"", file);
627 if ((n = (unsigned char) *cp++) != 0) {
628 for (c = n; c > 0 && cp < cp2; c--) {
629 if (strchr("\n\"\\", *cp))
630 (void) putc('\\', file);
631 (void) putc(*cp++, file);
632 }
633 }
634 putc('"', file);
635 break;
636
637 case T_TXT:
638 (void) putc('\t', file);
492 cp2 = cp1 + dlen; 639 cp2 = cp1 + dlen;
493 while (cp < cp2) { 640 while (cp < cp2) {
494 if (n = (unsigned char) *cp++) { 641 putc('"', file);
495 for (c = n; c > 0 && cp < cp2; c--) 642 if ((n = (unsigned char) *cp++)) {
496 if (*cp == '\n') { 643 for (c = n; c > 0 && cp < cp2; c--) {
497 (void) putc('\\', file); 644 if (strchr("\n\"\\", *cp))
498 (void) putc(*cp++, file); 645 (void) putc('\\', file);
499 } else 646 (void) putc(*cp++, file);
500 (void) putc(*cp++, file); 647 }
501 } 648 }
649 putc('"', file);
650 if (cp < cp2)
651 putc(' ', file);
502 } 652 }
503 putc('"', file); 653 break;
504 break; 654
655 case T_NSAP:
656 (void) fprintf(file, "\t%s", inet_nsap_ntoa(dlen, cp, NULL));
657 cp += dlen;
658 break;
659
660 case T_AAAA: {
661 char t[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"];
662
663 fprintf(file, "\t%s", inet_ntop(AF_INET6, cp, t, sizeof t));
664 cp += dlen;
665 break;
666 }
667
668 case T_LOC: {
669 char t[255];
670
671 fprintf(file, "\t%s", loc_ntoal(cp, t, sizeof t));
672 cp += dlen;
673 break;
674 }
675
676 case T_NAPTR: {
677 u_int order, preference;
678
679 order = _getshort(cp); cp += INT16SZ;
680 preference = _getshort(cp); cp += INT16SZ;
681 fprintf(file, "\t%u %u ",order, preference);
682 /* Flags */
683 n = *cp++;
684 fprintf(file,"\"%.*s\" ", (int)n, cp);
685 cp += n;
686 /* Service */
687 n = *cp++;
688 fprintf(file,"\"%.*s\" ", (int)n, cp);
689 cp += n;
690 /* Regexp */
691 n = *cp++;
692 fprintf(file,"\"%.*s\" ", (int)n, cp);
693 cp += n;
694 if ((cp = p_fqname(cp, msg, file)) == NULL)
695 return (NULL);
696 break;
697 }
698
699 case T_SRV: {
700 u_int priority, weight, port;
701
702 priority = _getshort(cp); cp += INT16SZ;
703 weight = _getshort(cp); cp += INT16SZ;
704 port = _getshort(cp); cp += INT16SZ;
705 fprintf(file, "\t%u %u %u ", priority, weight, port);
706 if ((cp = p_fqname(cp, msg, file)) == NULL)
707 return (NULL);
708 break;
709 }
505 710
506 case T_MINFO: 711 case T_MINFO:
507 case T_RP: 712 case T_RP:
508 putc('\t', file); 713 putc('\t', file);
509 cp = p_fqname(cp, msg, file); 714 if ((cp = p_fqname(cp, msg, file)) == NULL)
715 return (NULL);
510 putc(' ', file); 716 putc(' ', file);
511 cp = p_fqname(cp, msg, file); 717 if ((cp = p_fqname(cp, msg, file)) == NULL)
718 return (NULL);
512 break; 719 break;
513 720
514 case T_UINFO: 721 case T_UINFO:
515 putc('\t', file); 722 putc('\t', file);
516 fputs(cp, file); 723 fputs((char *)cp, file);
517 cp += dlen; 724 cp += dlen;
518 break; 725 break;
519 726
520 case T_UID: 727 case T_UID:
521 case T_GID: 728 case T_GID:
522 if (dlen == 4) { 729 if (dlen == 4) {
523 fprintf(file,"\t%u", _getlong(cp)); 730 fprintf(file, "\t%u", _getlong((u_char*)cp));
524 cp += sizeof(int32_t); 731 cp += INT32SZ;
525 } 732 }
526 break; 733 break;
527 734
528 case T_WKS: 735 case T_WKS:
529 if (dlen < sizeof(u_int32_t) + 1) 736 if (dlen < INT32SZ + 1)
530 break; 737 break;
531 bcopy(cp, (char *)&inaddr, sizeof(inaddr)); 738 bcopy(cp, (char *)&inaddr, INADDRSZ);
532 cp += sizeof(u_int32_t); 739 cp += INT32SZ;
533 fprintf(file, "\t%s %s ( ", 740 fprintf(file, "\t%s %s ( ",
534 inet_ntoa(inaddr), 741 inet_ntoa(inaddr),
535 deproto((int) *cp)); 742 deproto((int) *cp));
536 cp += sizeof(u_char); 743 cp += sizeof (u_char);
537 n = 0; 744 n = 0;
538 lcnt = 0; 745 lcnt = 0;
539 while (cp < cp1 + dlen) { 746 while (cp < cp1 + dlen) {
540 c = *cp++; 747 c = *cp++;
541 do { 748 do {
542 if (c & 0200) { 749 if (c & 0200) {
543 if (lcnt == 0) { 750 if (lcnt == 0) {
544 fputs("\n\t\t\t", file); 751 fputs("\n\t\t\t", file);
545 lcnt = 5; 752 lcnt = 5;
@@ -548,17 +755,83 @@ p_rr(cp, msg, file)
548 putc(' ', file); 755 putc(' ', file);
549 lcnt--; 756 lcnt--;
550 } 757 }
551 c <<= 1; 758 c <<= 1;
552 } while (++n & 07); 759 } while (++n & 07);
553 } 760 }
554 putc(')', file); 761 putc(')', file);
555 break; 762 break;
556 763
764 case T_KEY:
765 putc('\t', file);
766 keyflags = _getshort(cp);
767 cp += 2;
768 fprintf(file,"0x%04x", keyflags ); /* flags */
769 fprintf(file," %u", *cp++); /* protocol */
770 fprintf(file," %u (", *cp++); /* algorithm */
771
772 n = b64_ntop(cp, (cp1 + dlen) - cp,
773 base64_key, sizeof base64_key);
774 for (c = 0; c < n; ++c) {
775 if (0 == (c & 0x3F))
776 fprintf(file, "\n\t");
777 putc(base64_key[c], file); /* public key data */
778 }
779
780 fprintf(file, " )");
781 if (n < 0)
782 fprintf(file, "\t; BAD BASE64");
783 fflush(file);
784 cp = cp1 + dlen;
785 break;
786
787 case T_SIG:
788 type = _getshort((u_char*)cp);
789 cp += INT16SZ;
790 fprintf(file, " %s", p_type(type));
791 fprintf(file, "\t%u", *cp++); /* algorithm */
792 /* Check label value and print error if wrong. */
793 n = *cp++;
794 c = dn_count_labels (rrname);
795 if (n != c)
796 fprintf(file, "\t; LABELS WRONG (%d should be %d)\n\t",
797 n, c);
798 /* orig ttl */
799 n = _getlong((u_char*)cp);
800 if (n != tmpttl)
801 fprintf(file, " %u", n);
802 cp += INT32SZ;
803 /* sig expire */
804 fprintf(file, " (\n\t%s",
805 __p_secstodate(_getlong((u_char*)cp)));
806 cp += INT32SZ;
807 /* time signed */
808 fprintf(file, " %s", __p_secstodate(_getlong((u_char*)cp)));
809 cp += INT32SZ;
810 /* sig footprint */
811 fprintf(file," %u ", _getshort((u_char*)cp));
812 cp += INT16SZ;
813 /* signer's name */
814 cp = p_fqname(cp, msg, file);
815 n = b64_ntop(cp, (cp1 + dlen) - cp,
816 base64_key, sizeof base64_key);
817 for (c = 0; c < n; c++) {
818 if (0 == (c & 0x3F))
819 fprintf (file, "\n\t");
820 putc(base64_key[c], file); /* signature */
821 }
822 /* Clean up... */
823 fprintf(file, " )");
824 if (n < 0)
825 fprintf(file, "\t; BAD BASE64");
826 fflush(file);
827 cp = cp1+dlen;
828 break;
829
557#ifdef ALLOW_T_UNSPEC 830#ifdef ALLOW_T_UNSPEC
558 case T_UNSPEC: 831 case T_UNSPEC:
559 { 832 {
560 int NumBytes = 8; 833 int NumBytes = 8;
561 char *DataPtr; 834 u_char *DataPtr;
562 int i; 835 int i;
563 836
564 if (dlen < NumBytes) NumBytes = dlen; 837 if (dlen < NumBytes) NumBytes = dlen;
@@ -572,7 +845,7 @@ p_rr(cp, msg, file)
572#endif /* ALLOW_T_UNSPEC */ 845#endif /* ALLOW_T_UNSPEC */
573 846
574 default: 847 default:
575 fprintf(file,"\t?%d?", type); 848 fprintf(file, "\t?%d?", type);
576 cp += dlen; 849 cp += dlen;
577 } 850 }
578#if 0 851#if 0
@@ -581,136 +854,210 @@ p_rr(cp, msg, file)
581 putc('\n', file); 854 putc('\n', file);
582#endif 855#endif
583 if (cp - cp1 != dlen) { 856 if (cp - cp1 != dlen) {
584 fprintf(file,";; packet size error (found %d, dlen was %d)\n", 857 fprintf(file, ";; packet size error (found %ld, dlen was %d)\n",
585 cp - cp1, dlen); 858 (long)(cp - cp1), dlen);
586 cp = NULL; 859 cp = NULL;
587 } 860 }
588 return (cp); 861 return (cp);
589} 862}
590 863
591static char nbuf[40]; 864/*
865 * Names of RR classes and qclasses. Classes and qclasses are the same, except
866 * that C_ANY is a qclass but not a class. (You can ask for records of class
867 * C_ANY, but you can't have any records of that class in the database.)
868 */
869const struct res_sym __p_class_syms[] = {
870 {C_IN, "IN"},
871 {C_CHAOS, "CHAOS"},
872 {C_HS, "HS"},
873 {C_HS, "HESIOD"},
874 {C_ANY, "ANY"},
875 {C_IN, (char *)0}
876};
592 877
593/* 878/*
594 * Return a string for the type 879 * Names of RR types and qtypes. Types and qtypes are the same, except
880 * that T_ANY is a qtype but not a type. (You can ask for records of type
881 * T_ANY, but you can't have any records of that type in the database.)
595 */ 882 */
596char * 883const struct res_sym __p_type_syms[] = {
597__p_type(type) 884 {T_A, "A", "address"},
598 int type; 885 {T_NS, "NS", "name server"},
599{ 886 {T_MD, "MD", "mail destination (deprecated)"},
600 switch (type) { 887 {T_MF, "MF", "mail forwarder (deprecated)"},
601 case T_A: 888 {T_CNAME, "CNAME", "canonical name"},
602 return("A"); 889 {T_SOA, "SOA", "start of authority"},
603 case T_NS: /* authoritative server */ 890 {T_MB, "MB", "mailbox"},
604 return("NS"); 891 {T_MG, "MG", "mail group member"},
605 case T_CNAME: /* canonical name */ 892 {T_MR, "MR", "mail rename"},
606 return("CNAME"); 893 {T_NULL, "NULL", "null"},
607 case T_SOA: /* start of authority zone */ 894 {T_WKS, "WKS", "well-known service (deprecated)"},
608 return("SOA"); 895 {T_PTR, "PTR", "domain name pointer"},
609 case T_MB: /* mailbox domain name */ 896 {T_HINFO, "HINFO", "host information"},
610 return("MB"); 897 {T_MINFO, "MINFO", "mailbox information"},
611 case T_MG: /* mail group member */ 898 {T_MX, "MX", "mail exchanger"},
612 return("MG"); 899 {T_TXT, "TXT", "text"},
613 case T_MR: /* mail rename name */ 900 {T_RP, "RP", "responsible person"},
614 return("MR"); 901 {T_AFSDB, "AFSDB", "DCE or AFS server"},
615 case T_NULL: /* null resource record */ 902 {T_X25, "X25", "X25 address"},
616 return("NULL"); 903 {T_ISDN, "ISDN", "ISDN address"},
617 case T_WKS: /* well known service */ 904 {T_RT, "RT", "router"},
618 return("WKS"); 905 {T_NSAP, "NSAP", "nsap address"},
619 case T_PTR: /* domain name pointer */ 906 {T_NSAP_PTR, "NSAP_PTR", "domain name pointer"},
620 return("PTR"); 907 {T_SIG, "SIG", "signature"},
621 case T_HINFO: /* host information */ 908 {T_KEY, "KEY", "key"},
622 return("HINFO"); 909 {T_PX, "PX", "mapping information"},
623 case T_MINFO: /* mailbox information */ 910 {T_GPOS, "GPOS", "geographical position (withdrawn)"},
624 return("MINFO"); 911 {T_AAAA, "AAAA", "IPv6 address"},
625 case T_MX: /* mail routing info */ 912 {T_LOC, "LOC", "location"},
626 return("MX"); 913 {T_NXT, "NXT", "next valid name (unimplemented)"},
627 case T_TXT: /* text */ 914 {T_EID, "EID", "endpoint identifier (unimplemented)"},
628 return("TXT"); 915 {T_NIMLOC, "NIMLOC", "NIMROD locator (unimplemented)"},
629 case T_RP: /* responsible person */ 916 {T_SRV, "SRV", "server selection"},
630 return("RP"); 917 {T_ATMA, "ATMA", "ATM address (unimplemented)"},
631 case T_AFSDB: /* AFS cell database */ 918 {T_IXFR, "IXFR", "incremental zone transfer"},
632 return("AFSDB"); 919 {T_AXFR, "AXFR", "zone transfer"},
633 case T_AXFR: /* zone transfer */ 920 {T_MAILB, "MAILB", "mailbox-related data (deprecated)"},
634 return("AXFR"); 921 {T_MAILA, "MAILA", "mail agent (deprecated)"},
635 case T_MAILB: /* mail box */ 922 {T_UINFO, "UINFO", "user information (nonstandard)"},
636 return("MAILB"); 923 {T_UID, "UID", "user ID (nonstandard)"},
637 case T_MAILA: /* mail address */ 924 {T_GID, "GID", "group ID (nonstandard)"},
638 return("MAILA"); 925 {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 926#ifdef ALLOW_T_UNSPEC
648 case T_UNSPEC: 927 {T_UNSPEC, "UNSPEC", "unspecified data (nonstandard)"},
649 return("UNSPEC");
650#endif /* ALLOW_T_UNSPEC */ 928#endif /* ALLOW_T_UNSPEC */
929 {T_ANY, "ANY", "\"any\""},
930 {0, NULL, NULL}
931};
651 932
652 default: 933int
653 (void)sprintf(nbuf, "%d", type); 934__sym_ston(syms, name, success)
654 return(nbuf); 935 const struct res_sym *syms;
936 char *name;
937 int *success;
938{
939 for (; syms->name != 0; syms++) {
940 if (strcasecmp (name, syms->name) == 0) {
941 if (success)
942 *success = 1;
943 return (syms->number);
944 }
655 } 945 }
946 if (success)
947 *success = 0;
948 return (syms->number); /* The default value. */
949}
950
951const char *
952__sym_ntos(syms, number, success)
953 const struct res_sym *syms;
954 int number;
955 int *success;
956{
957 static char unname[20];
958
959 for (; syms->name != 0; syms++) {
960 if (number == syms->number) {
961 if (success)
962 *success = 1;
963 return (syms->name);
964 }
965 }
966
967 snprintf(unname, sizeof unname, "%d", number);
968 if (success)
969 *success = 0;
970 return (unname);
971}
972
973
974const char *
975__sym_ntop(syms, number, success)
976 const struct res_sym *syms;
977 int number;
978 int *success;
979{
980 static char unname[20];
981
982 for (; syms->name != 0; syms++) {
983 if (number == syms->number) {
984 if (success)
985 *success = 1;
986 return (syms->humanname);
987 }
988 }
989 snprintf(unname, sizeof unname, "%d", number);
990 if (success)
991 *success = 0;
992 return (unname);
993}
994
995/*
996 * Return a string for the type
997 */
998const char *
999__p_type(type)
1000 int type;
1001{
1002 return (__sym_ntos (__p_type_syms, type, (int *)0));
656} 1003}
657 1004
658/* 1005/*
659 * Return a mnemonic for class 1006 * Return a mnemonic for class
660 */ 1007 */
661char * 1008const char *
662__p_class(class) 1009__p_class(class)
663 int class; 1010 int class;
664{ 1011{
665 1012 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} 1013}
678 1014
679/* 1015/*
680 * Return a mnemonic for an option 1016 * Return a mnemonic for an option
681 */ 1017 */
682static char * 1018const char *
683p_option(option) 1019__p_option(option)
684 u_int32_t option; 1020 u_long option;
685{ 1021{
1022 static char nbuf[40];
1023
686 switch (option) { 1024 switch (option) {
687 case RES_INIT: return "init"; 1025 case RES_INIT: return "init";
688 case RES_DEBUG: return "debug"; 1026 case RES_DEBUG: return "debug";
689 case RES_AAONLY: return "aaonly"; 1027 case RES_AAONLY: return "aaonly(unimpl)";
690 case RES_USEVC: return "usevc"; 1028 case RES_USEVC: return "usevc";
691 case RES_PRIMARY: return "primry"; 1029 case RES_PRIMARY: return "primry(unimpl)";
692 case RES_IGNTC: return "igntc"; 1030 case RES_IGNTC: return "igntc";
693 case RES_RECURSE: return "recurs"; 1031 case RES_RECURSE: return "recurs";
694 case RES_DEFNAMES: return "defnam"; 1032 case RES_DEFNAMES: return "defnam";
695 case RES_STAYOPEN: return "styopn"; 1033 case RES_STAYOPEN: return "styopn";
696 case RES_DNSRCH: return "dnsrch"; 1034 case RES_DNSRCH: return "dnsrch";
697 default: sprintf(nbuf, "?0x%x?", option); return nbuf; 1035 case RES_INSECURE1: return "insecure1";
1036 case RES_INSECURE2: return "insecure2";
1037 case RES_USE_INET6: return "inet6";
1038 case RES_USE_EDNS0: return "edns0";
1039 default:
1040 snprintf(nbuf, sizeof nbuf, "?0x%lx?", (u_long)option);
1041 return (nbuf);
698 } 1042 }
699} 1043}
700 1044
701/* 1045/*
702 * Return a mnemonic for a time to live 1046 * Return a mnemonic for a time to live
703 */ 1047 */
704char * 1048const char *
705__p_time(value) 1049p_time(value)
706 u_int32_t value; 1050 u_int32_t value;
707{ 1051{
1052 static char nbuf[40];
1053 char *ebuf;
708 int secs, mins, hours, days; 1054 int secs, mins, hours, days;
709 register char *p; 1055 register char *p;
1056 int tmp;
710 1057
711 if (value == 0) { 1058 if (value == 0) {
712 strcpy(nbuf, "0 secs"); 1059 strlcpy(nbuf, "0 secs", sizeof nbuf);
713 return(nbuf); 1060 return (nbuf);
714 } 1061 }
715 1062
716 secs = value % 60; 1063 secs = value % 60;
@@ -724,26 +1071,490 @@ __p_time(value)
724 1071
725#define PLURALIZE(x) x, (x == 1) ? "" : "s" 1072#define PLURALIZE(x) x, (x == 1) ? "" : "s"
726 p = nbuf; 1073 p = nbuf;
1074 ebuf = nbuf + sizeof(nbuf);
727 if (days) { 1075 if (days) {
728 (void)sprintf(p, "%d day%s", PLURALIZE(days)); 1076 if ((tmp = snprintf(p, ebuf - p, "%d day%s",
729 while (*++p); 1077 PLURALIZE(days))) >= ebuf - nbuf || tmp < 0)
1078 goto full;
1079 p += tmp;
730 } 1080 }
731 if (hours) { 1081 if (hours) {
732 if (days) 1082 if (days)
733 *p++ = ' '; 1083 *p++ = ' ';
734 (void)sprintf(p, "%d hour%s", PLURALIZE(hours)); 1084 if (p >= ebuf)
735 while (*++p); 1085 goto full;
1086 if ((tmp = snprintf(p, ebuf - p, "%d hour%s",
1087 PLURALIZE(hours))) >= ebuf - nbuf || tmp < 0)
1088 goto full;
1089 p += tmp;
736 } 1090 }
737 if (mins) { 1091 if (mins) {
738 if (days || hours) 1092 if (days || hours)
739 *p++ = ' '; 1093 *p++ = ' ';
740 (void)sprintf(p, "%d min%s", PLURALIZE(mins)); 1094 if (p >= ebuf)
741 while (*++p); 1095 goto full;
1096 if ((tmp = snprintf(p, ebuf - p, "%d min%s",
1097 PLURALIZE(mins))) >= ebuf - nbuf || tmp < 0)
1098 goto full;
1099 p += tmp;
742 } 1100 }
743 if (secs || ! (days || hours || mins)) { 1101 if (secs || ! (days || hours || mins)) {
744 if (days || hours || mins) 1102 if (days || hours || mins)
745 *p++ = ' '; 1103 *p++ = ' ';
746 (void)sprintf(p, "%d sec%s", PLURALIZE(secs)); 1104 if (p >= ebuf)
1105 goto full;
1106 if ((tmp = snprintf(p, ebuf - p, "%d sec%s",
1107 PLURALIZE(secs))) >= ebuf - nbuf || tmp < 0)
1108 goto full;
1109 }
1110 return (nbuf);
1111full:
1112 p = nbuf + sizeof(nbuf) - 4;
1113 *p++ = '.';
1114 *p++ = '.';
1115 *p++ = '.';
1116 *p++ = '\0';
1117 return (nbuf);
1118}
1119
1120/*
1121 * routines to convert between on-the-wire RR format and zone file format.
1122 * Does not contain conversion to/from decimal degrees; divide or multiply
1123 * by 60*60*1000 for that.
1124 */
1125
1126static unsigned int poweroften[10] = {1, 10, 100, 1000, 10000, 100000,
1127 1000000,10000000,100000000,1000000000};
1128
1129/* takes an XeY precision/size value, returns a string representation. */
1130static const char *
1131precsize_ntoa(prec)
1132 u_int8_t prec;
1133{
1134 static char retbuf[sizeof "90000000.00"];
1135 unsigned long val;
1136 int mantissa, exponent;
1137
1138 mantissa = (int)((prec >> 4) & 0x0f) % 10;
1139 exponent = (int)((prec >> 0) & 0x0f) % 10;
1140
1141 val = mantissa * poweroften[exponent];
1142
1143 (void) snprintf(retbuf, sizeof retbuf, "%ld.%.2ld", val/100, val%100);
1144 return (retbuf);
1145}
1146
1147/* converts ascii size/precision X * 10**Y(cm) to 0xXY. moves pointer. */
1148static u_int8_t
1149precsize_aton(strptr)
1150 char **strptr;
1151{
1152 unsigned int mval = 0, cmval = 0;
1153 u_int8_t retval = 0;
1154 register char *cp;
1155 register int exponent;
1156 register int mantissa;
1157
1158 cp = *strptr;
1159
1160 while (isdigit(*cp))
1161 mval = mval * 10 + (*cp++ - '0');
1162
1163 if (*cp == '.') { /* centimeters */
1164 cp++;
1165 if (isdigit(*cp)) {
1166 cmval = (*cp++ - '0') * 10;
1167 if (isdigit(*cp)) {
1168 cmval += (*cp++ - '0');
1169 }
1170 }
1171 }
1172 cmval = (mval * 100) + cmval;
1173
1174 for (exponent = 0; exponent < 9; exponent++)
1175 if (cmval < poweroften[exponent+1])
1176 break;
1177
1178 mantissa = cmval / poweroften[exponent];
1179 if (mantissa > 9)
1180 mantissa = 9;
1181
1182 retval = (mantissa << 4) | exponent;
1183
1184 *strptr = cp;
1185
1186 return (retval);
1187}
1188
1189/* converts ascii lat/lon to unsigned encoded 32-bit number. moves pointer. */
1190static u_int32_t
1191latlon2ul(latlonstrptr,which)
1192 char **latlonstrptr;
1193 int *which;
1194{
1195 register char *cp;
1196 u_int32_t retval;
1197 int deg = 0, min = 0, secs = 0, secsfrac = 0;
1198
1199 cp = *latlonstrptr;
1200
1201 while (isdigit(*cp))
1202 deg = deg * 10 + (*cp++ - '0');
1203
1204 while (isspace(*cp))
1205 cp++;
1206
1207 if (!(isdigit(*cp)))
1208 goto fndhemi;
1209
1210 while (isdigit(*cp))
1211 min = min * 10 + (*cp++ - '0');
1212
1213 while (isspace(*cp))
1214 cp++;
1215
1216 if (!(isdigit(*cp)))
1217 goto fndhemi;
1218
1219 while (isdigit(*cp))
1220 secs = secs * 10 + (*cp++ - '0');
1221
1222 if (*cp == '.') { /* decimal seconds */
1223 cp++;
1224 if (isdigit(*cp)) {
1225 secsfrac = (*cp++ - '0') * 100;
1226 if (isdigit(*cp)) {
1227 secsfrac += (*cp++ - '0') * 10;
1228 if (isdigit(*cp)) {
1229 secsfrac += (*cp++ - '0');
1230 }
1231 }
1232 }
1233 }
1234
1235 while (!isspace(*cp)) /* if any trailing garbage */
1236 cp++;
1237
1238 while (isspace(*cp))
1239 cp++;
1240
1241 fndhemi:
1242 switch (*cp) {
1243 case 'N': case 'n':
1244 case 'E': case 'e':
1245 retval = ((unsigned)1<<31)
1246 + (((((deg * 60) + min) * 60) + secs) * 1000)
1247 + secsfrac;
1248 break;
1249 case 'S': case 's':
1250 case 'W': case 'w':
1251 retval = ((unsigned)1<<31)
1252 - (((((deg * 60) + min) * 60) + secs) * 1000)
1253 - secsfrac;
1254 break;
1255 default:
1256 retval = 0; /* invalid value -- indicates error */
1257 break;
1258 }
1259
1260 switch (*cp) {
1261 case 'N': case 'n':
1262 case 'S': case 's':
1263 *which = 1; /* latitude */
1264 break;
1265 case 'E': case 'e':
1266 case 'W': case 'w':
1267 *which = 2; /* longitude */
1268 break;
1269 default:
1270 *which = 0; /* error */
1271 break;
1272 }
1273
1274 cp++; /* skip the hemisphere */
1275
1276 while (!isspace(*cp)) /* if any trailing garbage */
1277 cp++;
1278
1279 while (isspace(*cp)) /* move to next field */
1280 cp++;
1281
1282 *latlonstrptr = cp;
1283
1284 return (retval);
1285}
1286
1287/* converts a zone file representation in a string to an RDATA on-the-wire
1288 * representation. */
1289int
1290loc_aton(ascii, binary)
1291 const char *ascii;
1292 u_char *binary;
1293{
1294 const char *maxcp;
1295 u_char *bcp;
1296 char *cp;
1297
1298 u_int32_t latit = 0, longit = 0, alt = 0;
1299 u_int32_t lltemp1 = 0, lltemp2 = 0;
1300 int altmeters = 0, altfrac = 0, altsign = 1;
1301 u_int8_t hp = 0x16; /* default = 1e6 cm = 10000.00m = 10km */
1302 u_int8_t vp = 0x13; /* default = 1e3 cm = 10.00m */
1303 u_int8_t siz = 0x12; /* default = 1e2 cm = 1.00m */
1304 int which1 = 0, which2 = 0;
1305
1306 cp = (char *)ascii;
1307 maxcp = cp + strlen(ascii);
1308
1309 lltemp1 = latlon2ul(&cp, &which1);
1310
1311 lltemp2 = latlon2ul(&cp, &which2);
1312
1313 switch (which1 + which2) {
1314 case 3: /* 1 + 2, the only valid combination */
1315 if ((which1 == 1) && (which2 == 2)) { /* normal case */
1316 latit = lltemp1;
1317 longit = lltemp2;
1318 } else if ((which1 == 2) && (which2 == 1)) { /* reversed */
1319 longit = lltemp1;
1320 latit = lltemp2;
1321 } else { /* some kind of brokenness */
1322 return (0);
1323 }
1324 break;
1325 default: /* we didn't get one of each */
1326 return (0);
1327 }
1328
1329 /* altitude */
1330 if (*cp == '-') {
1331 altsign = -1;
1332 cp++;
1333 }
1334
1335 if (*cp == '+')
1336 cp++;
1337
1338 while (isdigit(*cp))
1339 altmeters = altmeters * 10 + (*cp++ - '0');
1340
1341 if (*cp == '.') { /* decimal meters */
1342 cp++;
1343 if (isdigit(*cp)) {
1344 altfrac = (*cp++ - '0') * 10;
1345 if (isdigit(*cp)) {
1346 altfrac += (*cp++ - '0');
1347 }
1348 }
1349 }
1350
1351 alt = (10000000 + (altsign * (altmeters * 100 + altfrac)));
1352
1353 while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
1354 cp++;
1355
1356 while (isspace(*cp) && (cp < maxcp))
1357 cp++;
1358
1359 if (cp >= maxcp)
1360 goto defaults;
1361
1362 siz = precsize_aton(&cp);
1363
1364 while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
1365 cp++;
1366
1367 while (isspace(*cp) && (cp < maxcp))
1368 cp++;
1369
1370 if (cp >= maxcp)
1371 goto defaults;
1372
1373 hp = precsize_aton(&cp);
1374
1375 while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
1376 cp++;
1377
1378 while (isspace(*cp) && (cp < maxcp))
1379 cp++;
1380
1381 if (cp >= maxcp)
1382 goto defaults;
1383
1384 vp = precsize_aton(&cp);
1385
1386 defaults:
1387
1388 bcp = binary;
1389 *bcp++ = (u_int8_t) 0; /* version byte */
1390 *bcp++ = siz;
1391 *bcp++ = hp;
1392 *bcp++ = vp;
1393 PUTLONG(latit,bcp);
1394 PUTLONG(longit,bcp);
1395 PUTLONG(alt,bcp);
1396
1397 return (16); /* size of RR in octets */
1398}
1399
1400const char *
1401loc_ntoa(binary, ascii)
1402 const u_char *binary;
1403 char *ascii;
1404{
1405 return loc_ntoal(binary, ascii, 255);
1406}
1407
1408/* takes an on-the-wire LOC RR and formats it in a human readable format. */
1409static const char *
1410loc_ntoal(binary, ascii, ascii_len)
1411 const u_char *binary;
1412 char *ascii;
1413 int ascii_len;
1414{
1415 static char *error = "?";
1416 register const u_char *cp = binary;
1417
1418 int latdeg, latmin, latsec, latsecfrac;
1419 int longdeg, longmin, longsec, longsecfrac;
1420 char northsouth, eastwest;
1421 int altmeters, altfrac, altsign;
1422
1423 const int referencealt = 100000 * 100;
1424
1425 int32_t latval, longval, altval;
1426 u_int32_t templ;
1427 u_int8_t sizeval, hpval, vpval, versionval;
1428
1429 char *sizestr, *hpstr, *vpstr;
1430
1431 versionval = *cp++;
1432
1433 if (versionval) {
1434 snprintf(ascii, ascii_len, "; error: unknown LOC RR version");
1435 return (ascii);
747 } 1436 }
748 return(nbuf); 1437
1438 sizeval = *cp++;
1439
1440 hpval = *cp++;
1441 vpval = *cp++;
1442
1443 GETLONG(templ, cp);
1444 latval = (templ - ((unsigned)1<<31));
1445
1446 GETLONG(templ, cp);
1447 longval = (templ - ((unsigned)1<<31));
1448
1449 GETLONG(templ, cp);
1450 if (templ < referencealt) { /* below WGS 84 spheroid */
1451 altval = referencealt - templ;
1452 altsign = -1;
1453 } else {
1454 altval = templ - referencealt;
1455 altsign = 1;
1456 }
1457
1458 if (latval < 0) {
1459 northsouth = 'S';
1460 latval = -latval;
1461 } else
1462 northsouth = 'N';
1463
1464 latsecfrac = latval % 1000;
1465 latval = latval / 1000;
1466 latsec = latval % 60;
1467 latval = latval / 60;
1468 latmin = latval % 60;
1469 latval = latval / 60;
1470 latdeg = latval;
1471
1472 if (longval < 0) {
1473 eastwest = 'W';
1474 longval = -longval;
1475 } else
1476 eastwest = 'E';
1477
1478 longsecfrac = longval % 1000;
1479 longval = longval / 1000;
1480 longsec = longval % 60;
1481 longval = longval / 60;
1482 longmin = longval % 60;
1483 longval = longval / 60;
1484 longdeg = longval;
1485
1486 altfrac = altval % 100;
1487 altmeters = (altval / 100) * altsign;
1488
1489 if ((sizestr = strdup(precsize_ntoa(sizeval))) == NULL)
1490 sizestr = error;
1491 if ((hpstr = strdup(precsize_ntoa(hpval))) == NULL)
1492 hpstr = error;
1493 if ((vpstr = strdup(precsize_ntoa(vpval))) == NULL)
1494 vpstr = error;
1495
1496 snprintf(ascii, ascii_len,
1497 "%d %.2d %.2d.%.3d %c %d %.2d %.2d.%.3d %c %d.%.2dm %sm %sm %sm",
1498 latdeg, latmin, latsec, latsecfrac, northsouth,
1499 longdeg, longmin, longsec, longsecfrac, eastwest,
1500 altmeters, altfrac, sizestr, hpstr, vpstr);
1501
1502 if (sizestr != error)
1503 free(sizestr);
1504 if (hpstr != error)
1505 free(hpstr);
1506 if (vpstr != error)
1507 free(vpstr);
1508
1509 return (ascii);
1510}
1511
1512
1513/* Return the number of DNS hierarchy levels in the name. */
1514int
1515__dn_count_labels(name)
1516 char *name;
1517{
1518 int i, len, count;
1519
1520 len = strlen(name);
1521
1522 for(i = 0, count = 0; i < len; i++) {
1523 if (name[i] == '.')
1524 count++;
1525 }
1526
1527 /* don't count initial wildcard */
1528 if (name[0] == '*')
1529 if (count)
1530 count--;
1531
1532 /* don't count the null label for root. */
1533 /* if terminating '.' not found, must adjust */
1534 /* count to include last label */
1535 if (len > 0 && name[len-1] != '.')
1536 count++;
1537 return (count);
1538}
1539
1540
1541/*
1542 * Make dates expressed in seconds-since-Jan-1-1970 easy to read.
1543 * SIG records are required to be printed like this, by the Secure DNS RFC.
1544 */
1545char *
1546__p_secstodate (secs)
1547 unsigned long secs;
1548{
1549 static char output[15]; /* YYYYMMDDHHMMSS and null */
1550 time_t clock = secs;
1551 struct tm *time;
1552
1553 time = gmtime(&clock);
1554 time->tm_year += 1900;
1555 time->tm_mon += 1;
1556 snprintf(output, sizeof output, "%04d%02d%02d%02d%02d%02d",
1557 time->tm_year, time->tm_mon, time->tm_mday,
1558 time->tm_hour, time->tm_min, time->tm_sec);
1559 return (output);
749} 1560}
diff --git a/src/lib/libc/net/res_init.c b/src/lib/libc/net/res_init.c
index 33cc8d39f1..c55c7763a4 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.27 2002/07/25 21:13:45 deraadt 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,167 @@
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.27 2002/07/25 21:13:45 deraadt 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/*-------------------------------------- info about "sortlist" --------------
90 * Marc Majka 1994/04/16
91 * Allan Nathanson 1994/10/29 (BIND 4.9.3.x)
92 *
93 * NetInfo resolver configuration directory support.
94 *
95 * Allow a NetInfo directory to be created in the hierarchy which
96 * contains the same information as the resolver configuration file.
97 *
98 * - The local domain name is stored as the value of the "domain" property.
99 * - The Internet address(es) of the name server(s) are stored as values
100 * of the "nameserver" property.
101 * - The name server addresses are stored as values of the "nameserver"
102 * property.
103 * - The search list for host-name lookup is stored as values of the
104 * "search" property.
105 * - The sortlist comprised of IP address netmask pairs are stored as
106 * values of the "sortlist" property. The IP address and optional netmask
107 * should be separated by a slash (/) or ampersand (&) character.
108 * - Internal resolver variables can be set from the value of the "options"
109 * property.
110 */
111
112static void res_setoptions(char *, char *);
75 113
76static void res_setoptions __P((char *, char *)); 114#ifdef RESOLVSORT
77static u_int32_t net_mask __P((struct in_addr)); 115static const char sort_mask[] = "/&";
116#define ISSORTMASK(ch) (strchr(sort_mask, ch) != NULL)
117static u_int32_t net_mask(struct in_addr);
118#endif
78 119
79/* 120/*
80 * Resolver state default settings 121 * Resolver state default settings.
81 */ 122 */
82 123
83struct __res_state _res = { 124struct __res_state _res
84 RES_TIMEOUT, /* retransmition time interval */ 125# if defined(__BIND_RES_TEXT)
85 4, /* number of times to retransmit */ 126 = { RES_TIMEOUT, } /* Motorola, et al. */
86 RES_DEFAULT, /* options flags */ 127# endif
87 1, /* number of name servers */ 128 ;
88}; 129#ifdef INET6
130struct __res_state_ext _res_ext;
131#endif /* INET6 */
89 132
90/* 133/*
91 * Set up default settings. If the configuration file exist, the values 134 * Set up default settings. If the configuration file exist, the values
92 * there will have precedence. Otherwise, the server address is set to 135 * there will have precedence. Otherwise, the server address is set to
93 * INADDR_ANY and the default domain name comes from the gethostname(). 136 * INADDR_ANY and the default domain name comes from the gethostname().
94 * 137 *
95 * The configuration file should only be used if you want to redefine your 138 * 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. 139 * rather than INADDR_ANY ("0.0.0.0") as the default name server address
140 * since it was noted that INADDR_ANY actually meant ``the first interface
141 * you "ifconfig"'d at boot time'' and if this was a SLIP or PPP interface,
142 * it had to be "up" in order for you to reach your own name server. It
143 * was later decided that since the recommended practice is to always
144 * install local static routes through 127.0.0.1 for all your network
145 * interfaces, that we could solve this problem without a code change.
146 *
147 * The configuration file should always be used, since it is the only way
148 * to specify a default domain. If you are running a server on your local
149 * machine, you should say "nameserver 0.0.0.0" or "nameserver 127.0.0.1"
150 * in the configuration file.
97 * 151 *
98 * Return 0 if completes successfully, -1 on error 152 * Return 0 if completes successfully, -1 on error
99 */ 153 */
154int
100res_init() 155res_init()
101{ 156{
102 register FILE *fp; 157 register FILE *fp;
103 register char *cp, **pp, *net; 158 register char *cp, **pp;
104 register int n; 159 register int n;
105 char buf[BUFSIZ], buf2[BUFSIZ]; 160 char buf[BUFSIZ];
106 int nserv = 0; /* number of nameserver records read from file */ 161 int nserv = 0; /* number of nameserver records read from file */
107 int haveenv = 0; 162 int haveenv = 0;
108 int havesearch = 0; 163 int havesearch = 0;
164 size_t len;
165#ifdef RESOLVSORT
109 int nsort = 0; 166 int nsort = 0;
110 u_long mask; 167 char *net;
168#endif
169#ifndef RFC1535
170 int dots;
171#endif
172
173 /*
174 * These three fields used to be statically initialized. This made
175 * it hard to use this code in a shared library. It is necessary,
176 * now that we're doing dynamic initialization here, that we preserve
177 * the old semantics: if an application modifies one of these three
178 * fields of _res before res_init() is called, res_init() will not
179 * alter them. Of course, if an application is setting them to
180 * _zero_ before calling res_init(), hoping to override what used
181 * to be the static default, we can't detect it and unexpected results
182 * will follow. Zero for any of these fields would make no sense,
183 * so one can safely assume that the applications were already getting
184 * unexpected results.
185 *
186 * _res.options is tricky since some apps were known to diddle the bits
187 * before res_init() was first called. We can't replicate that semantic
188 * with dynamic initialization (they may have turned bits off that are
189 * set in RES_DEFAULT). Our solution is to declare such applications
190 * "broken". They could fool us by setting RES_INIT but none do (yet).
191 */
192 if (!_res.retrans)
193 _res.retrans = RES_TIMEOUT;
194 if (!_res.retry)
195 _res.retry = 4;
196 if (!(_res.options & RES_INIT))
197 _res.options = RES_DEFAULT;
111 198
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 199#ifdef USELOOPBACK
116 _res.nsaddr.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1); 200 _res.nsaddr.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1);
117#else 201#else
118 _res.nsaddr.sin_addr.s_addr = INADDR_ANY; 202 _res.nsaddr.sin_addr.s_addr = INADDR_ANY;
119#endif 203#endif
204 _res.nsaddr.sin_family = AF_INET;
205 _res.nsaddr.sin_port = htons(NAMESERVER_PORT);
206 _res.nsaddr.sin_len = sizeof(struct sockaddr_in);
207#ifdef INET6
208 if (sizeof(_res_ext.nsaddr) >= _res.nsaddr.sin_len)
209 memcpy(&_res_ext.nsaddr, &_res.nsaddr, _res.nsaddr.sin_len);
210#endif
120 _res.nscount = 1; 211 _res.nscount = 1;
121 _res.ndots = 1; 212 _res.ndots = 1;
122 _res.pfcode = 0; 213 _res.pfcode = 0;
123 strncpy(_res.lookups, "f", sizeof _res.lookups); 214 strlcpy(_res.lookups, "f", sizeof _res.lookups);
124 215
125 /* Allow user to override the local domain definition */ 216 /* Allow user to override the local domain definition */
126 if ((cp = getenv("LOCALDOMAIN")) != NULL) { 217 if (issetugid() == 0 && (cp = getenv("LOCALDOMAIN")) != NULL) {
127 (void)strncpy(_res.defdname, cp, sizeof(_res.defdname) - 1); 218 strlcpy(_res.defdname, cp, sizeof(_res.defdname));
128 if ((cp = strpbrk(_res.defdname, " \t\n")) != NULL)
129 *cp = '\0';
130 haveenv++; 219 haveenv++;
131 220
132 /* 221 /*
@@ -140,7 +229,7 @@ res_init()
140 pp = _res.dnsrch; 229 pp = _res.dnsrch;
141 *pp++ = cp; 230 *pp++ = cp;
142 for (n = 0; *cp && pp < _res.dnsrch + MAXDNSRCH; cp++) { 231 for (n = 0; *cp && pp < _res.dnsrch + MAXDNSRCH; cp++) {
143 if (*cp == '\n') /* silly backwards compat */ 232 if (*cp == '\n') /* silly backwards compat */
144 break; 233 break;
145 else if (*cp == ' ' || *cp == '\t') { 234 else if (*cp == ' ' || *cp == '\t') {
146 *cp = 0; 235 *cp = 0;
@@ -158,16 +247,29 @@ res_init()
158 *pp++ = 0; 247 *pp++ = 0;
159 } 248 }
160 249
250#define MATCH(line, name) \
251 (!strncmp(line, name, sizeof(name) - 1) && \
252 (line[sizeof(name) - 1] == ' ' || \
253 line[sizeof(name) - 1] == '\t'))
254
161 if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) { 255 if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) {
162 strncpy(_res.lookups, "bf", sizeof _res.lookups); 256 strlcpy(_res.lookups, "bf", sizeof _res.lookups);
163 257
164 /* read the config file */ 258 /* read the config file */
165 while (fgets(buf, sizeof(buf), fp) != NULL) { 259 buf[0] = '\0';
260 while ((cp = fgetln(fp, &len)) != NULL) {
261 /* skip lines that are too long or zero length */
262 if (len >= sizeof(buf) || len == 0)
263 continue;
264 (void)memcpy(buf, cp, len);
265 buf[len] = '\0';
166 /* skip comments */ 266 /* skip comments */
167 if ((*buf == ';') || (*buf == '#')) 267 if ((cp = strpbrk(buf, ";#")) != NULL)
268 *cp = '\0';
269 if (buf[0] == '\0')
168 continue; 270 continue;
169 /* read default domain name */ 271 /* read default domain name */
170 if (!strncmp(buf, "domain", sizeof("domain") - 1)) { 272 if (MATCH(buf, "domain")) {
171 if (haveenv) /* skip if have from environ */ 273 if (haveenv) /* skip if have from environ */
172 continue; 274 continue;
173 cp = buf + sizeof("domain") - 1; 275 cp = buf + sizeof("domain") - 1;
@@ -175,15 +277,14 @@ res_init()
175 cp++; 277 cp++;
176 if ((*cp == '\0') || (*cp == '\n')) 278 if ((*cp == '\0') || (*cp == '\n'))
177 continue; 279 continue;
178 (void)strncpy(_res.defdname, cp, 280 strlcpy(_res.defdname, cp, sizeof(_res.defdname));
179 sizeof(_res.defdname) - 1);
180 if ((cp = strpbrk(_res.defdname, " \t\n")) != NULL) 281 if ((cp = strpbrk(_res.defdname, " \t\n")) != NULL)
181 *cp = '\0'; 282 *cp = '\0';
182 havesearch = 0; 283 havesearch = 0;
183 continue; 284 continue;
184 } 285 }
185 /* lookup types */ 286 /* lookup types */
186 if (!strncmp(buf, "lookup", sizeof("lookup") -1)) { 287 if (MATCH(buf, "lookup")) {
187 char *sp = NULL; 288 char *sp = NULL;
188 289
189 bzero(_res.lookups, sizeof _res.lookups); 290 bzero(_res.lookups, sizeof _res.lookups);
@@ -210,7 +311,7 @@ res_init()
210 continue; 311 continue;
211 } 312 }
212 /* set search list */ 313 /* set search list */
213 if (!strncmp(buf, "search", sizeof("search") - 1)) { 314 if (MATCH(buf, "search")) {
214 if (haveenv) /* skip if have from environ */ 315 if (haveenv) /* skip if have from environ */
215 continue; 316 continue;
216 cp = buf + sizeof("search") - 1; 317 cp = buf + sizeof("search") - 1;
@@ -218,8 +319,7 @@ res_init()
218 cp++; 319 cp++;
219 if ((*cp == '\0') || (*cp == '\n')) 320 if ((*cp == '\0') || (*cp == '\n'))
220 continue; 321 continue;
221 (void)strncpy(_res.defdname, cp, 322 strlcpy(_res.defdname, cp, sizeof(_res.defdname));
222 sizeof(_res.defdname) - 1);
223 if ((cp = strchr(_res.defdname, '\n')) != NULL) 323 if ((cp = strchr(_res.defdname, '\n')) != NULL)
224 *cp = '\0'; 324 *cp = '\0';
225 /* 325 /*
@@ -247,122 +347,256 @@ res_init()
247 continue; 347 continue;
248 } 348 }
249 /* read nameservers to query */ 349 /* read nameservers to query */
250 if (!strncmp(buf, "nameserver", sizeof("nameserver") - 1) && 350 if (MATCH(buf, "nameserver") && nserv < MAXNS) {
251 nserv < MAXNS) { 351#ifdef INET6
252 struct in_addr a; 352 char *q;
353 struct addrinfo hints, *res;
354 char pbuf[NI_MAXSERV];
355#else
356 struct in_addr a;
357#endif /* INET6 */
253 358
254 cp = buf + sizeof("nameserver") - 1; 359 cp = buf + sizeof("nameserver") - 1;
255 while (*cp == ' ' || *cp == '\t') 360 while (*cp == ' ' || *cp == '\t')
256 cp++; 361 cp++;
362#ifdef INET6
363 if ((*cp == '\0') || (*cp == '\n'))
364 continue;
365 for (q = cp; *q; q++) {
366 if (isspace(*q)) {
367 *q = '\0';
368 break;
369 }
370 }
371 memset(&hints, 0, sizeof(hints));
372 hints.ai_flags = AI_NUMERICHOST;
373 hints.ai_socktype = SOCK_DGRAM;
374 snprintf(pbuf, sizeof(pbuf), "%u", NAMESERVER_PORT);
375 res = NULL;
376 if (getaddrinfo(cp, pbuf, &hints, &res) == 0 &&
377 res->ai_next == NULL) {
378 if (res->ai_addrlen <= sizeof(_res_ext.nsaddr_list[nserv])) {
379 memcpy(&_res_ext.nsaddr_list[nserv], res->ai_addr,
380 res->ai_addrlen);
381 } else {
382 memset(&_res_ext.nsaddr_list[nserv], 0,
383 sizeof(_res_ext.nsaddr_list[nserv]));
384 }
385 if (res->ai_addrlen <= sizeof(_res.nsaddr_list[nserv])) {
386 memcpy(&_res.nsaddr_list[nserv], res->ai_addr,
387 res->ai_addrlen);
388 } else {
389 memset(&_res.nsaddr_list[nserv], 0,
390 sizeof(_res.nsaddr_list[nserv]));
391 }
392 nserv++;
393 }
394 if (res)
395 freeaddrinfo(res);
396#else /* INET6 */
257 if ((*cp != '\0') && (*cp != '\n') && inet_aton(cp, &a)) { 397 if ((*cp != '\0') && (*cp != '\n') && inet_aton(cp, &a)) {
258 _res.nsaddr_list[nserv].sin_len = sizeof(struct sockaddr_in); 398 _res.nsaddr_list[nserv].sin_addr = a;
259 _res.nsaddr_list[nserv].sin_family = AF_INET; 399 _res.nsaddr_list[nserv].sin_family = AF_INET;
260 _res.nsaddr_list[nserv].sin_port = 400 _res.nsaddr_list[nserv].sin_port =
261 htons(NAMESERVER_PORT); 401 htons(NAMESERVER_PORT);
262 _res.nsaddr_list[nserv].sin_addr = a; 402 _res.nsaddr_list[nserv].sin_len =
403 sizeof(struct sockaddr_in);
263 nserv++; 404 nserv++;
264 } 405 }
406#endif /* INET6 */
265 continue; 407 continue;
266 } 408 }
267 if (!strncmp(buf, "sortlist", sizeof("sortlist") - 1)) { 409#ifdef RESOLVSORT
410 if (MATCH(buf, "sortlist")) {
268 struct in_addr a; 411 struct in_addr a;
412#ifdef INET6
413 struct in6_addr a6;
414 int m, i;
415 u_char *u;
416#endif /* INET6 */
269 417
270 cp = buf + sizeof("sortlist") - 1; 418 cp = buf + sizeof("sortlist") - 1;
271 while (*cp == ' ' || *cp == '\t') 419 while (nsort < MAXRESOLVSORT) {
272 cp++; 420 while (*cp == ' ' || *cp == '\t')
273 while (sscanf(cp,"%[0-9./]s", buf2) && nsort < MAXRESOLVSORT) { 421 cp++;
274 if (net = strchr(buf2, '/')) 422 if (*cp == '\0' || *cp == '\n' || *cp == ';')
275 *net = '\0'; 423 break;
276 if (inet_aton(buf2, &a)) { 424 net = cp;
425 while (*cp && !ISSORTMASK(*cp) && *cp != ';' &&
426 isascii(*cp) && !isspace(*cp))
427 cp++;
428 n = *cp;
429 *cp = 0;
430 if (inet_aton(net, &a)) {
277 _res.sort_list[nsort].addr = a; 431 _res.sort_list[nsort].addr = a;
278 if (net && inet_aton(net+1, &a)) { 432 if (ISSORTMASK(n)) {
279 _res.sort_list[nsort].mask = a.s_addr; 433 *cp++ = n;
280 } else { 434 net = cp;
281 _res.sort_list[nsort].mask = 435 while (*cp && *cp != ';' &&
436 isascii(*cp) && !isspace(*cp))
437 cp++;
438 n = *cp;
439 *cp = 0;
440 if (inet_aton(net, &a)) {
441 _res.sort_list[nsort].mask = a.s_addr;
442 } else {
443 _res.sort_list[nsort].mask =
282 net_mask(_res.sort_list[nsort].addr); 444 net_mask(_res.sort_list[nsort].addr);
445 }
446 } else {
447 _res.sort_list[nsort].mask =
448 net_mask(_res.sort_list[nsort].addr);
283 } 449 }
450#ifdef INET6
451 _res_ext.sort_list[nsort].af = AF_INET;
452 _res_ext.sort_list[nsort].addr.ina =
453 _res.sort_list[nsort].addr;
454 _res_ext.sort_list[nsort].mask.ina.s_addr =
455 _res.sort_list[nsort].mask;
456#endif /* INET6 */
284 nsort++; 457 nsort++;
285 } 458 }
286 if (net) 459#ifdef INET6
287 *net = '/'; 460 else if (inet_pton(AF_INET6, net, &a6) == 1) {
288 cp += strlen(buf2); 461 _res_ext.sort_list[nsort].af = AF_INET6;
289 while (*cp == ' ' || *cp == '\t') 462 _res_ext.sort_list[nsort].addr.in6a = a6;
290 cp++; 463 u = (u_char *)&_res_ext.sort_list[nsort].mask.in6a;
464 *cp++ = n;
465 net = cp;
466 while (*cp && *cp != ';' &&
467 isascii(*cp) && !isspace(*cp))
468 cp++;
469 m = n;
470 n = *cp;
471 *cp = 0;
472 switch (m) {
473 case '/':
474 m = atoi(net);
475 break;
476 case '&':
477 if (inet_pton(AF_INET6, net, u) == 1) {
478 m = -1;
479 break;
480 }
481 /*FALLTHRU*/
482 default:
483 m = sizeof(struct in6_addr) * NBBY;
484 break;
485 }
486 if (m >= 0) {
487 for (i = 0; i < sizeof(struct in6_addr); i++) {
488 if (m <= 0) {
489 *u = 0;
490 } else {
491 m -= NBBY;
492 *u = (u_char)~0;
493 if (m < 0)
494 *u <<= -m;
495 }
496 u++;
497 }
498 }
499 nsort++;
500 }
501#endif /* INET6 */
502 *cp = n;
291 } 503 }
292 continue; 504 continue;
293 } 505 }
294 if (!strncmp(buf, "options", sizeof("options") -1)) { 506#endif
507 if (MATCH(buf, "options")) {
295 res_setoptions(buf + sizeof("options") - 1, "conf"); 508 res_setoptions(buf + sizeof("options") - 1, "conf");
296 continue; 509 continue;
297 } 510 }
298 } 511 }
299 if (nserv > 1) 512 if (nserv > 1)
300 _res.nscount = nserv; 513 _res.nscount = nserv;
514#ifdef RESOLVSORT
301 _res.nsort = nsort; 515 _res.nsort = nsort;
516#endif
302 (void) fclose(fp); 517 (void) fclose(fp);
303 } 518 }
304 if (_res.defdname[0] == 0) { 519 if (_res.defdname[0] == 0 &&
305 if (gethostname(buf, sizeof(_res.defdname) - 1) == 0 && 520 gethostname(buf, sizeof(_res.defdname) - 1) == 0 &&
306 (cp = strchr(buf, '.'))) 521 (cp = strchr(buf, '.')) != NULL)
307 (void)strcpy(_res.defdname, cp + 1); 522 {
523 strlcpy(_res.defdname, cp + 1,
524 sizeof(_res.defdname));
308 } 525 }
309 526
310 /* find components of local domain that might be searched */ 527 /* find components of local domain that might be searched */
311 if (havesearch == 0) { 528 if (havesearch == 0) {
312 pp = _res.dnsrch; 529 pp = _res.dnsrch;
313 *pp++ = _res.defdname; 530 *pp++ = _res.defdname;
314#ifndef SEARCH_LOCAL_DOMAINS
315 *pp = NULL; 531 *pp = NULL;
316#else 532
317 for (cp = _res.defdname, n = 0; *cp; cp++) 533#ifndef RFC1535
318 if (*cp == '.') 534 dots = 0;
319 n++; 535 for (cp = _res.defdname; *cp; cp++)
536 dots += (*cp == '.');
537
320 cp = _res.defdname; 538 cp = _res.defdname;
321 for (; n >= LOCALDOMAINPARTS && pp < _res.dnsrch + MAXDFLSRCH; 539 while (pp < _res.dnsrch + MAXDFLSRCH) {
322 n--) { 540 if (dots < LOCALDOMAINPARTS)
323 cp = strchr(cp, '.'); 541 break;
324 *pp++ = ++cp; 542 cp = strchr(cp, '.') + 1; /* we know there is one */
543 *pp++ = cp;
544 dots--;
325 } 545 }
326 *pp++ = 0; 546 *pp = NULL;
327#endif 547#ifdef DEBUG
548 if (_res.options & RES_DEBUG) {
549 printf(";; res_init()... default dnsrch list:\n");
550 for (pp = _res.dnsrch; *pp; pp++)
551 printf(";;\t%s\n", *pp);
552 printf(";;\t..END..\n");
553 }
554#endif /* DEBUG */
555#endif /* !RFC1535 */
328 } 556 }
329 557
330 if ((cp = getenv("RES_OPTIONS")) != NULL) 558 if (issetugid())
559 _res.options |= RES_NOALIASES;
560 else if ((cp = getenv("RES_OPTIONS")) != NULL)
331 res_setoptions(cp, "env"); 561 res_setoptions(cp, "env");
332 _res.options |= RES_INIT; 562 _res.options |= RES_INIT;
333 return (0); 563 return (0);
334} 564}
335 565
566/* ARGSUSED */
336static void 567static void
337res_setoptions(options, source) 568res_setoptions(options, source)
338 char *options, *source; 569 char *options, *source;
339{ 570{
340 char *cp = options; 571 char *cp = options;
341 int i; 572 char *endp;
573 long l;
342 574
343#ifdef DEBUG 575#ifdef DEBUG
344 if (_res.options & RES_DEBUG) { 576 if (_res.options & RES_DEBUG)
345 printf(";; res_setoptions(\"%s\", \"%s\")...\n", 577 printf(";; res_setoptions(\"%s\", \"%s\")...\n",
346 options, source); 578 options, source);
347 }
348#endif 579#endif
349 while (*cp) { 580 while (*cp) {
350 /* skip leading and inner runs of spaces */ 581 /* skip leading and inner runs of spaces */
351 while (*cp == ' ' || *cp == '\t') 582 while (*cp == ' ' || *cp == '\t')
352 cp++; 583 cp++;
353 /* search for and process individual options */ 584 /* search for and process individual options */
354 if (!strncmp(cp, "ndots:", sizeof("ndots:")-1)) { 585 if (!strncmp(cp, "ndots:", sizeof("ndots:") - 1)) {
355 i = atoi(cp + sizeof("ndots:") - 1); 586 char *p = cp + sizeof("ndots:") - 1;
356 if (i <= RES_MAXNDOTS) 587 l = strtol(p, &endp, 10);
357 _res.ndots = i; 588 if (l >= 0 && endp != p &&
358 else 589 (*endp = '\0' || isspace(*endp))) {
359 _res.ndots = RES_MAXNDOTS; 590 if (l <= RES_MAXNDOTS)
591 _res.ndots = l;
592 else
593 _res.ndots = RES_MAXNDOTS;
360#ifdef DEBUG 594#ifdef DEBUG
361 if (_res.options & RES_DEBUG) { 595 if (_res.options & RES_DEBUG)
362 printf(";;\tndots=%d\n", _res.ndots); 596 printf(";;\tndots=%u\n", _res.ndots);
363 }
364#endif 597#endif
365 } else if (!strncmp(cp, "debug", sizeof("debug")-1)) { 598 }
599 } else if (!strncmp(cp, "debug", sizeof("debug") - 1)) {
366#ifdef DEBUG 600#ifdef DEBUG
367 if (!(_res.options & RES_DEBUG)) { 601 if (!(_res.options & RES_DEBUG)) {
368 printf(";; res_setoptions(\"%s\", \"%s\")..\n", 602 printf(";; res_setoptions(\"%s\", \"%s\")..\n",
@@ -371,6 +605,14 @@ res_setoptions(options, source)
371 } 605 }
372 printf(";;\tdebug\n"); 606 printf(";;\tdebug\n");
373#endif 607#endif
608 } else if (!strncmp(cp, "inet6", sizeof("inet6") - 1)) {
609 _res.options |= RES_USE_INET6;
610 } else if (!strncmp(cp, "insecure1", sizeof("insecure1") - 1)) {
611 _res.options |= RES_INSECURE1;
612 } else if (!strncmp(cp, "insecure2", sizeof("insecure2") - 1)) {
613 _res.options |= RES_INSECURE2;
614 } else if (!strncmp(cp, "edns0", sizeof("edns0") - 1)) {
615 _res.options |= RES_USE_EDNS0;
374 } else { 616 } else {
375 /* XXX - print a warning here? */ 617 /* XXX - print a warning here? */
376 } 618 }
@@ -380,6 +622,8 @@ res_setoptions(options, source)
380 } 622 }
381} 623}
382 624
625#ifdef RESOLVSORT
626/* XXX - should really support CIDR which means explicit masks always. */
383static u_int32_t 627static u_int32_t
384net_mask(in) /* XXX - should really use system's version of this */ 628net_mask(in) /* XXX - should really use system's version of this */
385 struct in_addr in; 629 struct in_addr in;
@@ -388,7 +632,8 @@ net_mask(in) /* XXX - should really use system's version of this */
388 632
389 if (IN_CLASSA(i)) 633 if (IN_CLASSA(i))
390 return (htonl(IN_CLASSA_NET)); 634 return (htonl(IN_CLASSA_NET));
391 if (IN_CLASSB(i)) 635 else if (IN_CLASSB(i))
392 return (htonl(IN_CLASSB_NET)); 636 return (htonl(IN_CLASSB_NET));
393 return (htonl(IN_CLASSC_NET)); 637 return (htonl(IN_CLASSC_NET));
394} 638}
639#endif
diff --git a/src/lib/libc/net/res_mkquery.c b/src/lib/libc/net/res_mkquery.c
index 25f025e147..6cd6a00dbe 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.12 2002/08/28 03:19:38 itojun 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,39 +58,47 @@
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.12 2002/08/28 03:19:38 itojun 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
72/* 77/*
73 * Form all types of queries. 78 * Form all types of queries.
74 * Returns the size of the result or -1. 79 * Returns the size of the result or -1.
75 */ 80 */
81/* ARGSUSED */
82int
76res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen) 83res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen)
77 int op; /* opcode of query */ 84 int op; /* opcode of query */
78 const char *dname; /* domain name */ 85 const char *dname; /* domain name */
79 int class, type; /* class and type of query */ 86 int class, type; /* class and type of query */
80 const char *data; /* resource record data */ 87 const u_char *data; /* resource record data */
81 int datalen; /* length of data */ 88 int datalen; /* length of data */
82 const char *newrr_in; /* new rr for modify or append */ 89 const u_char *newrr_in; /* new rr for modify or append */
83 char *buf; /* buffer to put query */ 90 u_char *buf; /* buffer to put query */
84 int buflen; /* size of buffer */ 91 int buflen; /* size of buffer */
85{ 92{
86 register HEADER *hp; 93 register HEADER *hp;
87 register char *cp; 94 register u_char *cp, *ep;
88 register int n; 95 register int n;
89 struct rrec *newrr = (struct rrec *) newrr_in; 96 u_char *dnptrs[20], **dpp, **lastdnptr;
90 char *dnptrs[10], **dpp, **lastdnptr;
91 97
98 if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
99 h_errno = NETDB_INTERNAL;
100 return (-1);
101 }
92#ifdef DEBUG 102#ifdef DEBUG
93 if (_res.options & RES_DEBUG) 103 if (_res.options & RES_DEBUG)
94 printf(";; res_mkquery(%d, %s, %d, %d)\n", 104 printf(";; res_mkquery(%d, %s, %d, %d)\n",
@@ -96,58 +106,64 @@ res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen)
96#endif 106#endif
97 /* 107 /*
98 * Initialize header fields. 108 * Initialize header fields.
109 *
110 * A special random number generator is used to create non predictable
111 * and non repeating ids over a long period. It also avoids reuse
112 * by switching between two distinct number cycles.
99 */ 113 */
100 if ((buf == NULL) || (buflen < sizeof(HEADER))) 114
101 return(-1); 115 if ((buf == NULL) || (buflen < HFIXEDSZ))
102 bzero(buf, sizeof(HEADER)); 116 return (-1);
117 bzero(buf, HFIXEDSZ);
103 hp = (HEADER *) buf; 118 hp = (HEADER *) buf;
104 hp->id = htons(++_res.id); 119 _res.id = res_randomid();
120 hp->id = htons(_res.id);
105 hp->opcode = op; 121 hp->opcode = op;
106 hp->pr = (_res.options & RES_PRIMARY) != 0;
107 hp->rd = (_res.options & RES_RECURSE) != 0; 122 hp->rd = (_res.options & RES_RECURSE) != 0;
108 hp->rcode = NOERROR; 123 hp->rcode = NOERROR;
109 cp = buf + sizeof(HEADER); 124 cp = buf + HFIXEDSZ;
110 buflen -= sizeof(HEADER); 125 ep = buf + buflen;
111 dpp = dnptrs; 126 dpp = dnptrs;
112 *dpp++ = buf; 127 *dpp++ = buf;
113 *dpp++ = NULL; 128 *dpp++ = NULL;
114 lastdnptr = dnptrs + sizeof(dnptrs)/sizeof(dnptrs[0]); 129 lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0];
115 /* 130 /*
116 * perform opcode specific processing 131 * perform opcode specific processing
117 */ 132 */
118 switch (op) { 133 switch (op) {
119 case QUERY: 134 case QUERY: /*FALLTHROUGH*/
120 if ((buflen -= QFIXEDSZ) < 0) 135 case NS_NOTIFY_OP:
121 return(-1); 136 if (ep - cp < QFIXEDSZ)
122 if ((n = dn_comp((u_char *)dname, (u_char *)cp, buflen, 137 return (-1);
123 (u_char **)dnptrs, (u_char **)lastdnptr)) < 0) 138 if ((n = dn_comp(dname, cp, ep - cp - QFIXEDSZ, dnptrs,
139 lastdnptr)) < 0)
124 return (-1); 140 return (-1);
125 cp += n; 141 cp += n;
126 buflen -= n; 142 __putshort(type, cp);
127 __putshort(type, (u_char *)cp); 143 cp += INT16SZ;
128 cp += sizeof(u_int16_t); 144 __putshort(class, cp);
129 __putshort(class, (u_char *)cp); 145 cp += INT16SZ;
130 cp += sizeof(u_int16_t);
131 hp->qdcount = htons(1); 146 hp->qdcount = htons(1);
132 if (op == QUERY || data == NULL) 147 if (op == QUERY || data == NULL)
133 break; 148 break;
134 /* 149 /*
135 * Make an additional record for completion domain. 150 * Make an additional record for completion domain.
136 */ 151 */
137 buflen -= RRFIXEDSZ; 152 if (ep - cp < RRFIXEDSZ)
138 if ((n = dn_comp((u_char *)data, (u_char *)cp, buflen, 153 return (-1);
139 (u_char **)dnptrs, (u_char **)lastdnptr)) < 0) 154 n = dn_comp((char *)data, cp, ep - cp - RRFIXEDSZ, dnptrs,
155 lastdnptr);
156 if (n < 0)
140 return (-1); 157 return (-1);
141 cp += n; 158 cp += n;
142 buflen -= n; 159 __putshort(T_NULL, cp);
143 __putshort(T_NULL, (u_char *)cp); 160 cp += INT16SZ;
144 cp += sizeof(u_int16_t); 161 __putshort(class, cp);
145 __putshort(class, (u_char *)cp); 162 cp += INT16SZ;
146 cp += sizeof(u_int16_t); 163 __putlong(0, cp);
147 __putlong(0, (u_char *)cp); 164 cp += INT32SZ;
148 cp += sizeof(u_int32_t); 165 __putshort(0, cp);
149 __putshort(0, (u_char *)cp); 166 cp += INT16SZ;
150 cp += sizeof(u_int16_t);
151 hp->arcount = htons(1); 167 hp->arcount = htons(1);
152 break; 168 break;
153 169
@@ -155,82 +171,72 @@ res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen)
155 /* 171 /*
156 * Initialize answer section 172 * Initialize answer section
157 */ 173 */
158 if (buflen < 1 + RRFIXEDSZ + datalen) 174 if (ep - cp < 1 + RRFIXEDSZ + datalen)
159 return (-1); 175 return (-1);
160 *cp++ = '\0'; /* no domain name */ 176 *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); 177 __putshort(type, cp);
196 cp += sizeof(u_int16_t); 178 cp += INT16SZ;
197 __putshort(class, cp); 179 __putshort(class, cp);
198 cp += sizeof(u_int16_t); 180 cp += INT16SZ;
199 __putlong(0, cp); 181 __putlong(0, cp);
200 cp += sizeof(u_int32_t); 182 cp += INT32SZ;
201 __putshort(datalen, cp); 183 __putshort(datalen, cp);
202 cp += sizeof(u_int16_t); 184 cp += INT16SZ;
203 if (datalen) { 185 if (datalen) {
204 bcopy(data, cp, datalen); 186 bcopy(data, cp, datalen);
205 cp += datalen; 187 cp += datalen;
206 } 188 }
207 if ( (op == UPDATED) || (op == UPDATEDA) ) { 189 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; 190 break;
232 191
233#endif /* ALLOW_UPDATES */ 192 default:
193 return (-1);
234 } 194 }
235 return (cp - buf); 195 return (cp - buf);
236} 196}
197
198/* attach OPT pseudo-RR, as documented in RFC2671 (EDNS0). */
199int
200res_opt(n0, buf, buflen, anslen)
201 int n0;
202 u_char *buf; /* buffer to put query */
203 int buflen; /* size of buffer */
204 int anslen; /* answer buffer length */
205{
206 register HEADER *hp;
207 register u_char *cp, *ep;
208
209 hp = (HEADER *) buf;
210 cp = buf + n0;
211 ep = buf + buflen;
212
213 if (ep - cp < 1 + RRFIXEDSZ)
214 return -1;
215
216 *cp++ = 0; /* "." */
217
218 __putshort(T_OPT, cp); /* TYPE */
219 cp += INT16SZ;
220 if (anslen > 0xffff)
221 anslen = 0xffff; /* limit to 16bit value */
222 __putshort(anslen & 0xffff, cp); /* CLASS = UDP payload size */
223 cp += INT16SZ;
224 *cp++ = NOERROR; /* extended RCODE */
225 *cp++ = 0; /* EDNS version */
226 if (_res.options & RES_USE_DNSSEC) {
227#ifdef DEBUG
228 if (_res.options & RES_DEBUG)
229 printf(";; res_opt()... ENDS0 DNSSEC OK\n");
230#endif /* DEBUG */
231 __putshort(DNS_MESSAGEEXTFLAG_DO, cp); /* EDNS Z field */
232 cp += INT16SZ;
233 } else {
234 __putshort(0, cp); /* EDNS Z field */
235 cp += INT16SZ;
236 }
237 __putshort(0, cp); /* RDLEN */
238 cp += INT16SZ;
239 hp->arcount = htons(ntohs(hp->arcount) + 1);
240
241 return cp - buf;
242}
diff --git a/src/lib/libc/net/res_query.c b/src/lib/libc/net/res_query.c
index 7649462e56..9c1aef1218 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.19 2002/06/27 09:55:49 itojun 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,26 @@
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.19 2002/06/27 09:55:49 itojun 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>
76 81
77#if PACKETSZ > 1024 82#if PACKETSZ > 1024
78#define MAXPACKET PACKETSZ 83#define MAXPACKET PACKETSZ
@@ -80,8 +85,9 @@ static char rcsid[] = "$NetBSD: res_query.c,v 1.9 1995/02/25 06:58:58 cgd Exp $"
80#define MAXPACKET 1024 85#define MAXPACKET 1024
81#endif 86#endif
82 87
83char *__hostalias __P((const char *)); 88const char *hostalias(const char *);
84int h_errno; 89int h_errno;
90extern int res_opt(int, u_char *, int, int);
85 91
86/* 92/*
87 * Formulate a normal query, send, and await answer. 93 * Formulate a normal query, send, and await answer.
@@ -90,26 +96,37 @@ int h_errno;
90 * if no error is indicated and the answer count is nonzero. 96 * if no error is indicated and the answer count is nonzero.
91 * Return the size of the response on success, -1 on error. 97 * Return the size of the response on success, -1 on error.
92 * Error number is left in h_errno. 98 * Error number is left in h_errno.
99 *
93 * Caller must parse answer and determine whether it answers the question. 100 * Caller must parse answer and determine whether it answers the question.
94 */ 101 */
102int
95res_query(name, class, type, answer, anslen) 103res_query(name, class, type, answer, anslen)
96 char *name; /* domain name */ 104 const char *name; /* domain name */
97 int class, type; /* class and type of query */ 105 int class, type; /* class and type of query */
98 u_char *answer; /* buffer to put answer */ 106 u_char *answer; /* buffer to put answer */
99 int anslen; /* size of answer buffer */ 107 int anslen; /* size of answer buffer */
100{ 108{
101 char buf[MAXPACKET]; 109 u_char buf[MAXPACKET];
102 HEADER *hp; 110 register HEADER *hp = (HEADER *) answer;
103 int n; 111 int n;
104 112
105 if ((_res.options & RES_INIT) == 0 && res_init() == -1) 113 hp->rcode = NOERROR; /* default */
114
115 if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
116 h_errno = NETDB_INTERNAL;
106 return (-1); 117 return (-1);
118 }
107#ifdef DEBUG 119#ifdef DEBUG
108 if (_res.options & RES_DEBUG) 120 if (_res.options & RES_DEBUG)
109 printf(";; res_query(%s, %d, %d)\n", name, class, type); 121 printf(";; res_query(%s, %d, %d)\n", name, class, type);
110#endif 122#endif
111 n = res_mkquery(QUERY, name, class, type, (char *)NULL, 0, NULL, 123
112 buf, sizeof(buf)); 124 n = res_mkquery(QUERY, name, class, type, NULL, 0, NULL,
125 buf, sizeof(buf));
126 if (n > 0 && ((_res.options & RES_USE_EDNS0) ||
127 (_res.options & RES_USE_DNSSEC))) {
128 n = res_opt(n, buf, sizeof(buf), anslen);
129 }
113 130
114 if (n <= 0) { 131 if (n <= 0) {
115#ifdef DEBUG 132#ifdef DEBUG
@@ -119,7 +136,7 @@ res_query(name, class, type, answer, anslen)
119 h_errno = NO_RECOVERY; 136 h_errno = NO_RECOVERY;
120 return (n); 137 return (n);
121 } 138 }
122 n = res_send(buf, n, (char *)answer, anslen); 139 n = res_send(buf, n, answer, anslen);
123 if (n < 0) { 140 if (n < 0) {
124#ifdef DEBUG 141#ifdef DEBUG
125 if (_res.options & RES_DEBUG) 142 if (_res.options & RES_DEBUG)
@@ -129,29 +146,28 @@ res_query(name, class, type, answer, anslen)
129 return (n); 146 return (n);
130 } 147 }
131 148
132 hp = (HEADER *) answer;
133 if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) { 149 if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
134#ifdef DEBUG 150#ifdef DEBUG
135 if (_res.options & RES_DEBUG) 151 if (_res.options & RES_DEBUG)
136 printf(";; rcode = %d, ancount=%d\n", hp->rcode, 152 printf(";; rcode = %u, ancount=%u\n", hp->rcode,
137 ntohs(hp->ancount)); 153 ntohs(hp->ancount));
138#endif 154#endif
139 switch (hp->rcode) { 155 switch (hp->rcode) {
140 case NXDOMAIN: 156 case NXDOMAIN:
141 h_errno = HOST_NOT_FOUND; 157 h_errno = HOST_NOT_FOUND;
142 break; 158 break;
143 case SERVFAIL: 159 case SERVFAIL:
144 h_errno = TRY_AGAIN; 160 h_errno = TRY_AGAIN;
145 break; 161 break;
146 case NOERROR: 162 case NOERROR:
147 h_errno = NO_DATA; 163 h_errno = NO_DATA;
148 break; 164 break;
149 case FORMERR: 165 case FORMERR:
150 case NOTIMP: 166 case NOTIMP:
151 case REFUSED: 167 case REFUSED:
152 default: 168 default:
153 h_errno = NO_RECOVERY; 169 h_errno = NO_RECOVERY;
154 break; 170 break;
155 } 171 }
156 return (-1); 172 return (-1);
157 } 173 }
@@ -162,9 +178,7 @@ res_query(name, class, type, answer, anslen)
162 * Formulate a normal query, send, and retrieve answer in supplied buffer. 178 * Formulate a normal query, send, and retrieve answer in supplied buffer.
163 * Return the size of the response on success, -1 on error. 179 * Return the size of the response on success, -1 on error.
164 * If enabled, implement search rules until answer or unrecoverable failure 180 * If enabled, implement search rules until answer or unrecoverable failure
165 * is detected. Error number is left in h_errno. 181 * 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 */ 182 */
169int 183int
170res_search(name, class, type, answer, anslen) 184res_search(name, class, type, answer, anslen)
@@ -173,28 +187,29 @@ res_search(name, class, type, answer, anslen)
173 u_char *answer; /* buffer to put answer */ 187 u_char *answer; /* buffer to put answer */
174 int anslen; /* size of answer */ 188 int anslen; /* size of answer */
175{ 189{
176 register char *cp, **domain; 190 register const char *cp, * const *domain;
177 int dots, trailing_dot, ret, got_nodata, saved_herrno, tried_as_is; 191 HEADER *hp = (HEADER *) answer;
192 u_int dots;
193 int trailing_dot, ret, saved_herrno;
194 int got_nodata = 0, got_servfail = 0, tried_as_is = 0;
178 195
179 if ((_res.options & RES_INIT) == 0 && res_init() == -1) 196 if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
197 h_errno = NETDB_INTERNAL;
180 return (-1); 198 return (-1);
181 199 }
182 got_nodata = 0;
183 errno = 0; 200 errno = 0;
184 h_errno = HOST_NOT_FOUND; /* default, if we never query */ 201 h_errno = HOST_NOT_FOUND; /* default, if we never query */
185 dots = 0; 202 dots = 0;
186 for (cp = (char *)name; *cp; cp++) { 203 for (cp = name; *cp; cp++)
187 if (*cp == '.') 204 dots += (*cp == '.');
188 dots++;
189 }
190 trailing_dot = 0; 205 trailing_dot = 0;
191 if ((cp > name) && (*--cp == '.')) 206 if (cp > name && *--cp == '.')
192 trailing_dot++; 207 trailing_dot++;
193 208
194 /* 209 /*
195 * if there aren't any dots, it could be a user-level alias 210 * if there aren't any dots, it could be a user-level alias
196 */ 211 */
197 if (!dots && (cp = __hostalias(name))) 212 if (!dots && (cp = __hostalias(name)) != NULL)
198 return (res_query(cp, class, type, answer, anslen)); 213 return (res_query(cp, class, type, answer, anslen));
199 214
200 /* 215 /*
@@ -202,7 +217,6 @@ res_search(name, class, type, answer, anslen)
202 * 'as is'. The threshold can be set with the "ndots" option. 217 * 'as is'. The threshold can be set with the "ndots" option.
203 */ 218 */
204 saved_herrno = -1; 219 saved_herrno = -1;
205 tried_as_is = 0;
206 if (dots >= _res.ndots) { 220 if (dots >= _res.ndots) {
207 ret = res_querydomain(name, NULL, class, type, answer, anslen); 221 ret = res_querydomain(name, NULL, class, type, answer, anslen);
208 if (ret > 0) 222 if (ret > 0)
@@ -219,13 +233,17 @@ res_search(name, class, type, answer, anslen)
219 */ 233 */
220 if ((!dots && (_res.options & RES_DEFNAMES)) || 234 if ((!dots && (_res.options & RES_DEFNAMES)) ||
221 (dots && !trailing_dot && (_res.options & RES_DNSRCH))) { 235 (dots && !trailing_dot && (_res.options & RES_DNSRCH))) {
222 for (domain = _res.dnsrch; *domain; domain++) { 236 int done = 0;
223 int done = 0; 237
238 for (domain = (const char * const *)_res.dnsrch;
239 *domain && !done;
240 domain++) {
224 241
225 ret = res_querydomain(name, *domain, class, type, 242 ret = res_querydomain(name, *domain, class, type,
226 answer, anslen); 243 answer, anslen);
227 if (ret > 0) 244 if (ret > 0)
228 return (ret); 245 return (ret);
246
229 /* 247 /*
230 * If no server present, give up. 248 * If no server present, give up.
231 * If name isn't found in this domain, 249 * If name isn't found in this domain,
@@ -251,24 +269,27 @@ res_search(name, class, type, answer, anslen)
251 case HOST_NOT_FOUND: 269 case HOST_NOT_FOUND:
252 /* keep trying */ 270 /* keep trying */
253 break; 271 break;
272 case TRY_AGAIN:
273 if (hp->rcode == SERVFAIL) {
274 /* try next search element, if any */
275 got_servfail++;
276 break;
277 }
278 /* FALLTHROUGH */
254 default: 279 default:
255 /* anything else implies that we're done */ 280 /* anything else implies that we're done */
256 done++; 281 done++;
257 } 282 }
258 /* 283
259 * if we got here for some reason other than DNSRCH, 284 /* if we got here for some reason other than DNSRCH,
260 * we only wanted one iteration of the loop, so stop. 285 * we only wanted one iteration of the loop, so stop.
261 */ 286 */
262 if (!(_res.options & RES_DNSRCH)) 287 if (!(_res.options & RES_DNSRCH))
263 done++; 288 done++;
264
265 if (done)
266 break;
267 } 289 }
268 } 290 }
269 291
270 /* 292 /* 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 293 * note that we do this regardless of how many dots were in the
273 * name or whether it ends with a dot. 294 * name or whether it ends with a dot.
274 */ 295 */
@@ -276,11 +297,9 @@ res_search(name, class, type, answer, anslen)
276 ret = res_querydomain(name, NULL, class, type, answer, anslen); 297 ret = res_querydomain(name, NULL, class, type, answer, anslen);
277 if (ret > 0) 298 if (ret > 0)
278 return (ret); 299 return (ret);
279 saved_herrno = h_errno;
280 } 300 }
281 301
282 /* 302 /* 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 303 * 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). 304 * (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. 305 * else if we ever got a nodata, send that back as the reason.
@@ -291,6 +310,8 @@ res_search(name, class, type, answer, anslen)
291 h_errno = saved_herrno; 310 h_errno = saved_herrno;
292 else if (got_nodata) 311 else if (got_nodata)
293 h_errno = NO_DATA; 312 h_errno = NO_DATA;
313 else if (got_servfail)
314 h_errno = TRY_AGAIN;
294 return (-1); 315 return (-1);
295} 316}
296 317
@@ -298,20 +319,25 @@ res_search(name, class, type, answer, anslen)
298 * Perform a call on res_query on the concatenation of name and domain, 319 * Perform a call on res_query on the concatenation of name and domain,
299 * removing a trailing dot from name if domain is NULL. 320 * removing a trailing dot from name if domain is NULL.
300 */ 321 */
322int
301res_querydomain(name, domain, class, type, answer, anslen) 323res_querydomain(name, domain, class, type, answer, anslen)
302 char *name, *domain; 324 const char *name, *domain;
303 int class, type; /* class and type of query */ 325 int class, type; /* class and type of query */
304 u_char *answer; /* buffer to put answer */ 326 u_char *answer; /* buffer to put answer */
305 int anslen; /* size of answer */ 327 int anslen; /* size of answer */
306{ 328{
307 char nbuf[2*MAXDNAME+2]; 329 char nbuf[MAXDNAME*2+1+1];
308 char *longname = nbuf; 330 const char *longname = nbuf;
309 int n; 331 int n;
310 332
333 if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
334 h_errno = NETDB_INTERNAL;
335 return (-1);
336 }
311#ifdef DEBUG 337#ifdef DEBUG
312 if (_res.options & RES_DEBUG) 338 if (_res.options & RES_DEBUG)
313 printf(";; res_querydomain(%s, %s, %d, %d)\n", 339 printf(";; res_querydomain(%s, %s, %d, %d)\n",
314 name, domain, class, type); 340 name, domain?domain:"<Nil>", class, type);
315#endif 341#endif
316 if (domain == NULL) { 342 if (domain == NULL) {
317 /* 343 /*
@@ -325,38 +351,51 @@ res_querydomain(name, domain, class, type, answer, anslen)
325 } else 351 } else
326 longname = name; 352 longname = name;
327 } else 353 } else
328 (void)sprintf(nbuf, "%.*s.%.*s", 354 snprintf(nbuf, sizeof nbuf, "%.*s.%.*s",
329 MAXDNAME, name, MAXDNAME, domain); 355 MAXDNAME, name, MAXDNAME, domain);
330 356
331 return (res_query(longname, class, type, answer, anslen)); 357 return (res_query(longname, class, type, answer, anslen));
332} 358}
333 359
334char * 360const char *
335__hostalias(name) 361hostalias(name)
336 register const char *name; 362 register const char *name;
337{ 363{
338 register char *cp1, *cp2; 364 register char *cp1, *cp2;
339 FILE *fp; 365 FILE *fp;
340 char *file, *getenv(), *strcpy(), *strncpy(); 366 char *file;
341 char buf[BUFSIZ]; 367 char buf[BUFSIZ];
342 static char abuf[MAXDNAME]; 368 static char abuf[MAXDNAME];
369 size_t len;
343 370
371 if (_res.options & RES_NOALIASES)
372 return (NULL);
344 file = getenv("HOSTALIASES"); 373 file = getenv("HOSTALIASES");
345 if (file == NULL || (fp = fopen(file, "r")) == NULL) 374 if (issetugid() != 0 || file == NULL || (fp = fopen(file, "r")) == NULL)
346 return (NULL); 375 return (NULL);
347 buf[sizeof(buf) - 1] = '\0'; 376 setbuf(fp, NULL);
348 while (fgets(buf, sizeof(buf), fp)) { 377 while ((cp1 = fgetln(fp, &len)) != NULL) {
349 for (cp1 = buf; *cp1 && !isspace(*cp1); ++cp1); 378 if (cp1[len-1] == '\n')
379 len--;
380 if (len >= sizeof(buf) || len == 0)
381 continue;
382 (void)memcpy(buf, cp1, len);
383 buf[len] = '\0';
384
385 for (cp1 = buf; *cp1 && !isspace(*cp1); ++cp1)
386 ;
350 if (!*cp1) 387 if (!*cp1)
351 break; 388 break;
352 *cp1 = '\0'; 389 *cp1 = '\0';
353 if (!strcasecmp(buf, name)) { 390 if (!strcasecmp(buf, name)) {
354 while (isspace(*++cp1)); 391 while (isspace(*++cp1))
392 ;
355 if (!*cp1) 393 if (!*cp1)
356 break; 394 break;
357 for (cp2 = cp1 + 1; *cp2 && !isspace(*cp2); ++cp2); 395 for (cp2 = cp1 + 1; *cp2 && !isspace(*cp2); ++cp2)
358 abuf[sizeof(abuf) - 1] = *cp2 = '\0'; 396 ;
359 (void)strncpy(abuf, cp1, sizeof(abuf) - 1); 397 *cp2 = '\0';
398 strlcpy(abuf, cp1, sizeof(abuf));
360 fclose(fp); 399 fclose(fp);
361 return (abuf); 400 return (abuf);
362 } 401 }
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..b043e7c9fb 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.12 2002/09/06 18:35:12 deraadt 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.12 2002/09/06 18:35:12 deraadt 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,22 @@ 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>
81 98
82static int s = -1; /* socket used for communications */ 99static int s = -1; /* socket used for communications */
83static struct sockaddr no_addr; 100static int connected = 0; /* is the socket connected */
101static int vc = 0; /* is the socket a virtual ciruit? */
102static int af = 0; /* address family of socket */
84 103
85#ifndef FD_SET 104#ifndef FD_SET
105/* XXX - should be in portability.h */
86#define NFDBITS 32 106#define NFDBITS 32
87#define FD_SETSIZE 32 107#define FD_SETSIZE 32
88#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS))) 108#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
@@ -91,121 +111,396 @@ static struct sockaddr no_addr;
91#define FD_ZERO(p) bzero((char *)(p), sizeof(*(p))) 111#define FD_ZERO(p) bzero((char *)(p), sizeof(*(p)))
92#endif 112#endif
93 113
94res_send(buf, buflen, answer, anslen) 114#define CAN_RECONNECT 1
95 const char *buf; 115
96 int buflen; 116#ifndef DEBUG
97 char *answer; 117# define Dprint(cond, args) /*empty*/
98 int anslen; 118# define DprintQ(cond, args, query, size) /*empty*/
119# define Aerror(file, string, error, address) /*empty*/
120# define Perror(file, string, error) /*empty*/
121#else
122# define Dprint(cond, args) if (cond) {fprintf args;} else {}
123# define DprintQ(cond, args, query, size) if (cond) {\
124 fprintf args;\
125 __fp_nquery(query, size, stdout);\
126 } else {}
127static char abuf[NI_MAXHOST];
128static char pbuf[NI_MAXSERV];
129static void Aerror(FILE *, char *, int, struct sockaddr *);
130static void Perror(FILE *, char *, int);
131
132 static void
133 Aerror(file, string, error, address)
134 FILE *file;
135 char *string;
136 int error;
137 struct sockaddr *address;
138 {
139 int save = errno;
140
141 if (_res.options & RES_DEBUG) {
142 if (getnameinfo(address, address->sa_len, abuf, sizeof(abuf),
143 pbuf, sizeof(pbuf),
144 NI_NUMERICHOST|NI_NUMERICSERV|NI_WITHSCOPEID) != 0) {
145 strncpy(abuf, "?", sizeof(abuf));
146 strncpy(pbuf, "?", sizeof(pbuf));
147 }
148 fprintf(file, "res_send: %s ([%s].%s): %s\n",
149 string, abuf, pbuf, strerror(error));
150 }
151 errno = save;
152 }
153 static void
154 Perror(file, string, error)
155 FILE *file;
156 char *string;
157 int error;
158 {
159 int save = errno;
160
161 if (_res.options & RES_DEBUG) {
162 fprintf(file, "res_send: %s: %s\n",
163 string, strerror(error));
164 }
165 errno = save;
166 }
167#endif
168
169static res_send_qhook Qhook = NULL;
170static res_send_rhook Rhook = NULL;
171
172void
173res_send_setqhook(hook)
174 res_send_qhook hook;
99{ 175{
100 register int n; 176
101 int try, v_circuit, resplen, ns; 177 Qhook = hook;
102 int gotsomewhere = 0, connected = 0; 178}
103 int connreset = 0; 179
104 u_short id, len; 180void
105 char *cp; 181res_send_setrhook(hook)
106 fd_set dsmask; 182 res_send_rhook hook;
107 struct timeval timeout; 183{
108 HEADER *hp = (HEADER *) buf; 184
109 HEADER *anhp = (HEADER *) answer; 185 Rhook = hook;
110 u_int badns; /* XXX NSMAX can't exceed #/bits per this */ 186}
111 struct iovec iov[2]; 187
112 int terrno = ETIMEDOUT; 188#ifdef INET6
113 char junk[512]; 189static struct sockaddr * get_nsaddr(size_t);
114 190
115#ifdef DEBUG 191/*
116 if ((_res.options & RES_DEBUG) || (_res.pfcode & RES_PRF_QUERY)) { 192 * pick appropriate nsaddr_list for use. see res_init() for initialization.
117 printf(";; res_send()\n"); 193 */
118 __p_query(buf); 194static struct sockaddr *
195get_nsaddr(n)
196 size_t n;
197{
198
199 if (!_res.nsaddr_list[n].sin_family) {
200 /*
201 * - _res_ext.nsaddr_list[n] holds an address that is larger
202 * than struct sockaddr, and
203 * - user code did not update _res.nsaddr_list[n].
204 */
205 return (struct sockaddr *)&_res_ext.nsaddr_list[n];
206 } else {
207 /*
208 * - user code updated _res.nsaddr_list[n], or
209 * - _res.nsaddr_list[n] has the same content as
210 * _res_ext.nsaddr_list[n].
211 */
212 return (struct sockaddr *)&_res.nsaddr_list[n];
119 } 213 }
214}
215#else
216#define get_nsaddr(n) ((struct sockaddr *)&_res.nsaddr_list[(n)])
120#endif 217#endif
121 if (!(_res.options & RES_INIT)) 218
122 if (res_init() == -1) { 219/* int
123 return(-1); 220 * res_isourserver(ina)
221 * looks up "ina" in _res.ns_addr_list[]
222 * returns:
223 * 0 : not found
224 * >0 : found
225 * author:
226 * paul vixie, 29may94
227 */
228int
229res_isourserver(inp)
230 const struct sockaddr_in *inp;
231{
232#ifdef INET6
233 const struct sockaddr_in6 *in6p = (const struct sockaddr_in6 *)inp;
234 const struct sockaddr_in6 *srv6;
235#endif
236 const struct sockaddr_in *srv;
237 int ns, ret;
238
239 ret = 0;
240 switch (inp->sin_family) {
241#ifdef INET6
242 case AF_INET6:
243 for (ns = 0; ns < _res.nscount; ns++) {
244 srv6 = (struct sockaddr_in6 *)get_nsaddr(ns);
245 if (srv6->sin6_family == in6p->sin6_family &&
246 srv6->sin6_port == in6p->sin6_port &&
247 srv6->sin6_scope_id == in6p->sin6_scope_id &&
248 (IN6_IS_ADDR_UNSPECIFIED(&srv6->sin6_addr) ||
249 IN6_ARE_ADDR_EQUAL(&srv6->sin6_addr,
250 &in6p->sin6_addr))) {
251 ret++;
252 break;
253 }
124 } 254 }
255 break;
256#endif
257 case AF_INET:
258 for (ns = 0; ns < _res.nscount; ns++) {
259 srv = (struct sockaddr_in *)get_nsaddr(ns);
260 if (srv->sin_family == inp->sin_family &&
261 srv->sin_port == inp->sin_port &&
262 (srv->sin_addr.s_addr == INADDR_ANY ||
263 srv->sin_addr.s_addr == inp->sin_addr.s_addr)) {
264 ret++;
265 break;
266 }
267 }
268 break;
269 }
270 return (ret);
271}
272
273/* int
274 * res_nameinquery(name, type, class, buf, eom)
275 * look for (name,type,class) in the query section of packet (buf,eom)
276 * returns:
277 * -1 : format error
278 * 0 : not found
279 * >0 : found
280 * author:
281 * paul vixie, 29may94
282 */
283int
284res_nameinquery(name, type, class, buf, eom)
285 const char *name;
286 register int type, class;
287 const u_char *buf, *eom;
288{
289 register const u_char *cp = buf + HFIXEDSZ;
290 int qdcount = ntohs(((HEADER*)buf)->qdcount);
291
292 while (qdcount-- > 0) {
293 char tname[MAXDNAME+1];
294 register int n, ttype, tclass;
295
296 n = dn_expand(buf, eom, cp, tname, sizeof tname);
297 if (n < 0)
298 return (-1);
299 cp += n;
300 ttype = _getshort(cp); cp += INT16SZ;
301 tclass = _getshort(cp); cp += INT16SZ;
302 if (ttype == type &&
303 tclass == class &&
304 strcasecmp(tname, name) == 0)
305 return (1);
306 }
307 return (0);
308}
309
310/* int
311 * res_queriesmatch(buf1, eom1, buf2, eom2)
312 * is there a 1:1 mapping of (name,type,class)
313 * in (buf1,eom1) and (buf2,eom2)?
314 * returns:
315 * -1 : format error
316 * 0 : not a 1:1 mapping
317 * >0 : is a 1:1 mapping
318 * author:
319 * paul vixie, 29may94
320 */
321int
322res_queriesmatch(buf1, eom1, buf2, eom2)
323 const u_char *buf1, *eom1;
324 const u_char *buf2, *eom2;
325{
326 register const u_char *cp = buf1 + HFIXEDSZ;
327 int qdcount = ntohs(((HEADER*)buf1)->qdcount);
328
329 if (qdcount != ntohs(((HEADER*)buf2)->qdcount))
330 return (0);
331 while (qdcount-- > 0) {
332 char tname[MAXDNAME+1];
333 register int n, ttype, tclass;
334
335 n = dn_expand(buf1, eom1, cp, tname, sizeof tname);
336 if (n < 0)
337 return (-1);
338 cp += n;
339 ttype = _getshort(cp); cp += INT16SZ;
340 tclass = _getshort(cp); cp += INT16SZ;
341 if (!res_nameinquery(tname, ttype, tclass, buf2, eom2))
342 return (0);
343 }
344 return (1);
345}
346
347int
348res_send(buf, buflen, ans, anssiz)
349 const u_char *buf;
350 int buflen;
351 u_char *ans;
352 int anssiz;
353{
354 HEADER *hp = (HEADER *) buf;
355 HEADER *anhp = (HEADER *) ans;
356 int gotsomewhere, connreset, terrno, try, v_circuit, resplen, ns;
357 register int n;
358 u_int badns; /* XXX NSMAX can't exceed #/bits in this var */
359
360 if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
361 /* errno should have been set by res_init() in this case. */
362 return (-1);
363 }
364 DprintQ((_res.options & RES_DEBUG) || (_res.pfcode & RES_PRF_QUERY),
365 (stdout, ";; res_send()\n"), buf, buflen);
125 v_circuit = (_res.options & RES_USEVC) || buflen > PACKETSZ; 366 v_circuit = (_res.options & RES_USEVC) || buflen > PACKETSZ;
126 id = hp->id; 367 gotsomewhere = 0;
368 connreset = 0;
369 terrno = ETIMEDOUT;
127 badns = 0; 370 badns = 0;
371
128 /* 372 /*
129 * Send request, RETRY times, or until successful 373 * Send request, RETRY times, or until successful
130 */ 374 */
131 for (try = 0; try < _res.retry; try++) { 375 for (try = 0; try < _res.retry; try++) {
132 for (ns = 0; ns < _res.nscount; ns++) { 376 for (ns = 0; ns < _res.nscount; ns++) {
133 if (badns & (1<<ns)) 377 struct sockaddr *nsap = get_nsaddr(ns);
134 continue; 378 socklen_t salen;
135#ifdef DEBUG 379
136 if (_res.options & RES_DEBUG) 380 if (nsap->sa_len)
137 printf(";; Querying server (# %d) address = %s\n", 381 salen = nsap->sa_len;
138 ns+1, 382#ifdef INET6
139 inet_ntoa(_res.nsaddr_list[ns].sin_addr)); 383 else if (nsap->sa_family == AF_INET6)
384 salen = sizeof(struct sockaddr_in6);
140#endif 385#endif
141 usevc: 386 else if (nsap->sa_family == AF_INET)
387 salen = sizeof(struct sockaddr_in);
388 else
389 salen = 0; /*unknown, die on connect*/
390
391 same_ns:
392 if (badns & (1 << ns)) {
393 res_close();
394 goto next_ns;
395 }
396
397 if (Qhook) {
398 int done = 0, loops = 0;
399
400 do {
401 res_sendhookact act;
402
403 act = (*Qhook)((struct sockaddr_in **)&nsap,
404 &buf, &buflen,
405 ans, anssiz, &resplen);
406 switch (act) {
407 case res_goahead:
408 done = 1;
409 break;
410 case res_nextns:
411 res_close();
412 goto next_ns;
413 case res_done:
414 return (resplen);
415 case res_modified:
416 /* give the hook another try */
417 if (++loops < 42) /*doug adams*/
418 break;
419 /*FALLTHROUGH*/
420 case res_error:
421 /*FALLTHROUGH*/
422 default:
423 return (-1);
424 }
425 } while (!done);
426 }
427
428 Dprint((_res.options & RES_DEBUG) &&
429 getnameinfo(nsap, salen, abuf, sizeof(abuf),
430 NULL, 0, NI_NUMERICHOST | NI_WITHSCOPEID) == 0,
431 (stdout, ";; Querying server (# %d) address = %s\n",
432 ns + 1, abuf));
433
142 if (v_circuit) { 434 if (v_circuit) {
143 int truncated = 0; 435 int truncated;
436 struct iovec iov[2];
437 u_short len;
438 u_char *cp;
144 439
145 /* 440 /*
146 * Use virtual circuit; 441 * Use virtual circuit;
147 * at most one attempt per server. 442 * at most one attempt per server.
148 */ 443 */
149 try = _res.retry; 444 try = _res.retry;
150 if (s < 0) { 445 truncated = 0;
151 s = socket(AF_INET, SOCK_STREAM, 0); 446 if ((s < 0) || (!vc) || (af != nsap->sa_family)) {
447 if (s >= 0)
448 res_close();
449
450 af = nsap->sa_family;
451 s = socket(af, SOCK_STREAM, 0);
152 if (s < 0) { 452 if (s < 0) {
153 terrno = errno; 453 terrno = errno;
154#ifdef DEBUG 454 Perror(stderr, "socket(vc)", errno);
155 if (_res.options & RES_DEBUG) 455#if 0
156 perror("socket (vc) failed"); 456 return (-1);
457#else
458 badns |= (1 << ns);
459 res_close();
460 goto next_ns;
157#endif 461#endif
158 continue;
159 } 462 }
160 if (connect(s, 463 errno = 0;
161 (struct sockaddr *)&(_res.nsaddr_list[ns]), 464 if (connect(s, nsap, salen) < 0) {
162 sizeof(struct sockaddr)) < 0) {
163 terrno = errno; 465 terrno = errno;
164#ifdef DEBUG 466 Aerror(stderr, "connect/vc",
165 if (_res.options & RES_DEBUG) 467 errno, nsap);
166 perror("connect failed"); 468 badns |= (1 << ns);
167#endif 469 res_close();
168 (void) close(s); 470 goto next_ns;
169 s = -1;
170 continue;
171 } 471 }
472 vc = 1;
172 } 473 }
173 /* 474 /*
174 * Send length & message 475 * Send length & message
175 */ 476 */
176 len = htons((u_short)buflen); 477 putshort((u_short)buflen, (u_char*)&len);
177 iov[0].iov_base = (caddr_t)&len; 478 iov[0].iov_base = (caddr_t)&len;
178 iov[0].iov_len = sizeof(len); 479 iov[0].iov_len = INT16SZ;
179 iov[1].iov_base = (char *)buf; 480 iov[1].iov_base = (caddr_t)buf;
180 iov[1].iov_len = buflen; 481 iov[1].iov_len = buflen;
181 if (writev(s, iov, 2) != sizeof(len) + buflen) { 482 if (writev(s, iov, 2) != (INT16SZ + buflen)) {
182 terrno = errno; 483 terrno = errno;
183#ifdef DEBUG 484 Perror(stderr, "write failed", errno);
184 if (_res.options & RES_DEBUG) 485 badns |= (1 << ns);
185 perror("write failed"); 486 res_close();
186#endif 487 goto next_ns;
187 (void) close(s);
188 s = -1;
189 continue;
190 } 488 }
191 /* 489 /*
192 * Receive length & response 490 * Receive length & response
193 */ 491 */
194 cp = answer; 492read_len:
195 len = sizeof(short); 493 cp = ans;
196 while (len != 0 && 494 len = INT16SZ;
197 (n = read(s, (char *)cp, (int)len)) > 0) { 495 while ((n = read(s, (char *)cp, (int)len)) > 0) {
198 cp += n; 496 cp += n;
199 len -= n; 497 if ((len -= n) <= 0)
498 break;
200 } 499 }
201 if (n <= 0) { 500 if (n <= 0) {
202 terrno = errno; 501 terrno = errno;
203#ifdef DEBUG 502 Perror(stderr, "read failed", errno);
204 if (_res.options & RES_DEBUG) 503 res_close();
205 perror("read failed");
206#endif
207 (void) close(s);
208 s = -1;
209 /* 504 /*
210 * A long running process might get its TCP 505 * A long running process might get its TCP
211 * connection reset if the remote server was 506 * connection reset if the remote server was
@@ -217,35 +512,32 @@ res_send(buf, buflen, answer, anslen)
217 */ 512 */
218 if (terrno == ECONNRESET && !connreset) { 513 if (terrno == ECONNRESET && !connreset) {
219 connreset = 1; 514 connreset = 1;
220 ns--; 515 res_close();
516 goto same_ns;
221 } 517 }
222 continue; 518 res_close();
519 goto next_ns;
223 } 520 }
224 cp = answer; 521 resplen = _getshort(ans);
225 if ((resplen = ntohs(*(u_short *)cp)) > anslen) { 522 if (resplen > anssiz) {
226#ifdef DEBUG 523 Dprint(_res.options & RES_DEBUG,
227 if (_res.options & RES_DEBUG) 524 (stdout, ";; response truncated\n")
228 fprintf(stderr, 525 );
229 ";; response truncated\n");
230#endif
231 len = anslen;
232 truncated = 1; 526 truncated = 1;
527 len = anssiz;
233 } else 528 } else
234 len = resplen; 529 len = resplen;
530 cp = ans;
235 while (len != 0 && 531 while (len != 0 &&
236 (n = read(s, (char *)cp, (int)len)) > 0) { 532 (n = read(s, (char *)cp, (int)len)) > 0) {
237 cp += n; 533 cp += n;
238 len -= n; 534 len -= n;
239 } 535 }
240 if (n <= 0) { 536 if (n <= 0) {
241 terrno = errno; 537 terrno = errno;
242#ifdef DEBUG 538 Perror(stderr, "read(vc)", errno);
243 if (_res.options & RES_DEBUG) 539 res_close();
244 perror("read failed"); 540 goto next_ns;
245#endif
246 (void) close(s);
247 s = -1;
248 continue;
249 } 541 }
250 if (truncated) { 542 if (truncated) {
251 /* 543 /*
@@ -253,33 +545,72 @@ res_send(buf, buflen, answer, anslen)
253 * so connection stays in synch. 545 * so connection stays in synch.
254 */ 546 */
255 anhp->tc = 1; 547 anhp->tc = 1;
256 len = resplen - anslen; 548 len = resplen - anssiz;
257 while (len != 0) { 549 while (len != 0) {
258 n = (len > sizeof(junk) ? 550 char junk[PACKETSZ];
259 sizeof(junk) : len); 551
552 n = (len > sizeof(junk)
553 ? sizeof(junk)
554 : len);
260 if ((n = read(s, junk, n)) > 0) 555 if ((n = read(s, junk, n)) > 0)
261 len -= n; 556 len -= n;
262 else 557 else
263 break; 558 break;
264 } 559 }
265 } 560 }
561 /*
562 * The calling applicating has bailed out of
563 * a previous call and failed to arrange to have
564 * the circuit closed or the server has got
565 * itself confused. Anyway drop the packet and
566 * wait for the correct one.
567 */
568 if (hp->id != anhp->id) {
569 DprintQ((_res.options & RES_DEBUG) ||
570 (_res.pfcode & RES_PRF_REPLY),
571 (stdout, ";; old answer (unexpected):\n"),
572 ans, (resplen>anssiz)?anssiz:resplen);
573 goto read_len;
574 }
266 } else { 575 } else {
267 /* 576 /*
268 * Use datagrams. 577 * Use datagrams.
269 */ 578 */
270 if (s < 0) { 579 struct timeval timeout;
271 s = socket(AF_INET, SOCK_DGRAM, 0); 580 fd_set *dsmaskp;
581 struct sockaddr_storage from;
582 socklen_t fromlen;
583
584 if ((s < 0) || vc || (af != nsap->sa_family)) {
585 if (vc)
586 res_close();
587 af = nsap->sa_family;
588 s = socket(af, SOCK_DGRAM, 0);
272 if (s < 0) { 589 if (s < 0) {
590#if !CAN_RECONNECT
591 bad_dg_sock:
592#endif
273 terrno = errno; 593 terrno = errno;
274#ifdef DEBUG 594 Perror(stderr, "socket(dg)", errno);
275 if (_res.options & RES_DEBUG) 595#if 0
276 perror("socket (dg) failed"); 596 return (-1);
597#else
598 badns |= (1 << ns);
599 res_close();
600 goto next_ns;
277#endif 601#endif
278 continue;
279 } 602 }
603#ifdef IPV6_MINMTU
604 if (af == AF_INET6) {
605 const int yes = 1;
606 (void)setsockopt(s, IPPROTO_IPV6,
607 IPV6_USE_MIN_MTU, &yes,
608 sizeof(yes));
609 }
610#endif
611 connected = 0;
280 } 612 }
281 /* 613 /*
282 * I'm tired of answering this question, so:
283 * On a 4.3BSD+ machine (client and server, 614 * On a 4.3BSD+ machine (client and server,
284 * actually), sending to a nameserver datagram 615 * actually), sending to a nameserver datagram
285 * port with no nameserver will cause an 616 * port with no nameserver will cause an
@@ -294,31 +625,28 @@ res_send(buf, buflen, answer, anslen)
294 * as we wish to receive answers from the first 625 * as we wish to receive answers from the first
295 * server to respond. 626 * server to respond.
296 */ 627 */
297 if (_res.nscount == 1 || (try == 0 && ns == 0)) { 628 if (!(_res.options & RES_INSECURE1) &&
629 (_res.nscount == 1 || (try == 0 && ns == 0))) {
298 /* 630 /*
299 * Don't use connect if we might 631 * Connect only if we are sure we won't
300 * still receive a response 632 * receive a response from another server.
301 * from another server.
302 */ 633 */
303 if (connected == 0) { 634 if (!connected) {
304 if (connect(s, 635 if (connect(s, nsap, salen) < 0) {
305 (struct sockaddr *) 636 Aerror(stderr,
306 &_res.nsaddr_list[ns], 637 "connect(dg)",
307 sizeof(struct sockaddr)) < 0) { 638 errno, nsap);
308#ifdef DEBUG 639 badns |= (1 << ns);
309 if (_res.options & RES_DEBUG) 640 res_close();
310 perror("connect"); 641 goto next_ns;
311#endif
312 continue;
313 } 642 }
314 connected = 1; 643 connected = 1;
315 } 644 }
316 if (send(s, buf, buflen, 0) != buflen) { 645 if (send(s, (char*)buf, buflen, 0) != buflen) {
317#ifdef DEBUG 646 Perror(stderr, "send", errno);
318 if (_res.options & RES_DEBUG) 647 badns |= (1 << ns);
319 perror("send"); 648 res_close();
320#endif 649 goto next_ns;
321 continue;
322 } 650 }
323 } else { 651 } else {
324 /* 652 /*
@@ -326,18 +654,45 @@ res_send(buf, buflen, answer, anslen)
326 * for responses from more than one server. 654 * for responses from more than one server.
327 */ 655 */
328 if (connected) { 656 if (connected) {
329 (void) connect(s, &no_addr, 657#if CAN_RECONNECT
330 sizeof(no_addr)); 658#ifdef INET6
659 /* XXX: any errornous address */
660#endif /* INET6 */
661 struct sockaddr_in no_addr;
662
663 no_addr.sin_family = AF_INET;
664 no_addr.sin_addr.s_addr = INADDR_ANY;
665 no_addr.sin_port = 0;
666 (void) connect(s,
667 (struct sockaddr *)
668 &no_addr,
669 sizeof(no_addr));
670#else
671 int s1 = socket(af, SOCK_DGRAM,0);
672 if (s1 < 0)
673 goto bad_dg_sock;
674 (void) dup2(s1, s);
675 (void) close(s1);
676 Dprint(_res.options & RES_DEBUG,
677 (stdout, ";; new DG socket\n"))
678#endif
679#ifdef IPV6_MINMTU
680 if (af == AF_INET6) {
681 const int yes = 1;
682 (void)setsockopt(s, IPPROTO_IPV6,
683 IPV6_USE_MIN_MTU, &yes,
684 sizeof(yes));
685 }
686#endif
331 connected = 0; 687 connected = 0;
688 errno = 0;
332 } 689 }
333 if (sendto(s, buf, buflen, 0, 690 if (sendto(s, (char*)buf, buflen, 0,
334 (struct sockaddr *)&_res.nsaddr_list[ns], 691 nsap, salen) != buflen) {
335 sizeof(struct sockaddr)) != buflen) { 692 Aerror(stderr, "sendto", errno, nsap);
336#ifdef DEBUG 693 badns |= (1 << ns);
337 if (_res.options & RES_DEBUG) 694 res_close();
338 perror("sendto"); 695 goto next_ns;
339#endif
340 continue;
341 } 696 }
342 } 697 }
343 698
@@ -350,110 +705,170 @@ res_send(buf, buflen, answer, anslen)
350 if ((long) timeout.tv_sec <= 0) 705 if ((long) timeout.tv_sec <= 0)
351 timeout.tv_sec = 1; 706 timeout.tv_sec = 1;
352 timeout.tv_usec = 0; 707 timeout.tv_usec = 0;
353wait: 708 wait:
354 FD_ZERO(&dsmask); 709 dsmaskp = (fd_set *)calloc(howmany(s+1, NFDBITS),
355 FD_SET(s, &dsmask); 710 sizeof(fd_mask));
356 n = select(s+1, &dsmask, (fd_set *)NULL, 711 if (dsmaskp == NULL) {
357 (fd_set *)NULL, &timeout); 712 res_close();
713 goto next_ns;
714 }
715 FD_SET(s, dsmaskp);
716 n = select(s+1, dsmaskp, (fd_set *)NULL,
717 (fd_set *)NULL, &timeout);
718 free(dsmaskp);
358 if (n < 0) { 719 if (n < 0) {
359#ifdef DEBUG 720 if (errno == EINTR)
360 if (_res.options & RES_DEBUG) 721 goto wait;
361 perror("select"); 722 Perror(stderr, "select", errno);
362#endif 723 res_close();
363 continue; 724 goto next_ns;
364 } 725 }
365 if (n == 0) { 726 if (n == 0) {
366 /* 727 /*
367 * timeout 728 * timeout
368 */ 729 */
369#ifdef DEBUG 730 Dprint(_res.options & RES_DEBUG,
370 if (_res.options & RES_DEBUG) 731 (stdout, ";; timeout\n"));
371 printf(";; timeout\n");
372#endif
373 gotsomewhere = 1; 732 gotsomewhere = 1;
374 continue; 733 res_close();
734 goto next_ns;
375 } 735 }
376 if ((resplen = recv(s, answer, anslen, 0)) <= 0) { 736 errno = 0;
377#ifdef DEBUG 737 fromlen = sizeof(from);
378 if (_res.options & RES_DEBUG) 738 resplen = recvfrom(s, (char*)ans, anssiz, 0,
379 perror("recvfrom"); 739 (struct sockaddr *)&from, &fromlen);
380#endif 740 if (resplen <= 0) {
381 continue; 741 Perror(stderr, "recvfrom", errno);
742 res_close();
743 goto next_ns;
382 } 744 }
383 gotsomewhere = 1; 745 gotsomewhere = 1;
384 if (id != anhp->id) { 746 if (hp->id != anhp->id) {
385 /* 747 /*
386 * response from old query, ignore it 748 * response from old query, ignore it.
749 * XXX - potential security hazard could
750 * be detected here.
387 */ 751 */
388#ifdef DEBUG 752 DprintQ((_res.options & RES_DEBUG) ||
389 if ((_res.options & RES_DEBUG) || 753 (_res.pfcode & RES_PRF_REPLY),
390 (_res.pfcode & RES_PRF_REPLY)) { 754 (stdout, ";; old answer:\n"),
391 printf(";; old answer:\n"); 755 ans, (resplen>anssiz)?anssiz:resplen);
392 __p_query(answer); 756 goto wait;
393 } 757 }
758#if CHECK_SRVR_ADDR
759 if (!(_res.options & RES_INSECURE1) &&
760 !res_isourserver((struct sockaddr_in *)&from)) {
761 /*
762 * response from wrong server? ignore it.
763 * XXX - potential security hazard could
764 * be detected here.
765 */
766 DprintQ((_res.options & RES_DEBUG) ||
767 (_res.pfcode & RES_PRF_REPLY),
768 (stdout, ";; not our server:\n"),
769 ans, (resplen>anssiz)?anssiz:resplen);
770 goto wait;
771 }
394#endif 772#endif
773 if (!(_res.options & RES_INSECURE2) &&
774 !res_queriesmatch(buf, buf + buflen,
775 ans, ans + anssiz)) {
776 /*
777 * response contains wrong query? ignore it.
778 * XXX - potential security hazard could
779 * be detected here.
780 */
781 DprintQ((_res.options & RES_DEBUG) ||
782 (_res.pfcode & RES_PRF_REPLY),
783 (stdout, ";; wrong query name:\n"),
784 ans, (resplen>anssiz)?anssiz:resplen);
395 goto wait; 785 goto wait;
396 } 786 }
397 if (anhp->rcode == SERVFAIL || anhp->rcode == NOTIMP || 787 if (anhp->rcode == SERVFAIL ||
788 anhp->rcode == NOTIMP ||
398 anhp->rcode == REFUSED) { 789 anhp->rcode == REFUSED) {
399#ifdef DEBUG 790 DprintQ(_res.options & RES_DEBUG,
400 if (_res.options & RES_DEBUG) { 791 (stdout, "server rejected query:\n"),
401 printf("server rejected query:\n"); 792 ans, (resplen>anssiz)?anssiz:resplen);
402 __p_query(answer); 793 badns |= (1 << ns);
403 } 794 res_close();
404#endif 795 /* don't retry if called from dig */
405 badns |= (1<<ns); 796 if (!_res.pfcode)
406 continue; 797 goto next_ns;
407 } 798 }
408 if (!(_res.options & RES_IGNTC) && anhp->tc) { 799 if (!(_res.options & RES_IGNTC) && anhp->tc) {
409 /* 800 /*
410 * get rest of answer; 801 * get rest of answer;
411 * use TCP with same server. 802 * use TCP with same server.
412 */ 803 */
413#ifdef DEBUG 804 Dprint(_res.options & RES_DEBUG,
414 if (_res.options & RES_DEBUG) 805 (stdout, ";; truncated answer\n"));
415 printf(";; truncated answer\n");
416#endif
417 (void) close(s);
418 s = -1;
419 v_circuit = 1; 806 v_circuit = 1;
420 goto usevc; 807 res_close();
808 goto same_ns;
421 } 809 }
422 } 810 } /*if vc/dg*/
423#ifdef DEBUG 811 Dprint((_res.options & RES_DEBUG) ||
424 if (_res.options & RES_DEBUG) 812 ((_res.pfcode & RES_PRF_REPLY) &&
425 printf(";; got answer:\n"); 813 (_res.pfcode & RES_PRF_HEAD1)),
426 if ((_res.options & RES_DEBUG) || 814 (stdout, ";; got answer:\n"));
427 (_res.pfcode & RES_PRF_REPLY)) 815 DprintQ((_res.options & RES_DEBUG) ||
428 __p_query(answer); 816 (_res.pfcode & RES_PRF_REPLY),
429#endif 817 (stdout, "%s", ""),
818 ans, (resplen>anssiz)?anssiz:resplen);
430 /* 819 /*
431 * If using virtual circuits, we assume that the first server 820 * If using virtual circuits, we assume that the first server
432 * is preferred * over the rest (i.e. it is on the local 821 * is preferred over the rest (i.e. it is on the local
433 * machine) and only keep that one open. 822 * machine) and only keep that one open.
434 * If we have temporarily opened a virtual circuit, 823 * If we have temporarily opened a virtual circuit,
435 * or if we haven't been asked to keep a socket open, 824 * or if we haven't been asked to keep a socket open,
436 * close the socket. 825 * close the socket.
437 */ 826 */
438 if ((v_circuit && 827 if ((v_circuit && (!(_res.options & RES_USEVC) || ns != 0)) ||
439 ((_res.options & RES_USEVC) == 0 || ns != 0)) || 828 !(_res.options & RES_STAYOPEN)) {
440 (_res.options & RES_STAYOPEN) == 0) { 829 res_close();
441 (void) close(s); 830 }
442 s = -1; 831 if (Rhook) {
832 int done = 0, loops = 0;
833
834 do {
835 res_sendhookact act;
836
837 act = (*Rhook)((struct sockaddr_in *)nsap,
838 buf, buflen,
839 ans, anssiz, &resplen);
840 switch (act) {
841 case res_goahead:
842 case res_done:
843 done = 1;
844 break;
845 case res_nextns:
846 res_close();
847 goto next_ns;
848 case res_modified:
849 /* give the hook another try */
850 if (++loops < 42) /*doug adams*/
851 break;
852 /*FALLTHROUGH*/
853 case res_error:
854 /*FALLTHROUGH*/
855 default:
856 return (-1);
857 }
858 } while (!done);
859
443 } 860 }
444 return (resplen); 861 return (resplen);
445 } 862 next_ns: ;
446 } 863 } /*foreach ns*/
447 if (s >= 0) { 864 } /*foreach retry*/
448 (void) close(s); 865 res_close();
449 s = -1; 866 if (!v_circuit) {
450 } 867 if (!gotsomewhere)
451 if (v_circuit == 0)
452 if (gotsomewhere == 0)
453 errno = ECONNREFUSED; /* no nameservers found */ 868 errno = ECONNREFUSED; /* no nameservers found */
454 else 869 else
455 errno = ETIMEDOUT; /* no answer obtained */ 870 errno = ETIMEDOUT; /* no answer obtained */
456 else 871 } else
457 errno = terrno; 872 errno = terrno;
458 return (-1); 873 return (-1);
459} 874}
@@ -465,10 +880,14 @@ wait:
465 * 880 *
466 * This routine is not expected to be user visible. 881 * This routine is not expected to be user visible.
467 */ 882 */
468_res_close() 883void
884res_close()
469{ 885{
470 if (s != -1) { 886 if (s >= 0) {
471 (void) close(s); 887 (void) close(s);
472 s = -1; 888 s = -1;
889 connected = 0;
890 vc = 0;
891 af = 0;
473 } 892 }
474} 893}
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..5392a2f11b 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.4 1997/03/15 21:53:50 pefo 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>
@@ -49,7 +43,11 @@ static char rcsid[] = "$NetBSD: sethostent.c,v 1.4 1995/02/25 06:21:03 cgd Exp $
49 43
50void 44void
51sethostent(stayopen) 45sethostent(stayopen)
46 int stayopen;
52{ 47{
48
49 if ((_res.options & RES_INIT) == 0 && res_init() == -1)
50 return;
53 if (stayopen) 51 if (stayopen)
54 _res.options |= RES_STAYOPEN | RES_USEVC; 52 _res.options |= RES_STAYOPEN | RES_USEVC;
55} 53}
@@ -58,5 +56,5 @@ void
58endhostent() 56endhostent()
59{ 57{
60 _res.options &= ~(RES_STAYOPEN | RES_USEVC); 58 _res.options &= ~(RES_STAYOPEN | RES_USEVC);
61 _res_close(); 59 res_close();
62} 60}
diff --git a/src/lib/libc/net/vars6.c b/src/lib/libc/net/vars6.c
new file mode 100644
index 0000000000..6d0f069ef6
--- /dev/null
+++ b/src/lib/libc/net/vars6.c
@@ -0,0 +1,42 @@
1/* $OpenBSD: vars6.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/types.h>
33#include <netinet/in.h>
34
35/*
36 * Definitions of some costant 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..4b4c88b9af 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 bsearch.c calloc.c \
8 exit.c getenv.c getopt.c heapsort.c l64a.c malloc.c merge.c \ 7 cfree.c exit.c getenv.c getopt.c getsubopt.c heapsort.c l64a.c \
9 multibyte.c putenv.c qsort.c radixsort.c rand.c random.c realpath.c \ 8 malloc.c merge.c multibyte.c putenv.c qsort.c radixsort.c rand.c \
10 setenv.c strtod.c strtol.c strtoq.c strtoul.c strtouq.c system.c \ 9 random.c realpath.c setenv.c strtod.c strtol.c strtoll.c strtoul.c \
10 strtoull.c system.c tfind.c tsearch.c \
11 _rand48.c drand48.c erand48.c jrand48.c lcong48.c lrand48.c \ 11 _rand48.c drand48.c erand48.c jrand48.c lcong48.c lrand48.c \
12 mrand48.c nrand48.c seed48.c srand48.c qabs.c qdiv.c 12 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,25 @@ 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 \ 35MAN+= a64l.3 abort.3 abs.3 alloca.3 atexit.3 atof.3 atoi.3 atol.3 bsearch.3 \
32 calloc.3 div.3 exit.3 free.3 getenv.3 getopt.3 labs.3 ldiv.3 \ 36 div.3 exit.3 getenv.3 getopt.3 getsubopt.3 labs.3 ldiv.3 \
33 malloc.3 memory.3 qabs.3 qdiv.3 qsort.3 radixsort.3 rand48.3 \ 37 malloc.3 memory.3 qabs.3 qdiv.3 qsort.3 radixsort.3 rand48.3 rand.3 \
34 rand.3 random.3 realloc.3 realpath.3 strtod.3 strtol.3 strtoul.3 \ 38 random.3 realpath.3 strtod.3 strtol.3 strtoul.3 system.3 tsearch.3
35 system.3
36 39
37MLINKS+=getenv.3 setenv.3 getenv.3 unsetenv.3 getenv.3 putenv.3 40MLINKS+=getenv.3 setenv.3 getenv.3 unsetenv.3 getenv.3 putenv.3
41MLINKS+=malloc.3 free.3 malloc.3 realloc.3 malloc.3 calloc.3
42MLINKS+=malloc.3 cfree.3 malloc.3 malloc.conf.5
38MLINKS+=qsort.3 heapsort.3 qsort.3 mergesort.3 43MLINKS+=qsort.3 heapsort.3 qsort.3 mergesort.3
39MLINKS+=rand.3 srand.3 44MLINKS+=radixsort.3 sradixsort.3
40MLINKS+=strtol.3 strtoq.3 45MLINKS+=rand.3 srand.3 rand.3 rand_r.3
41MLINKS+=strtoul.3 strtouq.3 46MLINKS+=random.3 initstate.3 random.3 setstate.3
42MLINKS+=random.3 initstate.3 random.3 setstate.3 random.3 srandom.3 47MLINKS+=random.3 srandom.3 random.3 srandomdev.3
43MLINKS+=rand48.3 drand48.3 rand48.3 erand48.3 rand48.3 lrand48.3 48MLINKS+=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 49MLINKS+=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 50MLINKS+=rand48.3 srand48.3 rand48.3 seed48.3 rand48.3 lcong48.3
51MLINKS+=strtol.3 strtoll.3 strtol.3 strtoq.3
52MLINKS+=strtoul.3 strtoull.3 strtoul.3 strtouq.3
53MLINKS+=tsearch.3 tfind.3
54MLINKS+=tsearch.3 tdelete.3
55MLINKS+=tsearch.3 twalk.3
56MLINKS+=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..787634303c
--- /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.5 2000/04/20 13:50:01 aaron 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..41a9f0f48b 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.7 2001/08/12 12:03:01 heko 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
43void (*__cleanup)();
42 44
43void 45void
44abort() 46abort()
45{ 47{
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);
58#ifdef _THREAD_SAFE
59 (void)_thread_sys_sigprocmask(SIG_SETMASK, &mask, (sigset_t *)NULL);
60#else /* _THREAD_SAFE */
54 (void)sigprocmask(SIG_SETMASK, &mask, (sigset_t *)NULL); 61 (void)sigprocmask(SIG_SETMASK, &mask, (sigset_t *)NULL);
62#endif /* _THREAD_SAFE */
63
64 /*
65 * POSIX requires we flush stdio buffers on abort
66 */
67 if (cleanup_called == 0 && __cleanup != NULL) {
68 cleanup_called = 1;
69 (*__cleanup)();
70 }
71
55 (void)kill(getpid(), SIGABRT); 72 (void)kill(getpid(), SIGABRT);
56 73
57 /* 74 /*
@@ -59,7 +76,11 @@ 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);
79#ifdef _THREAD_SAFE
80 (void)_thread_sys_sigprocmask(SIG_SETMASK, &mask, (sigset_t *)NULL);
81#else /* _THREAD_SAFE */
62 (void)sigprocmask(SIG_SETMASK, &mask, (sigset_t *)NULL); 82 (void)sigprocmask(SIG_SETMASK, &mask, (sigset_t *)NULL);
83#endif /* _THREAD_SAFE */
63 (void)kill(getpid(), SIGABRT); 84 (void)kill(getpid(), SIGABRT);
64 exit(1); 85 exit(1);
65} 86}
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..da5a0ddda0 100644
--- a/src/lib/libc/stdlib/atexit.c
+++ b/src/lib/libc/stdlib/atexit.c
@@ -1,47 +1,44 @@
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.6 2002/09/06 22:48:34 henning 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/*
@@ -51,18 +48,37 @@ int
51atexit(fn) 48atexit(fn)
52 void (*fn)(); 49 void (*fn)();
53{ 50{
54 static struct atexit __atexit0; /* one guaranteed table */ 51 register struct atexit *p = __atexit;
55 register struct atexit *p; 52 register int pgsize = getpagesize();
56 53
57 if ((p = __atexit) == NULL) 54 if (pgsize < sizeof(*p))
58 __atexit = p = &__atexit0; 55 return (-1);
59 else if (p->ind >= ATEXIT_SIZE) { 56 if (p != NULL) {
60 if ((p = malloc(sizeof(*p))) == NULL) 57 if (p->ind + 1 >= p->max)
58 p = NULL;
59 else if (mprotect(p, pgsize, PROT_READ | PROT_WRITE))
60 return (-1);
61 }
62 if (p == NULL) {
63 if (__atexit_invalid) {
64 /* malloc.c wants the first mmap() for sbrk()
65 games ('nice hack'), so enforce
66 malloc_init() with a dummy call. */
67 free(malloc(1));
68 __atexit_invalid = 0;
69 }
70 p = mmap(NULL, pgsize, PROT_READ | PROT_WRITE,
71 MAP_ANON | MAP_PRIVATE, -1, 0);
72 if (p == MAP_FAILED)
61 return (-1); 73 return (-1);
62 p->ind = 0; 74 p->ind = 0;
75 p->max = (pgsize - ((char *)&p->fns[0] - (char *)p)) /
76 sizeof(p->fns[0]);
63 p->next = __atexit; 77 p->next = __atexit;
64 __atexit = p; 78 __atexit = p;
65 } 79 }
66 p->fns[p->ind++] = fn; 80 p->fns[p->ind++] = fn;
81 if (mprotect(p, pgsize, PROT_READ))
82 return (-1);
67 return (0); 83 return (0);
68} 84}
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..53a518997f 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.4 2000/04/20 13:50:01 aaron 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:
@@ -70,6 +69,5 @@ strtol(nptr, (char **)NULL, 10);
70.Sh STANDARDS 69.Sh STANDARDS
71The 70The
72.Fn atol 71.Fn atol
73function 72function conforms to
74conforms to
75.St -ansiC . 73.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/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/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..bcfdfd38f5 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.6 2001/07/27 23:48:12 mpech 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,27 @@ Unlink all files created with the
66.Xr tmpfile 3 66.Xr tmpfile 3
67function. 67function.
68.El 68.El
69Following this,
70.Fn exit
71calls
72.Xr _exit 2 .
73Note that typically
74.Xr exit 2
75only passes the lower 8 bits of
76.Fa status
77on to the parent, thus negative values have less meaning.
69.Sh RETURN VALUES 78.Sh RETURN VALUES
70The 79The
71.Fn exit 80.Fn exit
72function 81function never returns.
73never returns.
74.Sh SEE ALSO 82.Sh SEE ALSO
75.Xr _exit 2 , 83.Xr _exit 2 ,
76.Xr atexit 3 , 84.Xr atexit 3 ,
77.Xr intro 3 , 85.Xr intro 3 ,
86.Xr sysexits 3 ,
78.Xr tmpfile 3 87.Xr tmpfile 3
79.Sh STANDARDS 88.Sh STANDARDS
80The 89The
81.Fn exit 90.Fn exit
82function 91function conforms to
83conforms to
84.St -ansiC . 92.St -ansiC .
diff --git a/src/lib/libc/stdlib/exit.c b/src/lib/libc/stdlib/exit.c
index b1412f42bb..c69639125e 100644
--- a/src/lib/libc/stdlib/exit.c
+++ b/src/lib/libc/stdlib/exit.c
@@ -32,29 +32,47 @@
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.7 2002/08/30 07:58:07 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)(); 45void (*__cleanup)();
44 46
45/* 47/*
48 * This variable is zero until a process has created a thread.
49 * It is used to avoid calling locking functions in libc when they
50 * are not required. By default, libc is intended to be(come)
51 * thread-safe, but without a (significant) penalty to non-threaded
52 * processes.
53 */
54int __isthreaded = 0;
55
56/*
46 * Exit, flushing stdio buffers if necessary. 57 * Exit, flushing stdio buffers if necessary.
47 */ 58 */
48void 59void
49exit(status) 60exit(status)
50 int status; 61 int status;
51{ 62{
52 register struct atexit *p; 63 register struct atexit *p, *q;
53 register int n; 64 register int n, pgsize = getpagesize();
54 65
55 for (p = __atexit; p; p = p->next) 66 if (!__atexit_invalid) {
56 for (n = p->ind; --n >= 0;) 67 p = __atexit;
57 (*p->fns[n])(); 68 while (p != NULL) {
69 for (n = p->ind; --n >= 0;)
70 (*p->fns[n])();
71 q = p;
72 p = p->next;
73 munmap(q, pgsize);
74 }
75 }
58 if (__cleanup) 76 if (__cleanup)
59 (*__cleanup)(); 77 (*__cleanup)();
60 _exit(status); 78 _exit(status);
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/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..4db86df915 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,28 +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.4 1998/07/16 18:02:33 deraadt 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/* 41/*
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
56/*
57 * __findenv -- 42 * __findenv --
58 * Returns pointer to value associated with name, if any, else NULL. 43 * Returns pointer to value associated with name, if any, else NULL.
59 * Sets offset to be the offset of the name/value combination in the 44 * Sets offset to be the offset of the name/value combination in the
@@ -64,19 +49,41 @@ getenv(name)
64 */ 49 */
65char * 50char *
66__findenv(name, offset) 51__findenv(name, offset)
67 register char *name; 52 register const char *name;
68 int *offset; 53 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;
73 59
74 for (C = name, len = 0; *C && *C != '='; ++C, ++len); 60 if (name == NULL || environ == NULL)
75 for (P = environ; *P; ++P) 61 return (NULL);
76 if (!strncmp(*P, name, len)) 62 for (np = name; *np && *np != '='; ++np)
77 if (*(C = *P + len) == '=') { 63 ;
78 *offset = P - environ; 64 len = np - name;
79 return(++C); 65 for (p = environ; (cp = *p) != NULL; ++p) {
80 } 66 for (np = name, i = len; i && *cp; i--)
81 return(NULL); 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;
86 char *__findenv();
87
88 return(__findenv(name, &offset));
82} 89}
diff --git a/src/lib/libc/stdlib/getopt.3 b/src/lib/libc/stdlib/getopt.3
index f843881afd..4acbe69606 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.17 2002/08/19 22:29:52 miod Exp $
33.\" 33.\"
34.Dd April 19, 1994 34.Dd April 19, 1994
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,31 +126,58 @@ 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.
129.Sh EXAMPLES
130.Bd -literal -compact
131int bflag, ch, fd;
132
133bflag = 0;
134while ((ch = getopt(argc, argv, "bf:")) != -1) {
135 switch (ch) {
136 case 'b':
137 bflag = 1;
138 break;
139 case 'f':
140 if ((fd = open(optarg, O_RDONLY, 0)) < 0) {
141 (void)fprintf(stderr,
142 "myname: %s: %s\en", optarg, strerror(errno));
143 exit(1);
144 }
145 break;
146 case '?':
147 default:
148 usage();
149 }
150}
151argc -= optind;
152argv += optind;
153.Ed
154.Sh SEE ALSO
155.Xr getopt 1 ,
156.Xr getsubopt 3
136.Sh DIAGNOSTICS 157.Sh DIAGNOSTICS
137If the 158If the
138.Fn getopt 159.Fn getopt
139function encounters a character not found in the string 160function encounters a character not found in the string
140.Va optarg 161.Va optstring
141or detects 162or detects
142a missing option argument it writes an error message and returns 163a missing option argument it writes an error message to
143.Ql ? 164.Em stderr
144to the 165and returns
145.Em stderr . 166.Ql ? .
146Setting 167Setting
147.Va opterr 168.Va opterr
148to a zero will disable these error messages. 169to a zero will disable these error messages.
149If 170If
150.Va optstring 171.Va optstring
151has a leading 172has a leading
152.Ql \&: 173.Ql \&:
153then a missing option argument causes a 174then a missing option argument causes a
154.Ql \&: 175.Ql \&:
155to be returned in addition to suppressing any error messages. 176to be returned in addition to suppressing any error messages.
156.Pp 177.Pp
157Option arguments are allowed to begin with 178Option arguments are allowed to begin with
158.Dq Li \- ; 179.Ql - ;
159this is reasonable but 180this is reasonable but reduces the amount of error checking possible.
160reduces the amount of error checking possible.
161.Sh EXTENSIONS 181.Sh EXTENSIONS
162The 182The
163.Va optreset 183.Va optreset
@@ -167,53 +187,27 @@ function multiple times.
167This is an extension to the 187This is an extension to the
168.St -p1003.2 188.St -p1003.2
169specification. 189specification.
170.Sh EXAMPLE
171.Bd -literal -compact
172extern char *optarg;
173extern int optind;
174int bflag, ch, fd;
175
176bflag = 0;
177while ((ch = getopt(argc, argv, "bf:")) != -1)
178 switch(ch) {
179 case 'b':
180 bflag = 1;
181 break;
182 case 'f':
183 if ((fd = open(optarg, O_RDONLY, 0)) < 0) {
184 (void)fprintf(stderr,
185 "myname: %s: %s\en", optarg, strerror(errno));
186 exit(1);
187 }
188 break;
189 case '?':
190 default:
191 usage();
192}
193argc -= optind;
194argv += optind;
195.Ed
196.Sh HISTORY 190.Sh HISTORY
197The 191The
198.Fn getopt 192.Fn getopt
199function appeared 193function appeared in
200.Bx 4.3 . 194.Bx 4.3 .
201.Sh BUGS 195.Sh BUGS
202The 196The
203.Fn getopt 197.Fn getopt
204function was once specified to return 198function was once specified to return
205.Dv EOF 199.Dv EOF
206instead of \-1. 200instead of \-1.
207This was changed by 201This was changed by
208.St -p1003.2-92 202.St -p1003.2-92
209to decouple 203to decouple
210.Fn getopt 204.Fn getopt
211from 205from
212.Pa <stdio.h> . 206.Pa <stdio.h> .
213.Pp 207.Pp
214A single dash 208A single dash
215.Dq Li - 209.Pq Ql -
216may be specified as an character in 210may be specified as a character in
217.Fa optstring , 211.Fa optstring ,
218however it should 212however it should
219.Em never 213.Em never
@@ -221,7 +215,7 @@ have an argument associated with it.
221This allows 215This allows
222.Fn getopt 216.Fn getopt
223to be used with programs that expect 217to be used with programs that expect
224.Dq Li - 218.Ql -
225as an option flag. 219as an option flag.
226This practice is wrong, and should not be used in any current development. 220This practice is wrong, and should not be used in any current development.
227It is provided for backward compatibility 221It is provided for backward compatibility
@@ -242,18 +236,18 @@ It is provided for backward compatibility
242.Em only . 236.Em only .
243The following code fragment works in most cases. 237The following code fragment works in most cases.
244.Bd -literal -offset indent 238.Bd -literal -offset indent
245int length; 239long length;
246char *p; 240char *p;
247 241
248while ((c = getopt(argc, argv, "0123456789")) != -1) 242while ((c = getopt(argc, argv, "0123456789")) != -1) {
249 switch (c) { 243 switch (c) {
250 case '0': case '1': case '2': case '3': case '4': 244 case '0': case '1': case '2': case '3': case '4':
251 case '5': case '6': case '7': case '8': case '9': 245 case '5': case '6': case '7': case '8': case '9':
252 p = argv[optind - 1]; 246 p = argv[optind - 1];
253 if (p[0] == '-' && p[1] == ch && !p[2]) 247 if (p[0] == '-' && p[1] == ch && !p[2])
254 length = atoi(++p); 248 length = ch - '0';
255 else 249 else
256 length = atoi(argv[optind] + 1); 250 length = strtol(argv[optind] + 1, NULL, 10);
257 break; 251 break;
258 } 252 }
259} 253}
diff --git a/src/lib/libc/stdlib/getopt.c b/src/lib/libc/stdlib/getopt.c
index 63c5e6a479..b7f6163662 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.2 1996/08/19 08:33:32 tholo 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>
diff --git a/src/lib/libc/stdlib/getsubopt.3 b/src/lib/libc/stdlib/getsubopt.3
new file mode 100644
index 0000000000..8a17da4ea5
--- /dev/null
+++ b/src/lib/libc/stdlib/getsubopt.3
@@ -0,0 +1,147 @@
1.\" $OpenBSD: getsubopt.3,v 1.5 2000/12/15 14:31:17 aaron 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/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/malloc.3 b/src/lib/libc/stdlib/malloc.3
index 3bbf2bf65e..8f05c38e86 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.24 2001/12/05 09:49:39 deraadt 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
259is 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..4e90ce402e 100644
--- a/src/lib/libc/stdlib/malloc.c
+++ b/src/lib/libc/stdlib/malloc.c
@@ -1,421 +1,1305 @@
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.48 2002/05/27 03:13:23 deraadt 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 <errno.h>
50
51/*
52 * The basic parameters you can tweak.
53 *
54 * malloc_pageshift pagesize = 1 << malloc_pageshift
55 * It's probably best if this is the native
56 * page size, but it shouldn't have to be.
57 *
58 * malloc_minsize minimum size of an allocation in bytes.
59 * If this is too small it's too much work
60 * to manage them. This is also the smallest
61 * unit of alignment used for the storage
62 * returned by malloc/realloc.
63 *
64 */
65
66#if defined(__OpenBSD__) && defined(__sparc__)
67# define malloc_pageshift 13U
68#endif /* __OpenBSD__ */
69
70#ifdef _THREAD_SAFE
71# include "thread_private.h"
72# if 0
73 /* kernel threads */
74# include <pthread.h>
75 static pthread_mutex_t malloc_lock;
76# define THREAD_LOCK() pthread_mutex_lock(&malloc_lock)
77# define THREAD_UNLOCK() pthread_mutex_unlock(&malloc_lock)
78# define THREAD_LOCK_INIT() pthread_mutex_init(&malloc_lock, 0);
79# else
80 /* user threads */
81# include "spinlock.h"
82 static spinlock_t malloc_lock = _SPINLOCK_INITIALIZER;
83# define THREAD_LOCK() if (__isthreaded) _SPINLOCK(&malloc_lock)
84# define THREAD_UNLOCK() if (__isthreaded) _SPINUNLOCK(&malloc_lock)
85# define THREAD_LOCK_INIT()
86 /*
87 * Malloc can't use the wrapped write() if it fails very early, so
88 * we use the unwrapped syscall _thread_sys_write()
89 */
90# define write _thread_sys_write
91 ssize_t write(int, const void *, size_t);
92# undef malloc
93# undef realloc
94# undef free
95# endif
96#else
97 /* no threads */
98# define THREAD_LOCK()
99# define THREAD_UNLOCK()
100# define THREAD_LOCK_INIT()
101#endif
54 102
55#define NULL 0 103/*
104 * No user serviceable parts behind this point.
105 *
106 * This structure describes a page worth of chunks.
107 */
56 108
57static void morecore(); 109struct pginfo {
58static int findbucket(); 110 struct pginfo *next; /* next on the free list */
111 void *page; /* Pointer to the page */
112 u_short size; /* size of this page's chunks */
113 u_short shift; /* How far to shift for this size chunks */
114 u_short free; /* How many free chunks */
115 u_short total; /* How many chunk */
116 u_long bits[1]; /* Which chunks are free */
117};
59 118
60/* 119/*
61 * The overhead on a block is at least 4 bytes. When free, this space 120 * This structure describes a number of free pages.
62 * contains a pointer to the next free block, and the bottom two bits must
63 * be zero. When in use, the first byte is set to MAGIC, and the second
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 */ 121 */
70union overhead { 122
71 union overhead *ov_next; /* when free */ 123struct pgfree {
72 struct { 124 struct pgfree *next; /* next run of free pages */
73 u_char ovu_magic; /* magic number */ 125 struct pgfree *prev; /* prev run of free pages */
74 u_char ovu_index; /* bucket # */ 126 void *page; /* pointer to free pages */
75#ifdef RCHECK 127 void *end; /* pointer to end of free pages */
76 u_short ovu_rmagic; /* range magic number */ 128 u_long size; /* number of bytes free */
77 u_long ovu_size; /* actual block size */
78#endif
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}; 129};
85 130
86#define MAGIC 0xef /* magic # on accounting info */ 131/*
87#define RMAGIC 0x5555 /* magic # on range info */ 132 * How many bits per u_long in the bitmap.
133 * Change only if not 8 bits/byte
134 */
135#define MALLOC_BITS (8*sizeof(u_long))
136
137/*
138 * Magic values to put in the page_directory
139 */
140#define MALLOC_NOT_MINE ((struct pginfo*) 0)
141#define MALLOC_FREE ((struct pginfo*) 1)
142#define MALLOC_FIRST ((struct pginfo*) 2)
143#define MALLOC_FOLLOW ((struct pginfo*) 3)
144#define MALLOC_MAGIC ((struct pginfo*) 4)
145
146#ifndef malloc_pageshift
147#define malloc_pageshift (PGSHIFT)
148#endif
149
150#ifndef malloc_minsize
151#define malloc_minsize 16U
152#endif
153
154#ifndef malloc_pageshift
155#error "malloc_pageshift undefined"
156#endif
157
158#if !defined(malloc_pagesize)
159#define malloc_pagesize (1UL<<malloc_pageshift)
160#endif
161
162#if ((1UL<<malloc_pageshift) != malloc_pagesize)
163#error "(1UL<<malloc_pageshift) != malloc_pagesize"
164#endif
165
166#ifndef malloc_maxsize
167#define malloc_maxsize ((malloc_pagesize)>>1)
168#endif
88 169
89#ifdef RCHECK 170/* A mask for the offset inside a page. */
90#define RSLOP sizeof (u_short) 171#define malloc_pagemask ((malloc_pagesize)-1)
172
173#define pageround(foo) (((foo) + (malloc_pagemask))&(~(malloc_pagemask)))
174#define ptr2index(foo) (((u_long)(foo) >> malloc_pageshift)-malloc_origo)
175
176/* fd of /dev/zero */
177#ifdef USE_DEV_ZERO
178static int fdzero;
179#define MMAP_FD fdzero
180#define INIT_MMAP() \
181 { if ((fdzero=open("/dev/zero", O_RDWR, 0000)) == -1) \
182 wrterror("open of /dev/zero"); }
91#else 183#else
92#define RSLOP 0 184#define MMAP_FD (-1)
185#define INIT_MMAP()
186#endif
187
188/* Set when initialization has been done */
189static unsigned int malloc_started;
190
191/* Number of free pages we cache */
192static unsigned int malloc_cache = 16;
193
194/* The offset from pagenumber to index into the page directory */
195static u_long malloc_origo;
196
197/* The last index in the page directory we care about */
198static u_long last_index;
199
200/* Pointer to page directory. Allocated "as if with" malloc */
201static struct pginfo **page_dir;
202
203/* How many slots in the page directory */
204static size_t malloc_ninfo;
205
206/* Free pages line up here */
207static struct pgfree free_list;
208
209/* Abort(), user doesn't handle problems. */
210static int malloc_abort;
211
212/* Are we trying to die ? */
213static int suicide;
214
215#ifdef MALLOC_STATS
216/* dump statistics */
217static int malloc_stats;
218#endif
219
220/* avoid outputting warnings? */
221static int malloc_silent;
222
223/* always realloc ? */
224static int malloc_realloc;
225
226#if defined(__FreeBSD__) || (defined(__OpenBSD__) && defined(MADV_FREE))
227/* pass the kernel a hint on free pages ? */
228static int malloc_hint;
229#endif
230
231/* xmalloc behaviour ? */
232static int malloc_xmalloc;
233
234/* zero fill ? */
235static int malloc_zero;
236
237/* junk fill ? */
238static int malloc_junk;
239
240#ifdef __FreeBSD__
241/* utrace ? */
242static int malloc_utrace;
243
244struct ut { void *p; size_t s; void *r; };
245
246void utrace(struct ut *, int);
247
248#define UTRACE(a, b, c) \
249 if (malloc_utrace) \
250 {struct ut u; u.p=a; u.s = b; u.r=c; utrace(&u, sizeof u);}
251#else /* !__FreeBSD__ */
252#define UTRACE(a,b,c)
93#endif 253#endif
94 254
255/* my last break. */
256static void *malloc_brk;
257
258/* one location cache for free-list holders */
259static struct pgfree *px;
260
261/* compile-time options */
262char *malloc_options;
263
264/* Name of the current public function */
265static char *malloc_func;
266
267/* Macro for mmap */
268#define MMAP(size) \
269 mmap((void *)0, (size), PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, \
270 MMAP_FD, (off_t)0);
271
95/* 272/*
96 * nextf[i] is the pointer to the next free block of size 2^(i+3). The 273 * Necessary function declarations
97 * smallest allocatable block is 8 bytes. The overhead information
98 * precedes the data area returned to the user.
99 */ 274 */
100#define NBUCKETS 30 275static int extend_pgdir(u_long index);
101static union overhead *nextf[NBUCKETS]; 276static void *imalloc(size_t size);
102extern char *sbrk(); 277static void ifree(void *ptr);
278static void *irealloc(void *ptr, size_t size);
279static void *malloc_bytes(size_t size);
280
281#ifdef MALLOC_STATS
282void
283malloc_dump(fd)
284 FILE *fd;
285{
286 struct pginfo **pd;
287 struct pgfree *pf;
288 int j;
289
290 pd = page_dir;
291
292 /* print out all the pages */
293 for(j=0;j<=last_index;j++) {
294 fprintf(fd, "%08lx %5d ", (j+malloc_origo) << malloc_pageshift, j);
295 if (pd[j] == MALLOC_NOT_MINE) {
296 for(j++;j<=last_index && pd[j] == MALLOC_NOT_MINE;j++)
297 ;
298 j--;
299 fprintf(fd, ".. %5d not mine\n", j);
300 } else if (pd[j] == MALLOC_FREE) {
301 for(j++;j<=last_index && pd[j] == MALLOC_FREE;j++)
302 ;
303 j--;
304 fprintf(fd, ".. %5d free\n", j);
305 } else if (pd[j] == MALLOC_FIRST) {
306 for(j++;j<=last_index && pd[j] == MALLOC_FOLLOW;j++)
307 ;
308 j--;
309 fprintf(fd, ".. %5d in use\n", j);
310 } else if (pd[j] < MALLOC_MAGIC) {
311 fprintf(fd, "(%p)\n", pd[j]);
312 } else {
313 fprintf(fd, "%p %d (of %d) x %d @ %p --> %p\n",
314 pd[j], pd[j]->free, pd[j]->total,
315 pd[j]->size, pd[j]->page, pd[j]->next);
316 }
317 }
318
319 for(pf=free_list.next; pf; pf=pf->next) {
320 fprintf(fd, "Free: @%p [%p...%p[ %ld ->%p <-%p\n",
321 pf, pf->page, pf->end, pf->size, pf->prev, pf->next);
322 if (pf == pf->next) {
323 fprintf(fd, "Free_list loops.\n");
324 break;
325 }
326 }
327
328 /* print out various info */
329 fprintf(fd, "Minsize\t%d\n", malloc_minsize);
330 fprintf(fd, "Maxsize\t%d\n", malloc_maxsize);
331 fprintf(fd, "Pagesize\t%lu\n", (u_long)malloc_pagesize);
332 fprintf(fd, "Pageshift\t%d\n", malloc_pageshift);
333 fprintf(fd, "FirstPage\t%ld\n", malloc_origo);
334 fprintf(fd, "LastPage\t%ld %lx\n", last_index+malloc_pageshift,
335 (last_index + malloc_pageshift) << malloc_pageshift);
336 fprintf(fd, "Break\t%ld\n", (u_long)sbrk(0) >> malloc_pageshift);
337}
338#endif /* MALLOC_STATS */
339
340extern char *__progname;
341
342static void
343wrterror(p)
344 char *p;
345{
346 char *q = " error: ";
347 struct iovec iov[4];
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 suicide = 1;
360#ifdef MALLOC_STATS
361 if (malloc_stats)
362 malloc_dump(stderr);
363#endif /* MALLOC_STATS */
364 abort();
365}
366
367static void
368wrtwarning(p)
369 char *p;
370{
371 char *q = " warning: ";
372 struct iovec iov[4];
373
374 if (malloc_abort)
375 wrterror(p);
376 else if (malloc_silent)
377 return;
378
379 iov[0].iov_base = __progname;
380 iov[0].iov_len = strlen(__progname);
381 iov[1].iov_base = malloc_func;
382 iov[1].iov_len = strlen(malloc_func);
383 iov[2].iov_base = q;
384 iov[2].iov_len = strlen(q);
385 iov[3].iov_base = p;
386 iov[3].iov_len = strlen(p);
387 writev(STDERR_FILENO, iov, 4);
388}
389
390#ifdef MALLOC_STATS
391static void
392malloc_exit()
393{
394 FILE *fd = fopen("malloc.out", "a");
395 char *q = "malloc() warning: Couldn't dump stats.\n";
396 if (fd) {
397 malloc_dump(fd);
398 fclose(fd);
399 } else
400 write(2, q, strlen(q));
401}
402#endif /* MALLOC_STATS */
103 403
104static int pagesz; /* page size */
105static int pagebucket; /* page size bucket */
106 404
107#ifdef MSTATS
108/* 405/*
109 * nmalloc[i] is the difference between the number of mallocs and frees 406 * Allocate a number of pages from the OS
110 * for a given block size.
111 */ 407 */
112static u_int nmalloc[NBUCKETS]; 408static void *
113#include <stdio.h> 409map_pages(pages)
114#endif 410 int pages;
411{
412 caddr_t result, tail;
115 413
116#if defined(DEBUG) || defined(RCHECK) 414 result = (caddr_t)pageround((u_long)sbrk(0));
117#define ASSERT(p) if (!(p)) botch("p") 415 tail = result + (pages << malloc_pageshift);
118#include <stdio.h> 416
119static 417 if (brk(tail)) {
120botch(s) 418#ifdef MALLOC_EXTRA_SANITY
121 char *s; 419 wrterror("(ES): map_pages fails\n");
420#endif /* MALLOC_EXTRA_SANITY */
421 return 0;
422 }
423
424 last_index = ptr2index(tail) - 1;
425 malloc_brk = tail;
426
427 if ((last_index+1) >= malloc_ninfo && !extend_pgdir(last_index))
428 return 0;
429
430 return result;
431}
432
433/*
434 * Extend page directory
435 */
436static int
437extend_pgdir(index)
438 u_long index;
122{ 439{
123 fprintf(stderr, "\r\nassertion botched: %s\r\n", s); 440 struct pginfo **new, **old;
124 (void) fflush(stderr); /* just in case user buffered it */ 441 size_t i, oldlen;
125 abort(); 442
443 /* Make it this many pages */
444 i = index * sizeof *page_dir;
445 i /= malloc_pagesize;
446 i += 2;
447
448 /* remember the old mapping size */
449 oldlen = malloc_ninfo * sizeof *page_dir;
450
451 /*
452 * NOTE: we allocate new pages and copy the directory rather than tempt
453 * fate by trying to "grow" the region.. There is nothing to prevent
454 * us from accidently re-mapping space that's been allocated by our caller
455 * via dlopen() or other mmap().
456 *
457 * The copy problem is not too bad, as there is 4K of page index per
458 * 4MB of malloc arena.
459 *
460 * We can totally avoid the copy if we open a file descriptor to associate
461 * the anon mappings with. Then, when we remap the pages at the new
462 * address, the old pages will be "magically" remapped.. But this means
463 * keeping open a "secret" file descriptor.....
464 */
465
466 /* Get new pages */
467 new = (struct pginfo**) MMAP(i * malloc_pagesize);
468 if (new == MAP_FAILED)
469 return 0;
470
471 /* Copy the old stuff */
472 memcpy(new, page_dir,
473 malloc_ninfo * sizeof *page_dir);
474
475 /* register the new size */
476 malloc_ninfo = i * malloc_pagesize / sizeof *page_dir;
477
478 /* swap the pointers */
479 old = page_dir;
480 page_dir = new;
481
482 /* Now free the old stuff */
483 munmap(old, oldlen);
484 return 1;
126} 485}
127#else
128#define ASSERT(p)
129#endif
130 486
131void * 487/*
132malloc(nbytes) 488 * Initialize the world
133 size_t nbytes; 489 */
490static void
491malloc_init ()
134{ 492{
135 register union overhead *op; 493 char *p, b[64];
136 register long bucket, n; 494 int i, j;
137 register unsigned amt; 495 int save_errno = errno;
138 496
139 /* 497 THREAD_LOCK_INIT();
140 * First time malloc is called, setup page size and 498
141 * align break pointer so all data will be page aligned. 499 INIT_MMAP();
142 */ 500
143 if (pagesz == 0) { 501#ifdef MALLOC_EXTRA_SANITY
144 pagesz = n = getpagesize(); 502 malloc_junk = 1;
145 op = (union overhead *)sbrk(0); 503#endif /* MALLOC_EXTRA_SANITY */
146 n = n - sizeof (*op) - ((long)op & (n - 1)); 504
147 if (n < 0) 505 for (i = 0; i < 3; i++) {
148 n += pagesz; 506 if (i == 0) {
149 if (n) { 507 j = readlink("/etc/malloc.conf", b, sizeof b - 1);
150 if (sbrk(n) == (char *)-1) 508 if (j <= 0)
151 return (NULL); 509 continue;
152 } 510 b[j] = '\0';
153 bucket = 0; 511 p = b;
154 amt = 8; 512 } else if (i == 1) {
155 while (pagesz > amt) { 513 if (issetugid() == 0)
156 amt <<= 1; 514 p = getenv("MALLOC_OPTIONS");
157 bucket++; 515 else
158 } 516 continue;
159 pagebucket = bucket; 517 } else if (i == 2) {
160 } 518 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 } 519 }
179 while (nbytes > amt + n) { 520 for (; p && *p; p++) {
180 amt <<= 1; 521 switch (*p) {
181 if (amt == 0) 522 case '>': malloc_cache <<= 1; break;
182 return (NULL); 523 case '<': malloc_cache >>= 1; break;
183 bucket++; 524 case 'a': malloc_abort = 0; break;
525 case 'A': malloc_abort = 1; break;
526#ifdef MALLOC_STATS
527 case 'd': malloc_stats = 0; break;
528 case 'D': malloc_stats = 1; break;
529#endif /* MALLOC_STATS */
530#if defined(__FreeBSD__) || (defined(__OpenBSD__) && defined(MADV_FREE))
531 case 'h': malloc_hint = 0; break;
532 case 'H': malloc_hint = 1; break;
533#endif /* __FreeBSD__ */
534 case 'r': malloc_realloc = 0; break;
535 case 'R': malloc_realloc = 1; break;
536 case 'j': malloc_junk = 0; break;
537 case 'J': malloc_junk = 1; break;
538 case 'n': malloc_silent = 0; break;
539 case 'N': malloc_silent = 1; break;
540#ifdef __FreeBSD__
541 case 'u': malloc_utrace = 0; break;
542 case 'U': malloc_utrace = 1; break;
543#endif /* __FreeBSD__ */
544 case 'x': malloc_xmalloc = 0; break;
545 case 'X': malloc_xmalloc = 1; break;
546 case 'z': malloc_zero = 0; break;
547 case 'Z': malloc_zero = 1; break;
548 default:
549 j = malloc_abort;
550 malloc_abort = 0;
551 wrtwarning("unknown char in MALLOC_OPTIONS\n");
552 malloc_abort = j;
553 break;
554 }
184 } 555 }
185 /* 556 }
186 * If nothing in hash bucket right now, 557
187 * request more memory from the system. 558 UTRACE(0, 0, 0);
188 */ 559
189 if ((op = nextf[bucket]) == NULL) { 560 /*
190 morecore(bucket); 561 * We want junk in the entire allocation, and zero only in the part
191 if ((op = nextf[bucket]) == NULL) 562 * the user asked for.
192 return (NULL); 563 */
564 if (malloc_zero)
565 malloc_junk=1;
566
567#ifdef MALLOC_STATS
568 if (malloc_stats)
569 atexit(malloc_exit);
570#endif /* MALLOC_STATS */
571
572 /* Allocate one page for the page directory */
573 page_dir = (struct pginfo **) MMAP(malloc_pagesize);
574
575 if (page_dir == MAP_FAILED)
576 wrterror("mmap(2) failed, check limits.\n");
577
578 /*
579 * We need a maximum of malloc_pageshift buckets, steal these from the
580 * front of the page_directory;
581 */
582 malloc_origo = ((u_long)pageround((u_long)sbrk(0))) >> malloc_pageshift;
583 malloc_origo -= malloc_pageshift;
584
585 malloc_ninfo = malloc_pagesize / sizeof *page_dir;
586
587 /* Been here, done that */
588 malloc_started++;
589
590 /* Recalculate the cache size in bytes, and make sure it's nonzero */
591
592 if (!malloc_cache)
593 malloc_cache++;
594
595 malloc_cache <<= malloc_pageshift;
596
597 /*
598 * This is a nice hack from Kaleb Keithly (kaleb@x.org).
599 * We can sbrk(2) further back when we keep this on a low address.
600 */
601 px = (struct pgfree *) imalloc (sizeof *px);
602 errno = save_errno;
603}
604
605/*
606 * Allocate a number of complete pages
607 */
608static void *
609malloc_pages(size)
610 size_t size;
611{
612 void *p, *delay_free = 0;
613 int i;
614 struct pgfree *pf;
615 u_long index;
616
617 size = pageround(size);
618
619 p = 0;
620 /* Look for free pages before asking for more */
621 for(pf = free_list.next; pf; pf = pf->next) {
622
623#ifdef MALLOC_EXTRA_SANITY
624 if (pf->size & malloc_pagemask)
625 wrterror("(ES): junk length entry on free_list\n");
626 if (!pf->size)
627 wrterror("(ES): zero length entry on free_list\n");
628 if (pf->page == pf->end)
629 wrterror("(ES): zero entry on free_list\n");
630 if (pf->page > pf->end)
631 wrterror("(ES): sick entry on free_list\n");
632 if ((void*)pf->page >= (void*)sbrk(0))
633 wrterror("(ES): entry on free_list past brk\n");
634 if (page_dir[ptr2index(pf->page)] != MALLOC_FREE)
635 wrterror("(ES): non-free first page on free-list\n");
636 if (page_dir[ptr2index(pf->end)-1] != MALLOC_FREE)
637 wrterror("(ES): non-free last page on free-list\n");
638#endif /* MALLOC_EXTRA_SANITY */
639
640 if (pf->size < size)
641 continue;
642
643 if (pf->size == size) {
644 p = pf->page;
645 if (pf->next)
646 pf->next->prev = pf->prev;
647 pf->prev->next = pf->next;
648 delay_free = pf;
649 break;
193 } 650 }
194 /* remove from linked list */ 651
195 nextf[bucket] = op->ov_next; 652 p = pf->page;
196 op->ov_magic = MAGIC; 653 pf->page = (char *)pf->page + size;
197 op->ov_index = bucket; 654 pf->size -= size;
198#ifdef MSTATS 655 break;
199 nmalloc[bucket]++; 656 }
200#endif 657
201#ifdef RCHECK 658#ifdef MALLOC_EXTRA_SANITY
202 /* 659 if (p && page_dir[ptr2index(p)] != MALLOC_FREE)
203 * Record allocated size of block and 660 wrterror("(ES): allocated non-free page on free-list\n");
204 * bound space with magic numbers. 661#endif /* MALLOC_EXTRA_SANITY */
205 */ 662
206 op->ov_size = (nbytes + RSLOP - 1) & ~(RSLOP - 1); 663 size >>= malloc_pageshift;
207 op->ov_rmagic = RMAGIC; 664
208 *(u_short *)((caddr_t)(op + 1) + op->ov_size) = RMAGIC; 665 /* Map new pages */
209#endif 666 if (!p)
210 return ((char *)(op + 1)); 667 p = map_pages(size);
668
669 if (p) {
670
671 index = ptr2index(p);
672 page_dir[index] = MALLOC_FIRST;
673 for (i=1;i<size;i++)
674 page_dir[index+i] = MALLOC_FOLLOW;
675
676 if (malloc_junk)
677 memset(p, SOME_JUNK, size << malloc_pageshift);
678 }
679
680 if (delay_free) {
681 if (!px)
682 px = delay_free;
683 else
684 ifree(delay_free);
685 }
686
687 return p;
211} 688}
212 689
213/* 690/*
214 * Allocate more memory to the indicated bucket. 691 * Allocate a page of fragments
215 */ 692 */
216static void 693
217morecore(bucket) 694static __inline__ int
218 int bucket; 695malloc_make_chunks(bits)
696 int bits;
219{ 697{
220 register union overhead *op; 698 struct pginfo *bp;
221 register long sz; /* size of desired block */ 699 void *pp;
222 long amt; /* amount to allocate */ 700 int i, k, l;
223 int nblks; /* how many blocks we get */
224 701
225 /* 702 /* Allocate a new bucket */
226 * sbrk_size <= 0 only for big, FLUFFY, requests (about 703 pp = malloc_pages((size_t)malloc_pagesize);
227 * 2^30 bytes on a VAX, I think) or for a negative arg. 704 if (!pp)
228 */ 705 return 0;
229 sz = 1 << (bucket + 3); 706
230#ifdef DEBUG 707 /* Find length of admin structure */
231 ASSERT(sz > 0); 708 l = sizeof *bp - sizeof(u_long);
232#else 709 l += sizeof(u_long) *
233 if (sz <= 0) 710 (((malloc_pagesize >> bits)+MALLOC_BITS-1) / MALLOC_BITS);
234 return; 711
235#endif 712 /* Don't waste more than two chunks on this */
236 if (sz < pagesz) { 713 /*
237 amt = pagesz; 714 * If we are to allocate a memory protected page for the malloc(0)
238 nblks = amt / sz; 715 * case (when bits=0), it must be from a different page than the
239 } else { 716 * pginfo page.
240 amt = sz + pagesz; 717 * --> Treat it like the big chunk alloc, get a second data page.
241 nblks = 1; 718 */
719 if (bits != 0 && (1UL<<(bits)) <= l+l) {
720 bp = (struct pginfo *)pp;
721 } else {
722 bp = (struct pginfo *)imalloc(l);
723 if (!bp) {
724 ifree(pp);
725 return 0;
242 } 726 }
243 op = (union overhead *)sbrk(amt); 727 }
244 /* no more room! */ 728
245 if ((long)op == -1) 729 /* memory protect the page allocated in the malloc(0) case */
246 return; 730 if (bits == 0) {
247 /* 731
248 * Add new memory allocated to that on 732 bp->size = 0;
249 * free list for this hash bucket. 733 bp->shift = 1;
250 */ 734 i = malloc_minsize-1;
251 nextf[bucket] = op; 735 while (i >>= 1)
252 while (--nblks > 0) { 736 bp->shift++;
253 op->ov_next = (union overhead *)((caddr_t)op + sz); 737 bp->total = bp->free = malloc_pagesize >> bp->shift;
254 op = (union overhead *)((caddr_t)op + sz); 738 bp->page = pp;
255 } 739
740 k = mprotect(pp, malloc_pagesize, PROT_NONE);
741 if (k < 0) {
742 ifree(pp);
743 ifree(bp);
744 return 0;
745 }
746 } else {
747 bp->size = (1UL<<bits);
748 bp->shift = bits;
749 bp->total = bp->free = malloc_pagesize >> bits;
750 bp->page = pp;
751 }
752
753 /* set all valid bits in the bitmap */
754 k = bp->total;
755 i = 0;
756
757 /* Do a bunch at a time */
758 for(;k-i >= MALLOC_BITS; i += MALLOC_BITS)
759 bp->bits[i / MALLOC_BITS] = ~0UL;
760
761 for(; i < k; i++)
762 bp->bits[i/MALLOC_BITS] |= 1UL<<(i%MALLOC_BITS);
763
764 if (bp == bp->page) {
765 /* Mark the ones we stole for ourselves */
766 for(i=0;l > 0;i++) {
767 bp->bits[i/MALLOC_BITS] &= ~(1UL<<(i%MALLOC_BITS));
768 bp->free--;
769 bp->total--;
770 l -= (1 << bits);
771 }
772 }
773
774 /* MALLOC_LOCK */
775
776 page_dir[ptr2index(pp)] = bp;
777
778 bp->next = page_dir[bits];
779 page_dir[bits] = bp;
780
781 /* MALLOC_UNLOCK */
782
783 return 1;
256} 784}
257 785
258void 786/*
259free(cp) 787 * Allocate a fragment
260 void *cp; 788 */
261{ 789static void *
262 register long size; 790malloc_bytes(size)
263 register union overhead *op; 791 size_t size;
264 792{
265 if (cp == NULL) 793 int i,j;
266 return; 794 u_long u;
267 op = (union overhead *)((caddr_t)cp - sizeof (union overhead)); 795 struct pginfo *bp;
268#ifdef DEBUG 796 int k;
269 ASSERT(op->ov_magic == MAGIC); /* make sure it was in use */ 797 u_long *lp;
270#else 798
271 if (op->ov_magic != MAGIC) 799 /* Don't bother with anything less than this */
272 return; /* sanity */ 800 /* unless we have a malloc(0) requests */
273#endif 801 if (size != 0 && size < malloc_minsize)
274#ifdef RCHECK 802 size = malloc_minsize;
275 ASSERT(op->ov_rmagic == RMAGIC); 803
276 ASSERT(*(u_short *)((caddr_t)(op + 1) + op->ov_size) == RMAGIC); 804 /* Find the right bucket */
277#endif 805 if (size == 0)
278 size = op->ov_index; 806 j=0;
279 ASSERT(size < NBUCKETS); 807 else {
280 op->ov_next = nextf[size]; /* also clobbers ov_magic */ 808 j = 1;
281 nextf[size] = op; 809 i = size-1;
282#ifdef MSTATS 810 while (i >>= 1)
283 nmalloc[size]--; 811 j++;
284#endif 812 }
813
814 /* If it's empty, make a page more of that size chunks */
815 if (!page_dir[j] && !malloc_make_chunks(j))
816 return 0;
817
818 bp = page_dir[j];
819
820 /* Find first word of bitmap which isn't empty */
821 for (lp = bp->bits; !*lp; lp++)
822 ;
823
824 /* Find that bit, and tweak it */
825 u = 1;
826 k = 0;
827 while (!(*lp & u)) {
828 u += u;
829 k++;
830 }
831 *lp ^= u;
832
833 /* If there are no more free, remove from free-list */
834 if (!--bp->free) {
835 page_dir[j] = bp->next;
836 bp->next = 0;
837 }
838
839 /* Adjust to the real offset of that chunk */
840 k += (lp-bp->bits)*MALLOC_BITS;
841 k <<= bp->shift;
842
843 if (malloc_junk && bp->size != 0)
844 memset((char *)bp->page + k, SOME_JUNK, bp->size);
845
846 return (u_char *)bp->page + k;
285} 847}
286 848
287/* 849/*
288 * When a program attempts "storage compaction" as mentioned in the 850 * 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 */ 851 */
298int realloc_srchlen = 4; /* 4 should be plenty, -1 =>'s whole list */ 852static void *
853imalloc(size)
854 size_t size;
855{
856 void *result;
299 857
300void * 858 if (!malloc_started)
301realloc(cp, nbytes) 859 malloc_init();
302 void *cp; 860
303 size_t nbytes; 861 if (suicide)
304{ 862 abort();
305 register u_long onb; 863
306 register long i; 864 if ((size + malloc_pagesize) < size) /* Check for overflow */
307 union overhead *op; 865 result = 0;
308 char *res; 866 else if (size <= malloc_maxsize)
309 int was_alloced = 0; 867 result = malloc_bytes(size);
310 868 else
311 if (cp == NULL) 869 result = malloc_pages(size);
312 return (malloc(nbytes)); 870
313 op = (union overhead *)((caddr_t)cp - sizeof (union overhead)); 871 if (malloc_abort && !result)
314 if (op->ov_magic == MAGIC) { 872 wrterror("allocation failed.\n");
315 was_alloced++; 873
316 i = op->ov_index; 874 if (malloc_zero && result)
317 } else { 875 memset(result, 0, size);
318 /* 876
319 * Already free, doing "compaction". 877 return result;
320 * 878}
321 * Search for the old block of memory on the 879
322 * free list. First, check the most common 880/*
323 * case (last element free'd), then (this failing) 881 * Change the size of an allocation.
324 * the last ``realloc_srchlen'' items free'd. 882 */
325 * If all lookups fail, then assume the size of 883static void *
326 * the memory block being realloc'd is the 884irealloc(ptr, size)
327 * largest possible (so that all "nbytes" of new 885 void *ptr;
328 * memory are copied into). Note that this could cause 886 size_t size;
329 * a memory fault if the old area was tiny, and the moon 887{
330 * is gibbous. However, that is very unlikely. 888 void *p;
331 */ 889 u_long osize, index;
332 if ((i = findbucket(op, 1)) < 0 && 890 struct pginfo **mp;
333 (i = findbucket(op, realloc_srchlen)) < 0) 891 int i;
334 i = NBUCKETS; 892
893 if (suicide)
894 abort();
895
896 if (!malloc_started) {
897 wrtwarning("malloc() has never been called.\n");
898 return 0;
899 }
900
901 index = ptr2index(ptr);
902
903 if (index < malloc_pageshift) {
904 wrtwarning("junk pointer, too low to make sense.\n");
905 return 0;
906 }
907
908 if (index > last_index) {
909 wrtwarning("junk pointer, too high to make sense.\n");
910 return 0;
911 }
912
913 mp = &page_dir[index];
914
915 if (*mp == MALLOC_FIRST) { /* Page allocation */
916
917 /* Check the pointer */
918 if ((u_long)ptr & malloc_pagemask) {
919 wrtwarning("modified (page-) pointer.\n");
920 return 0;
335 } 921 }
336 onb = 1 << (i + 3); 922
337 if (onb < pagesz) 923 /* Find the size in bytes */
338 onb -= sizeof (*op) + RSLOP; 924 for (osize = malloc_pagesize; *++mp == MALLOC_FOLLOW;)
339 else 925 osize += malloc_pagesize;
340 onb += pagesz - sizeof (*op) - RSLOP; 926
341 /* avoid the copy if same size block */ 927 if (!malloc_realloc && /* unless we have to, */
342 if (was_alloced) { 928 size <= osize && /* .. or are too small, */
343 if (i) { 929 size > (osize - malloc_pagesize)) { /* .. or can free a page, */
344 i = 1 << (i + 2); 930 return ptr; /* don't do anything. */
345 if (i < pagesz) 931 }
346 i -= sizeof (*op) + RSLOP; 932
347 else 933 } else if (*mp >= MALLOC_MAGIC) { /* Chunk allocation */
348 i += pagesz - sizeof (*op) - RSLOP; 934
349 } 935 /* Check the pointer for sane values */
350 if (nbytes <= onb && nbytes > i) { 936 if ((u_long)ptr & ((1UL<<((*mp)->shift))-1)) {
351#ifdef RCHECK 937 wrtwarning("modified (chunk-) pointer.\n");
352 op->ov_size = (nbytes + RSLOP - 1) & ~(RSLOP - 1); 938 return 0;
353 *(u_short *)((caddr_t)(op + 1) + op->ov_size) = RMAGIC; 939 }
354#endif 940
355 return(cp); 941 /* Find the chunk index in the page */
356 } else 942 i = ((u_long)ptr & malloc_pagemask) >> (*mp)->shift;
357 free(cp); 943
944 /* Verify that it isn't a free chunk already */
945 if ((*mp)->bits[i/MALLOC_BITS] & (1UL<<(i%MALLOC_BITS))) {
946 wrtwarning("chunk is already free.\n");
947 return 0;
358 } 948 }
359 if ((res = malloc(nbytes)) == NULL) 949
360 return (NULL); 950 osize = (*mp)->size;
361 if (cp != res) /* common optimization if "compacting" */ 951
362 bcopy(cp, res, (nbytes < onb) ? nbytes : onb); 952 if (!malloc_realloc && /* Unless we have to, */
363 return (res); 953 size < osize && /* ..or are too small, */
954 (size > osize/2 || /* ..or could use a smaller size, */
955 osize == malloc_minsize)) { /* ..(if there is one) */
956 return ptr; /* ..Don't do anything */
957 }
958
959 } else {
960 wrtwarning("pointer to wrong page.\n");
961 return 0;
962 }
963
964 p = imalloc(size);
965
966 if (p) {
967 /* copy the lesser of the two sizes, and free the old one */
968 /* Don't move from/to 0 sized region !!! */
969 if (osize != 0 && size != 0) {
970 if (osize < size)
971 memcpy(p, ptr, osize);
972 else
973 memcpy(p, ptr, size);
974 }
975 ifree(ptr);
976 }
977 return p;
364} 978}
365 979
366/* 980/*
367 * Search ``srchlen'' elements of each free list for a block whose 981 * 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 */ 982 */
371static 983
372findbucket(freep, srchlen) 984static __inline__ void
373 union overhead *freep; 985free_pages(ptr, index, info)
374 int srchlen; 986 void *ptr;
987 int index;
988 struct pginfo *info;
375{ 989{
376 register union overhead *p; 990 int i;
377 register int i, j; 991 struct pgfree *pf, *pt=0;
378 992 u_long l;
379 for (i = 0; i < NBUCKETS; i++) { 993 void *tail;
380 j = 0; 994
381 for (p = nextf[i]; p && j != srchlen; p = p->ov_next) { 995 if (info == MALLOC_FREE) {
382 if (p == freep) 996 wrtwarning("page is already free.\n");
383 return (i); 997 return;
384 j++; 998 }
385 } 999
1000 if (info != MALLOC_FIRST) {
1001 wrtwarning("pointer to wrong page.\n");
1002 return;
1003 }
1004
1005 if ((u_long)ptr & malloc_pagemask) {
1006 wrtwarning("modified (page-) pointer.\n");
1007 return;
1008 }
1009
1010 /* Count how many pages and mark them free at the same time */
1011 page_dir[index] = MALLOC_FREE;
1012 for (i = 1; page_dir[index+i] == MALLOC_FOLLOW; i++)
1013 page_dir[index + i] = MALLOC_FREE;
1014
1015 l = i << malloc_pageshift;
1016
1017 if (malloc_junk)
1018 memset(ptr, SOME_JUNK, l);
1019
1020#if defined(__FreeBSD__) || (defined(__OpenBSD__) && defined(MADV_FREE))
1021 if (malloc_hint)
1022 madvise(ptr, l, MADV_FREE);
1023#endif
1024
1025 tail = (char *)ptr+l;
1026
1027 /* add to free-list */
1028 if (!px)
1029 px = imalloc(sizeof *px); /* This cannot fail... */
1030 px->page = ptr;
1031 px->end = tail;
1032 px->size = l;
1033 if (!free_list.next) {
1034
1035 /* Nothing on free list, put this at head */
1036 px->next = free_list.next;
1037 px->prev = &free_list;
1038 free_list.next = px;
1039 pf = px;
1040 px = 0;
1041
1042 } else {
1043
1044 /* Find the right spot, leave pf pointing to the modified entry. */
1045 tail = (char *)ptr+l;
1046
1047 for(pf = free_list.next; pf->end < ptr && pf->next; pf = pf->next)
1048 ; /* Race ahead here */
1049
1050 if (pf->page > tail) {
1051 /* Insert before entry */
1052 px->next = pf;
1053 px->prev = pf->prev;
1054 pf->prev = px;
1055 px->prev->next = px;
1056 pf = px;
1057 px = 0;
1058 } else if (pf->end == ptr ) {
1059 /* Append to the previous entry */
1060 pf->end = (char *)pf->end + l;
1061 pf->size += l;
1062 if (pf->next && pf->end == pf->next->page ) {
1063 /* And collapse the next too. */
1064 pt = pf->next;
1065 pf->end = pt->end;
1066 pf->size += pt->size;
1067 pf->next = pt->next;
1068 if (pf->next)
1069 pf->next->prev = pf;
1070 }
1071 } else if (pf->page == tail) {
1072 /* Prepend to entry */
1073 pf->size += l;
1074 pf->page = ptr;
1075 } else if (!pf->next) {
1076 /* Append at tail of chain */
1077 px->next = 0;
1078 px->prev = pf;
1079 pf->next = px;
1080 pf = px;
1081 px = 0;
1082 } else {
1083 wrterror("freelist is destroyed.\n");
386 } 1084 }
387 return (-1); 1085 }
1086
1087 /* Return something to OS ? */
1088 if (!pf->next && /* If we're the last one, */
1089 pf->size > malloc_cache && /* ..and the cache is full, */
1090 pf->end == malloc_brk && /* ..and none behind us, */
1091 malloc_brk == sbrk(0)) { /* ..and it's OK to do... */
1092
1093 /*
1094 * Keep the cache intact. Notice that the '>' above guarantees that
1095 * the pf will always have at least one page afterwards.
1096 */
1097 pf->end = (char *)pf->page + malloc_cache;
1098 pf->size = malloc_cache;
1099
1100 brk(pf->end);
1101 malloc_brk = pf->end;
1102
1103 index = ptr2index(pf->end);
1104 last_index = index - 1;
1105
1106 for(i=index;i <= last_index;)
1107 page_dir[i++] = MALLOC_NOT_MINE;
1108
1109 /* XXX: We could realloc/shrink the pagedir here I guess. */
1110 }
1111 if (pt)
1112 ifree(pt);
388} 1113}
389 1114
390#ifdef MSTATS
391/* 1115/*
392 * mstats - print out statistics about malloc 1116 * 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 */ 1117 */
398mstats(s) 1118
399 char *s; 1119/* ARGSUSED */
1120static __inline__ void
1121free_bytes(ptr, index, info)
1122 void *ptr;
1123 int index;
1124 struct pginfo *info;
400{ 1125{
401 register int i, j; 1126 int i;
402 register union overhead *p; 1127 struct pginfo **mp;
403 int totfree = 0, 1128 void *vp;
404 totused = 0; 1129
405 1130 /* Find the chunk number on the page */
406 fprintf(stderr, "Memory allocation statistics %s\nfree:\t", s); 1131 i = ((u_long)ptr & malloc_pagemask) >> info->shift;
407 for (i = 0; i < NBUCKETS; i++) { 1132
408 for (j = 0, p = nextf[i]; p; p = p->ov_next, j++) 1133 if ((u_long)ptr & ((1UL<<(info->shift))-1)) {
409 ; 1134 wrtwarning("modified (chunk-) pointer.\n");
410 fprintf(stderr, " %d", j); 1135 return;
411 totfree += j * (1 << (i + 3)); 1136 }
412 } 1137
413 fprintf(stderr, "\nused:\t"); 1138 if (info->bits[i/MALLOC_BITS] & (1UL<<(i%MALLOC_BITS))) {
414 for (i = 0; i < NBUCKETS; i++) { 1139 wrtwarning("chunk is already free.\n");
415 fprintf(stderr, " %d", nmalloc[i]); 1140 return;
416 totused += nmalloc[i] * (1 << (i + 3)); 1141 }
417 } 1142
418 fprintf(stderr, "\n\tTotal in use: %d, total free: %d\n", 1143 if (malloc_junk && info->size != 0)
419 totused, totfree); 1144 memset(ptr, SOME_JUNK, info->size);
1145
1146 info->bits[i/MALLOC_BITS] |= 1UL<<(i%MALLOC_BITS);
1147 info->free++;
1148
1149 if (info->size != 0)
1150 mp = page_dir + info->shift;
1151 else
1152 mp = page_dir;
1153
1154 if (info->free == 1) {
1155
1156 /* Page became non-full */
1157
1158 /* Insert in address order */
1159 while (*mp && (*mp)->next && (*mp)->next->page < info->page)
1160 mp = &(*mp)->next;
1161 info->next = *mp;
1162 *mp = info;
1163 return;
1164 }
1165
1166 if (info->free != info->total)
1167 return;
1168
1169 /* Find & remove this page in the queue */
1170 while (*mp != info) {
1171 mp = &((*mp)->next);
1172#ifdef MALLOC_EXTRA_SANITY
1173 if (!*mp)
1174 wrterror("(ES): Not on queue\n");
1175#endif /* MALLOC_EXTRA_SANITY */
1176 }
1177 *mp = info->next;
1178
1179 /* Free the page & the info structure if need be */
1180 page_dir[ptr2index(info->page)] = MALLOC_FIRST;
1181
1182 /* If the page was mprotected, unprotect it before releasing it */
1183 if (info->size == 0) {
1184 mprotect(info->page, malloc_pagesize, PROT_READ|PROT_WRITE);
1185 /* Do we have to care if mprotect succeeds here ? */
1186 }
1187
1188 vp = info->page; /* Order is important ! */
1189 if(vp != (void*)info)
1190 ifree(info);
1191 ifree(vp);
1192}
1193
1194static void
1195ifree(ptr)
1196 void *ptr;
1197{
1198 struct pginfo *info;
1199 int index;
1200
1201 /* This is legal */
1202 if (!ptr)
1203 return;
1204
1205 if (!malloc_started) {
1206 wrtwarning("malloc() has never been called.\n");
1207 return;
1208 }
1209
1210 /* If we're already sinking, don't make matters any worse. */
1211 if (suicide)
1212 return;
1213
1214 index = ptr2index(ptr);
1215
1216 if (index < malloc_pageshift) {
1217 wrtwarning("junk pointer, too low to make sense.\n");
1218 return;
1219 }
1220
1221 if (index > last_index) {
1222 wrtwarning("junk pointer, too high to make sense.\n");
1223 return;
1224 }
1225
1226 info = page_dir[index];
1227
1228 if (info < MALLOC_MAGIC)
1229 free_pages(ptr, index, info);
1230 else
1231 free_bytes(ptr, index, info);
1232 return;
1233}
1234
1235/*
1236 * These are the public exported interface routines.
1237 */
1238
1239static int malloc_active;
1240
1241void *
1242malloc(size_t size)
1243{
1244 register void *r;
1245
1246 malloc_func = " in malloc():";
1247 THREAD_LOCK();
1248 if (malloc_active++) {
1249 wrtwarning("recursive call.\n");
1250 malloc_active--;
1251 THREAD_UNLOCK();
1252 return (0);
1253 }
1254 r = imalloc(size);
1255 UTRACE(0, size, r);
1256 malloc_active--;
1257 THREAD_UNLOCK();
1258 if (malloc_xmalloc && !r)
1259 wrterror("out of memory.\n");
1260 return (r);
1261}
1262
1263void
1264free(void *ptr)
1265{
1266 malloc_func = " in free():";
1267 THREAD_LOCK();
1268 if (malloc_active++) {
1269 wrtwarning("recursive call.\n");
1270 malloc_active--;
1271 THREAD_UNLOCK();
1272 return;
1273 }
1274 ifree(ptr);
1275 UTRACE(ptr, 0, 0);
1276 malloc_active--;
1277 THREAD_UNLOCK();
1278 return;
1279}
1280
1281void *
1282realloc(void *ptr, size_t size)
1283{
1284 register void *r;
1285
1286 malloc_func = " in realloc():";
1287 THREAD_LOCK();
1288 if (malloc_active++) {
1289 wrtwarning("recursive call.\n");
1290 malloc_active--;
1291 THREAD_UNLOCK();
1292 return (0);
1293 }
1294 if (!ptr) {
1295 r = imalloc(size);
1296 } else {
1297 r = irealloc(ptr, size);
1298 }
1299 UTRACE(ptr, size, r);
1300 malloc_active--;
1301 THREAD_UNLOCK();
1302 if (malloc_xmalloc && !r)
1303 wrterror("out of memory.\n");
1304 return (r);
420} 1305}
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..6c4eba46bf 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.9 2002/02/23 19:51:46 miod 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.
@@ -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..31a4fdf4dd 100644
--- a/src/lib/libc/stdlib/rand48.3
+++ b/src/lib/libc/stdlib/rand48.3
@@ -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.8 2001/08/06 10:42:26 mpech Exp $
13.\" 13.\"
14.Dd October 8, 1993 14.Dd October 8, 1993
15.Dt RAND48 3 15.Dt RAND48 3
@@ -27,7 +27,7 @@
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,7 +64,8 @@ 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
@@ -71,7 +73,8 @@ such that the values produced lie in the interval [0.0, 1.0).
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
@@ -153,8 +157,9 @@ generator 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..3d4545651b 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.14 2001/09/06 15:04:34 mpech 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
68.Fn srandom
69functions have (almost) the same calling sequence and initialization
70properties as
70.Xr rand 3 Ns / Xr srand 3 . 71.Xr rand 3 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 initialize 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..5ce7c90ee9 100644
--- a/src/lib/libc/stdlib/random.c
+++ b/src/lib/libc/stdlib/random.c
@@ -32,12 +32,15 @@
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.9 2000/04/04 14:27:00 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/types.h>
39#include <sys/time.h>
40#include <fcntl.h>
39#include <stdio.h> 41#include <stdio.h>
40#include <stdlib.h> 42#include <stdlib.h>
43#include <unistd.h>
41 44
42/* 45/*
43 * random.c: 46 * random.c:
@@ -136,12 +139,12 @@ static int seps [MAX_TYPES] = { SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 };
136 139
137static long randtbl[DEG_3 + 1] = { 140static long randtbl[DEG_3 + 1] = {
138 TYPE_3, 141 TYPE_3,
139 0x9a319039, 0x32d9c024, 0x9b663182, 0x5da1f342, 0xde3b81e0, 0xdf0a6fb5, 142 0x991539b1, 0x16a5bce3, 0x6774a4cd, 0x3e01511e, 0x4e508aaa, 0x61048c05,
140 0xf103bc02, 0x48f340fb, 0x7449e56b, 0xbeb1dbb0, 0xab5c5918, 0x946554fd, 143 0xf5500617, 0x846b7115, 0x6a19892c, 0x896a97af, 0xdb48f936, 0x14898454,
141 0x8c2e680f, 0xeb3d799f, 0xb11ee0b7, 0x2d436b86, 0xda672e2a, 0x1588ca88, 144 0x37ffd106, 0xb58bff9c, 0x59e17104, 0xcf918a49, 0x09378c83, 0x52c7a471,
142 0xe369735d, 0x904f35f7, 0xd7158fd6, 0x6fa6f051, 0x616e6b96, 0xac94efdc, 145 0x8d293ea9, 0x1f4fc301, 0xc3db71be, 0x39b44e1c, 0xf8a44ef9, 0x4c8b80b1,
143 0x36413f93, 0xc622c298, 0xf5a42ab8, 0x8a88d77b, 0xf5ad9d0e, 0x8999220b, 146 0x19edc328, 0x87bf4bdd, 0xc9b240e5, 0xe9ee4b1b, 0x4382aee7, 0x535b6b41,
144 0x27fb47b9, 147 0xf3bec5da,
145}; 148};
146 149
147/* 150/*
@@ -193,15 +196,26 @@ void
193srandom(x) 196srandom(x)
194 u_int x; 197 u_int x;
195{ 198{
196 register int i, j; 199 register long int test;
200 register int i;
201 ldiv_t val;
197 202
198 if (rand_type == TYPE_0) 203 if (rand_type == TYPE_0)
199 state[0] = x; 204 state[0] = x;
200 else { 205 else {
201 j = 1;
202 state[0] = x; 206 state[0] = x;
203 for (i = 1; i < rand_deg; i++) 207 for (i = 1; i < rand_deg; i++) {
204 state[i] = 1103515245 * state[i - 1] + 12345; 208 /*
209 * Implement the following, without overflowing 31 bits:
210 *
211 * state[i] = (16807 * state[i - 1]) % 2147483647;
212 *
213 * 2^31-1 (prime) = 2147483647 = 127773*16807+2836
214 */
215 val = ldiv(state[i-1], 127773);
216 test = 16807 * val.rem - 2836 * val.quot;
217 state[i] = test + (test < 0 ? 2147483647 : 0);
218 }
205 fptr = &state[rand_sep]; 219 fptr = &state[rand_sep];
206 rptr = &state[0]; 220 rptr = &state[0];
207 for (i = 0; i < 10 * rand_deg; i++) 221 for (i = 0; i < 10 * rand_deg; i++)
@@ -210,6 +224,49 @@ srandom(x)
210} 224}
211 225
212/* 226/*
227 * srandomdev:
228 *
229 * Many programs choose the seed value in a totally predictable manner.
230 * This often causes problems. We seed the generator using the much more
231 * secure arandom(4) interface. Note that this particular seeding
232 * procedure can generate states which are impossible to reproduce by
233 * calling srandom() with any value, since the succeeding terms in the
234 * state buffer are no longer derived from the LC algorithm applied to
235 * a fixed seed.
236 */
237void
238srandomdev()
239{
240 int fd;
241 size_t len;
242
243 if (rand_type == TYPE_0)
244 len = sizeof(state[0]);
245 else
246 len = rand_deg * sizeof(state[0]);
247
248 if ((fd = open("/dev/arandom", O_RDONLY, 0)) != -1 &&
249 read(fd, (void *) state, len) == (ssize_t) len) {
250 close(fd);
251 } else {
252 struct timeval tv;
253 u_int junk;
254
255 /* XXX - this could be better */
256 gettimeofday(&tv, NULL);
257 srandom(getpid() ^ tv.tv_sec ^ tv.tv_usec ^ junk);
258 if (fd != -1)
259 close(fd);
260 return;
261 }
262
263 if (rand_type != TYPE_0) {
264 fptr = &state[rand_sep];
265 rptr = &state[0];
266 }
267}
268
269/*
213 * initstate: 270 * initstate:
214 * 271 *
215 * Initialize the state information in the given array of n bytes for future 272 * Initialize the state information in the given array of n bytes for future
@@ -232,7 +289,7 @@ char *
232initstate(seed, arg_state, n) 289initstate(seed, arg_state, n)
233 u_int seed; /* seed for R.N.G. */ 290 u_int seed; /* seed for R.N.G. */
234 char *arg_state; /* pointer to state array */ 291 char *arg_state; /* pointer to state array */
235 int n; /* # bytes of state info */ 292 size_t n; /* # bytes of state info */
236{ 293{
237 register char *ostate = (char *)(&state[-1]); 294 register char *ostate = (char *)(&state[-1]);
238 295
@@ -240,11 +297,8 @@ initstate(seed, arg_state, n)
240 state[-1] = rand_type; 297 state[-1] = rand_type;
241 else 298 else
242 state[-1] = MAX_TYPES * (rptr - state) + rand_type; 299 state[-1] = MAX_TYPES * (rptr - state) + rand_type;
243 if (n < BREAK_0) { 300 if (n < BREAK_0)
244 (void)fprintf(stderr, 301 return(NULL);
245 "random: not enough state (%d bytes); ignored.\n", n);
246 return(0);
247 }
248 if (n < BREAK_1) { 302 if (n < BREAK_1) {
249 rand_type = TYPE_0; 303 rand_type = TYPE_0;
250 rand_deg = DEG_0; 304 rand_deg = DEG_0;
@@ -293,7 +347,7 @@ initstate(seed, arg_state, n)
293 */ 347 */
294char * 348char *
295setstate(arg_state) 349setstate(arg_state)
296 char *arg_state; 350 const char *arg_state;
297{ 351{
298 register long *new_state = (long *)arg_state; 352 register long *new_state = (long *)arg_state;
299 register int type = new_state[0] % MAX_TYPES; 353 register int type = new_state[0] % MAX_TYPES;
@@ -315,8 +369,7 @@ setstate(arg_state)
315 rand_sep = seps[type]; 369 rand_sep = seps[type];
316 break; 370 break;
317 default: 371 default:
318 (void)fprintf(stderr, 372 return(NULL);
319 "random: state info corrupted; not changed.\n");
320 } 373 }
321 state = &new_state[1]; 374 state = &new_state[1];
322 if (rand_type != TYPE_0) { 375 if (rand_type != TYPE_0) {
diff --git a/src/lib/libc/stdlib/realloc.3 b/src/lib/libc/stdlib/realloc.3
deleted file mode 100644
index 66f09b2081..0000000000
--- a/src/lib/libc/stdlib/realloc.3
+++ /dev/null
@@ -1,100 +0,0 @@
1.\" Copyright (c) 1991 The Regents of the University of California.
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. All advertising materials mentioning features or use of this software
13.\" must display the following acknowledgement:
14.\" This product includes software developed by the University of
15.\" California, Berkeley and its contributors.
16.\" 4. Neither the name of the University 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 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.\" from: @(#)realloc.3 5.1 (Berkeley) 5/2/91
33.\" $Id: realloc.3,v 1.1.1.1 1995/10/18 08:42:19 deraadt Exp $
34.\"
35.Dd May 2, 1991
36.Dt REALLOC 3
37.Os
38.Sh NAME
39.Nm realloc
40.Nd reallocation of memory function
41.Sh SYNOPSIS
42.Fd #include <stdlib.h>
43.Ft void *
44.Fn realloc "void *ptr" "size_t size"
45.Sh DESCRIPTION
46The
47.Fn realloc
48function changes the size of the object pointed to by
49.Fa ptr
50to the size specified by
51.Fa size .
52The contents of the object are unchanged up to the lesser
53of the new and old sizes.
54If the new size is larger, the value of the newly allocated portion
55of the object is indeterminate.
56If
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
87The
88.Fn realloc
89function returns either a null pointer or a pointer
90to the possibly moved allocated space.
91.Sh SEE ALSO
92.Xr alloca 3 ,
93.Xr calloc 3 ,
94.Xr free 3 ,
95.Xr malloc 3 ,
96.Sh STANDARDS
97The
98.Fn realloc
99function conforms to
100.St -ansiC .
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..d01b19e0f2 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.7 2002/05/24 21:22:37 deraadt 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
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..fc7c67a5db 100644
--- a/src/lib/libc/stdlib/setenv.c
+++ b/src/lib/libc/stdlib/setenv.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: @(#)setenv.c 5.6 (Berkeley) 6/4/91";*/ 35static char *rcsid = "$OpenBSD: setenv.c,v 1.4 2001/07/09 06:57:45 deraadt 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>
@@ -63,7 +62,8 @@ setenv(name, value, rewrite)
63 if (!rewrite) 62 if (!rewrite)
64 return (0); 63 return (0);
65 if (strlen(C) >= l_value) { /* old larger; copy over */ 64 if (strlen(C) >= l_value) { /* old larger; copy over */
66 while (*C++ = *value++); 65 while ((*C++ = *value++))
66 ;
67 return (0); 67 return (0);
68 } 68 }
69 } else { /* create new slot */ 69 } else { /* create new slot */
@@ -72,10 +72,11 @@ setenv(name, value, rewrite)
72 72
73 for (P = environ, cnt = 0; *P; ++P, ++cnt); 73 for (P = environ, cnt = 0; *P; ++P, ++cnt);
74 if (alloced) { /* just increase size */ 74 if (alloced) { /* just increase size */
75 environ = (char **)realloc((char *)environ, 75 P = (char **)realloc((void *)environ,
76 (size_t)(sizeof(char *) * (cnt + 2))); 76 (size_t)(sizeof(char *) * (cnt + 2)));
77 if (!environ) 77 if (!P)
78 return (-1); 78 return (-1);
79 environ = P;
79 } 80 }
80 else { /* get new space */ 81 else { /* get new space */
81 alloced = 1; /* copy old entries into it */ 82 alloced = 1; /* copy old entries into it */
@@ -95,7 +96,7 @@ setenv(name, value, rewrite)
95 return (-1); 96 return (-1);
96 for (C = environ[offset]; (*C = *name++) && *C != '='; ++C) 97 for (C = environ[offset]; (*C = *name++) && *C != '='; ++C)
97 ; 98 ;
98 for (*C++ = '='; *C++ = *value++; ) 99 for (*C++ = '='; (*C++ = *value++); )
99 ; 100 ;
100 return (0); 101 return (0);
101} 102}
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..ce7ce9fe56 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.15 2002/02/19 19:39:37 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;
@@ -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..a5bdff0b81 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.10 2002/06/29 00:20:11 millert 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,13 @@ 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 sscanf 3 ,
160.Xr strtod 3 , 235.Xr strtod 3 ,
161.Xr strtoul 3 236.Xr strtoul 3
162.Sh STANDARDS 237.Sh STANDARDS
163The 238The
164.Fn strtol 239.Fn strtol
165function 240function conforms to
166conforms to
167.St -ansiC . 241.St -ansiC .
168.Sh BUGS 242.Sh BUGS
169Ignores the current locale. 243Ignores 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..6d55de4d7a 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.10 2002/06/29 00:20:11 millert 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,29 @@
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.
77.Pp 86.Pp
78The string may begin with an arbitrary amount of white space 87The string may begin with an arbitrary amount of whitespace
79(as determined by 88(as determined by
80.Xr isspace 3 ) 89.Xr isspace 3 )
81followed by a single optional 90followed by a single optional
@@ -85,26 +94,22 @@ or
85sign. 94sign.
86If 95If
87.Fa base 96.Fa base
88is zero or 16, 97is zero or 16, the string may then include a
89the string may then include a
90.Ql 0x 98.Ql 0x
91prefix, 99prefix, 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 100.Fa base
94is taken as 10 (decimal) unless the next character is 101is taken as 10 (decimal) unless the next character is
95.Ql 0 , 102.Ql 0 ,
96in which case it is taken as 8 (octal). 103in which case it is taken as 8 (octal).
97.Pp 104.Pp
98The remainder of the string is converted to an 105The remainder of the string is converted to an
99.Em unsigned long 106.Li unsigned long
100value in the obvious manner, 107value 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 108or at the first character that does not produce a valid digit
103in the given base. 109in the given base.
104(In bases above 10, the letter 110(In bases above 10, the letter
105.Ql A 111.Ql A
106in either upper or lower case 112in either upper or lower case represents 10,
107represents 10,
108.Ql B 113.Ql B
109represents 11, and so forth, with 114represents 11, and so forth, with
110.Ql Z 115.Ql Z
@@ -112,7 +117,7 @@ representing 35.)
112.Pp 117.Pp
113If 118If
114.Fa endptr 119.Fa endptr
115is non nil, 120is non-null,
116.Fn strtoul 121.Fn strtoul
117stores the address of the first invalid character in 122stores the address of the first invalid character in
118.Fa *endptr . 123.Fa *endptr .
@@ -134,12 +139,18 @@ on return, the entire string was valid.)
134.Sh RETURN VALUES 139.Sh RETURN VALUES
135The 140The
136.Fn strtoul 141.Fn strtoul
137function 142function returns the result of the conversion,
138returns either the result of the conversion 143unless the value would overflow, in which case
139or, if there was a leading minus sign, 144.Dv ULONG_MAX
140the negation of the result of the conversion, 145is returned and
141unless the original (non-negated) value would overflow; 146.Va errno
142in the latter case, 147is set to
148.Er ERANGE .
149If there was a leading minus sign,
150.Fn strtoul
151returns the (unsigned) negation of the absolute value of the number, unless
152the absolute value would overflow.
153In this case,
143.Fn strtoul 154.Fn strtoul
144returns 155returns
145.Dv ULONG_MAX 156.Dv ULONG_MAX
@@ -147,18 +158,68 @@ and sets the global variable
147.Va errno 158.Va errno
148to 159to
149.Er ERANGE . 160.Er ERANGE .
161.Pp
162The
163.Fn strtoull
164function has identical return values except that
165.Dv ULLONG_MIN
166and
167.Dv ULLONG_MAX
168are used to indicate underflow and overflow respectively.
169.Pp
170There is no way to determine if
171.Fn strtoul
172has processed a negative number (and returned an unsigned value) short of
173examining the string in
174.Fa nptr
175directly.
176.Sh EXAMPLES
177Ensuring that a string is a valid number (i.e., in range and containing no
178trailing characters) requires clearing
179.Va errno
180beforehand explicitly since
181.Va errno
182is not changed on a successful call to
183.Fn strtoul ,
184and the return value of
185.Fn strtoul
186cannot be used unambiguously to signal an error:
187.Bd -literal -offset indent
188char *ep;
189unsigned long ulval;
190
191\&...
192
193errno = 0;
194ulval = strtoul(buf, &ep, 10);
195if (buf[0] == '\e0' || *ep != '\e0')
196 goto not_a_number;
197if (errno == ERANGE && ulval == ULONG_MAX)
198 goto out_of_range;
199.Ed
200.Pp
201This example will accept
202.Dq 12
203but not
204.Dq 12foo
205or
206.Dq 12\en .
207If trailing whitespace is acceptable, further checks must be done on
208.Va *ep ;
209alternately, use
210.Xr sscanf 3 .
150.Sh ERRORS 211.Sh ERRORS
151.Bl -tag -width Er 212.Bl -tag -width Er
152.It Bq Er ERANGE 213.It Bq Er ERANGE
153The given string was out of range; the value converted has been clamped. 214The given string was out of range; the value converted has been clamped.
154.El 215.El
155.Sh SEE ALSO 216.Sh SEE ALSO
217.Xr sscanf 3 ,
156.Xr strtol 3 218.Xr strtol 3
157.Sh STANDARDS 219.Sh STANDARDS
158The 220The
159.Fn strtoul 221.Fn strtoul
160function 222function conforms to
161conforms to
162.St -ansiC . 223.St -ansiC .
163.Sh BUGS 224.Sh BUGS
164Ignores the current locale. 225Ignores 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..e7b81d0c43 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.10 2001/09/05 16:27:01 mickey 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 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,38 @@ 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
diff --git a/src/lib/libc/string/__strerror.c b/src/lib/libc/string/__strerror.c
index cd604906db..ae19ab3365 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.8 2001/12/08 20:37:32 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 strcpy(buf, UPREFIX);
84#endif 102#endif
103 strncat(buf, itoa(errnum), NL_TEXTMAX-strlen(buf)-1);
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..4ca5bad3c0 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.6 2001/06/27 00:58:56 lebel 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 strcpy(buf, UPREFIX);
78#endif 93#endif
94 strncat(buf, itoa(signum), NL_TEXTMAX-strlen(buf)-1);
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..b290418f4a 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.5 2000/04/21 15:24:19 aaron 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
@@ -68,5 +66,5 @@ is zero, no bytes are copied.
68.Sh HISTORY 66.Sh HISTORY
69A 67A
70.Fn bcopy 68.Fn bcopy
71function appeared in 69function appeared in
72.Bx 4.2 . 70.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.3 b/src/lib/libc/string/index.3
deleted file mode 100644
index 847b03628b..0000000000
--- a/src/lib/libc/string/index.3
+++ /dev/null
@@ -1,83 +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: @(#)index.3 5.3 (Berkeley) 4/19/91
35.\" $Id: index.3,v 1.1.1.1 1995/10/18 08:42:21 deraadt Exp $
36.\"
37.Dd April 19, 1991
38.Dt INDEX 3
39.Os
40.Sh NAME
41.Nm index
42.Nd locate character in string
43.Sh SYNOPSIS
44.Fd #include <string.h>
45.Ft char *
46.Fn index "const char *s" "int c"
47.Sh DESCRIPTION
48The
49.Fn index
50function
51locates the first character matching
52.Fa c
53(converted to a
54.Em char )
55in the null-terminated string
56.Fa s .
57.Sh RETURN VALUES
58The character
59.Fa c
60is returned if it is found; otherwise
61.Dv NULL
62is returned.
63If
64.Fa c
65is '\e0',
66.Fn index
67locates the terminating '\e0'.
68.Sh SEE ALSO
69.Xr memchr 3 ,
70.Xr rindex 3 ,
71.Xr strchr 3 ,
72.Xr strcspn 3 ,
73.Xr strpbrk 3 ,
74.Xr strrchr 3 ,
75.Xr strsep 3 ,
76.Xr strspn 3 ,
77.Xr strstr 3 ,
78.Xr strtok 3
79.Sh HISTORY
80A
81.Fn index
82function appeared in
83.At v6 .
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..feedeff3a6 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.6 2000/04/21 15:24:19 aaron 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,7 +63,7 @@ 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 ,
@@ -69,5 +72,5 @@ bytes are copied, and a NULL pointer is returned.
69.Sh HISTORY 72.Sh HISTORY
70The 73The
71.Fn memccpy 74.Fn memccpy
72function is 75function first appeared in
73.Ud . 76.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..030eadff20 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.3 2000/04/21 15:24:19 aaron 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,8 +57,7 @@ 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 ,
@@ -70,8 +67,7 @@ returns the original value of
70.Sh STANDARDS 67.Sh STANDARDS
71The 68The
72.Fn memcpy 69.Fn memcpy
73function 70function conforms to
74conforms to
75.St -ansiC . 71.St -ansiC .
76.Sh BUGS 72.Sh BUGS
77In this implementation 73In this implementation
diff --git a/src/lib/libc/string/memmove.3 b/src/lib/libc/string/memmove.3
index 24422e7971..026dab0f9f 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.3 2000/04/21 15:24:19 aaron 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
@@ -71,6 +69,5 @@ function returns the original value of
71.Sh STANDARDS 69.Sh STANDARDS
72The 70The
73.Fn memmove 71.Fn memmove
74function 72function conforms to
75conforms to
76.St -ansiC . 73.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..3cfc76e36f 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.6 2000/04/21 15:24:19 aaron 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,8 +53,7 @@ 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
@@ -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..c1173a423a 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.5 2000/04/21 15:24:19 aaron 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 .
@@ -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..5d3e44ee96 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.3 2000/04/21 15:24:19 aaron 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,8 +48,7 @@
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
@@ -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..9c154c7d70 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.10 2000/04/21 15:32:15 aaron 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,46 @@
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 strlen 3
61.Sh HISTORY 83.Sh HISTORY
62The 84The
63.Fn strdup 85.Fn strdup
64function 86function first appeared in
65.Ud . 87.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..11bacd313e 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.4 2000/10/23 19:14:41 aaron 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
@@ -50,7 +49,11 @@
50The 49The
51.Fn strerror 50.Fn strerror
52function returns a pointer to the language-dependent error message 51function returns a pointer to the language-dependent error message
53string affiliated with an error number. 52string affiliated with the specified error number
53.Fa errnum .
54The returned string contains a maximum of
55.Dv NL_TEXTMAX
56characters, including the trailing NUL.
54.Pp 57.Pp
55The array pointed to is not to be modified by the program, but may be 58The array pointed to is not to be modified by the program, but may be
56overwritten by subsequent calls to 59overwritten by subsequent calls to
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/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..b309648155
--- /dev/null
+++ b/src/lib/libc/string/strlcat.c
@@ -0,0 +1,73 @@
1/* $OpenBSD: strlcat.c,v 1.8 2001/05/13 15:40:15 deraadt Exp $ */
2
3/*
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.
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: strlcat.c,v 1.8 2001/05/13 15:40:15 deraadt Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <sys/types.h>
35#include <string.h>
36
37/*
38 * Appends src to string dst of size siz (unlike strncat, siz is the
39 * full size of dst, not space left). At most siz-1 characters
40 * will be copied. Always NUL terminates (unless siz <= strlen(dst)).
41 * Returns strlen(src) + MIN(siz, strlen(initial dst)).
42 * If retval >= siz, truncation occurred.
43 */
44size_t
45strlcat(dst, src, siz)
46 char *dst;
47 const char *src;
48 size_t siz;
49{
50 register char *d = dst;
51 register const char *s = src;
52 register size_t n = siz;
53 size_t dlen;
54
55 /* Find the end of dst and adjust bytes left but don't go past end */
56 while (n-- != 0 && *d != '\0')
57 d++;
58 dlen = d - dst;
59 n = siz - dlen;
60
61 if (n == 0)
62 return(dlen + strlen(s));
63 while (*s != '\0') {
64 if (n != 1) {
65 *d++ = *s;
66 n--;
67 }
68 s++;
69 }
70 *d = '\0';
71
72 return(dlen + (s - src)); /* count does not include NUL */
73}
diff --git a/src/lib/libc/string/strlcpy.3 b/src/lib/libc/string/strlcpy.3
new file mode 100644
index 0000000000..b103588b96
--- /dev/null
+++ b/src/lib/libc/string/strlcpy.3
@@ -0,0 +1,190 @@
1.\" $OpenBSD: strlcpy.3,v 1.14 2002/04/30 16:31:42 mpech Exp $
2.\"
3.\" Copyright (c) 1998, 2000 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 June 22, 1998
29.Dt STRLCPY 3
30.Os
31.Sh NAME
32.Nm strlcpy ,
33.Nm strlcat
34.Nd size-bounded string copying and concatenation
35.Sh SYNOPSIS
36.Fd #include <string.h>
37.Ft size_t
38.Fn strlcpy "char *dst" "const char *src" "size_t size"
39.Ft size_t
40.Fn strlcat "char *dst" "const char *src" "size_t size"
41.Sh DESCRIPTION
42The
43.Fn strlcpy
44and
45.Fn strlcat
46functions copy and concatenate strings respectively.
47They are designed
48to be safer, more consistent, and less error prone replacements for
49.Xr strncpy 3
50and
51.Xr strncat 3 .
52Unlike those functions,
53.Fn strlcpy
54and
55.Fn strlcat
56take the full size of the buffer (not just the length) and guarantee to
57NUL-terminate the result (as long as
58.Fa size
59is larger than 0 or, in the case of
60.Fn strlcat ,
61as long as there is at least one byte free in
62.Fa dst ) .
63Note that you should include a byte for the NUL in
64.Fa size .
65Also note that
66.Fn strlcpy
67and
68.Fn strlcat
69only operate on true
70.Dq C
71strings.
72This means that for
73.Fn strlcpy
74.Fa src
75must be NUL-terminated and for
76.Fn strlcat
77both
78.Fa src
79and
80.Fa dst
81must be NUL-terminated.
82.Pp
83The
84.Fn strlcpy
85function copies up to
86.Fa size
87- 1 characters from the NUL-terminated string
88.Fa src
89to
90.Fa dst ,
91NUL-terminating the result.
92.Pp
93The
94.Fn strlcat
95function appends the NUL-terminated string
96.Fa src
97to the end of
98.Fa dst .
99It will append at most
100.Fa size
101- strlen(dst) - 1 bytes, NUL-terminating the result.
102.Sh RETURN VALUES
103The
104.Fn strlcpy
105and
106.Fn strlcat
107functions return the total length of the string they tried to create.
108For
109.Fn strlcpy
110that means the length of
111.Fa src .
112For
113.Fn strlcat
114that means the initial length of
115.Fa dst
116plus
117the length of
118.Fa src .
119While this may seem somewhat confusing it was done to make
120truncation detection simple.
121.Pp
122Note however, that if
123.Fn strlcat
124traverses
125.Fa size
126characters without finding a NUL, the length of the string is considered
127to be
128.Fa size
129and the destination string will not be NUL-terminated (since there was
130no space for the NUL).
131This keeps
132.Fn strlcat
133from running off the end of a string.
134In practice this should not happen (as it means that either
135.Fa size
136is incorrect or that
137.Fa dst
138is not a proper
139.Dq C
140string).
141The check exists to prevent potential security problems in incorrect code.
142.Sh EXAMPLES
143The following code fragment illustrates the simple case:
144.Bd -literal -offset indent
145char *s, *p, buf[BUFSIZ];
146
147\&...
148
149(void)strlcpy(buf, s, sizeof(buf));
150(void)strlcat(buf, p, sizeof(buf));
151.Ed
152.Pp
153To detect truncation, perhaps while building a pathname, something
154like the following might be used:
155.Bd -literal -offset indent
156char *dir, *file, pname[MAXPATHLEN];
157
158\&...
159
160if (strlcpy(pname, dir, sizeof(pname)) >= sizeof(pname))
161 goto toolong;
162if (strlcat(pname, file, sizeof(pname)) >= sizeof(pname))
163 goto toolong;
164.Ed
165.Pp
166Since we know how many characters we copied the first time, we can
167speed things up a bit by using a copy instead of an append:
168.Bd -literal -offset indent
169char *dir, *file, pname[MAXPATHLEN];
170size_t n;
171
172\&...
173
174n = strlcpy(pname, dir, sizeof(pname));
175if (n >= sizeof(pname))
176 goto toolong;
177if (strlcpy(pname + n, file, sizeof(pname) - n) >= sizeof(pname) - n)
178 goto toolong;
179.Ed
180.Pp
181However, one may question the validity of such optimizations, as they
182defeat the whole purpose of
183.Fn strlcpy
184and
185.Fn strlcat .
186As a matter of fact, the first version of this manual page got it wrong.
187.Sh SEE ALSO
188.Xr snprintf 3 ,
189.Xr strncat 3 ,
190.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..5f586964b7
--- /dev/null
+++ b/src/lib/libc/string/strlcpy.c
@@ -0,0 +1,69 @@
1/* $OpenBSD: strlcpy.c,v 1.5 2001/05/13 15:40:16 deraadt Exp $ */
2
3/*
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.
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: strlcpy.c,v 1.5 2001/05/13 15:40:16 deraadt Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <sys/types.h>
35#include <string.h>
36
37/*
38 * Copy src to string dst of size siz. At most siz-1 characters
39 * will be copied. Always NUL terminates (unless siz == 0).
40 * Returns strlen(src); if retval >= siz, truncation occurred.
41 */
42size_t
43strlcpy(dst, src, siz)
44 char *dst;
45 const char *src;
46 size_t siz;
47{
48 register char *d = dst;
49 register const char *s = src;
50 register size_t n = siz;
51
52 /* Copy as many bytes as will fit */
53 if (n != 0 && --n != 0) {
54 do {
55 if ((*d++ = *s++) == 0)
56 break;
57 } while (--n != 0);
58 }
59
60 /* Not enough room in dst, add NUL and traverse rest of src */
61 if (n == 0) {
62 if (siz != 0)
63 *d = '\0'; /* NUL-terminate dst */
64 while (*s++)
65 ;
66 }
67
68 return(s - src - 1); /* count does not include NUL */
69}
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..bf311f1f99 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.8 2000/04/21 15:24:20 aaron 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
@@ -72,6 +71,8 @@ symbolic link
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)