aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorgreen <green@FreeBSD.org>2000-01-14 07:22:17 +0800
committergreen <green@FreeBSD.org>2000-01-14 07:22:17 +0800
commit31ff3d8b8e3a98ff7cc836114f499cd165d6c5d4 (patch)
treedf9195fdb301e7c218a13f363f5ec175d83123b2 /security
parentda7dcc13580c6c33244ffdce133a5cfb8fc4ff3a (diff)
downloadfreebsd-ports-gnome-31ff3d8b8e3a98ff7cc836114f499cd165d6c5d4.tar.gz
freebsd-ports-gnome-31ff3d8b8e3a98ff7cc836114f499cd165d6c5d4.tar.zst
freebsd-ports-gnome-31ff3d8b8e3a98ff7cc836114f499cd165d6c5d4.zip
Update to a more current OpenSSH, including...
IPv6 support!! Thank you very much, Sumikawa san. Submitted by: Munechika SUMIKAWA <sumikawa@ebina.hitachi.co.jp>
Diffstat (limited to 'security')
-rw-r--r--security/openssh/Makefile11
-rw-r--r--security/openssh/distinfo44
-rw-r--r--security/openssh/files/bindresvport.c151
-rw-r--r--security/openssh/files/getaddrinfo.c1024
-rw-r--r--security/openssh/files/getnameinfo.c228
-rw-r--r--security/openssh/files/name6.c1262
-rw-r--r--security/openssh/files/netdb.h259
-rw-r--r--security/openssh/files/patch-ab9
-rw-r--r--security/openssh/files/patch-ac38
-rw-r--r--security/openssh/files/patch-ad12
-rw-r--r--security/openssh/files/patch-an76
-rw-r--r--security/openssh/files/patch-ao10
-rw-r--r--security/openssh/files/patch-at14
-rw-r--r--security/openssh/files/rcmd.c653
14 files changed, 3716 insertions, 75 deletions
diff --git a/security/openssh/Makefile b/security/openssh/Makefile
index 5c6e61ac8445..052b25b1dcd3 100644
--- a/security/openssh/Makefile
+++ b/security/openssh/Makefile
@@ -23,7 +23,7 @@ CAT?= /bin/cat
DISTFILES!= ${CAT} ${FILESDIR}/distfiles
CVS_CMD?= cvs -z3
-CVS_DATE= Thu Dec 23 01:07:56 EST 1999
+CVS_DATE= Fri Jan 7 01:25:49 JST 2000
SED?= /usr/bin/sed
CVS_DATE_!= ${ECHO} -n "${CVS_DATE}" | ${SED} 's/[ \t:]/_/g'
CVS_SITES= anoncvs@anoncvs1.ca.openbsd.org:/cvs \
@@ -34,6 +34,9 @@ CRYPTOLIBS+= -lRSAglue -lrsaref
.endif
# Here, MANDIR is concetenated to DESTDIR which all forms the man install dir...
MAKE_ENV= DESTDIR=${PREFIX} MANDIR=/man/man CRYPTOLIBS="${CRYPTOLIBS}"
+.if defined(USE_INET6)
+MAKE_ENV+= USET_INET6=yes
+.endif
.if !exists(/usr/include/tcpd.h)
MAKE_ENV+= TCP_WRAPPERS=no
.endif
@@ -113,6 +116,12 @@ do-extract:
@${MKDIR} ${WRKDIR}
@${CP} -r ${DISTDIR}/${PKGNAME}/${DISTNAME} ${WRKDIR}
@${CP} ${FILESDIR}/strlcat.c ${FILESDIR}/strlcpy.c ${WRKSRC}/lib/
+.if !defined(USE_INET6)
+ @${CP} ${FILESDIR}/getaddrinfo.c ${FILESDIR}/name6.c ${WRKSRC}/lib/
+ @${CP} ${FILESDIR}/bindresvport.c ${FILESDIR}/rcmd.c ${WRKSRC}/lib/
+ @${CP} ${FILESDIR}/getnameinfo.c ${FILESDIR}/rcmd.c ${WRKSRC}/lib/
+ @${CP} ${FILESDIR}/netdb.h ${WRKSRC}/
+.endif
@${MKDIR} ${WRKSRC}/pam_ssh
@${CP} ${FILESDIR}/pam_ssh_Makefile ${WRKSRC}/pam_ssh/Makefile
@${CP} ${FILESDIR}/pam_ssh.c ${WRKSRC}/pam_ssh/
diff --git a/security/openssh/distinfo b/security/openssh/distinfo
index b1240d5bbf1c..8f75ea9de002 100644
--- a/security/openssh/distinfo
+++ b/security/openssh/distinfo
@@ -6,9 +6,9 @@ MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/README) = e54fb9189053db5ad25892054c8d0989
MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/RFC.nroff) = 1615f30810a3d47716883b2eaddd712c
MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/atomicio.c) = 765037b689925ccd476de647d4aaf9ed
MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/auth-krb4.c) = e9f588343a4954004ecbf7ba805edde2
-MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/auth-passwd.c) = ad6e1b7a3e64d3de451b319a3bdda823
+MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/auth-passwd.c) = 176629d0f658f24120a5710c9b5a84d8
MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/auth-rh-rsa.c) = a1c4177fb07f7dcc4dbe6c468bab608e
-MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/auth-rhosts.c) = 50c042e1a659782bba7e1edd7c43c233
+MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/auth-rhosts.c) = 2df099d85d31d7346cba663a45592c91
MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/auth-rsa.c) = 1c3d74a611cda703b133112123a677c1
MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/auth-skey.c) = 1c003cb98aea4e771a9ec3e67dd99096
MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/authfd.c) = 08ebd5cb6fd9521ead44475a59880ea9
@@ -18,8 +18,8 @@ MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/bufaux.c) = 877a21dbdd68ef04a1e39a0e6d34450e
MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/bufaux.h) = 46caf1274857d0bdc5eabe60d56f6aaf
MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/buffer.c) = 6cea321387c23d5cfaefca38bc167c1f
MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/buffer.h) = c284a258593ae4d8905d94ddae45f4b1
-MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/canohost.c) = d138b179904396b30bba07a3d96bc3f1
-MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/channels.c) = 21569b184aca98f6a53723b647ea2227
+MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/canohost.c) = 4ebd799aac04aa6c0e23d0c1e27e9ea6
+MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/channels.c) = a646f9209452b8993ff4b547e6e1f945
MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/channels.h) = e597ecd2255e0f92fb5a92c40c99d8b4
MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/cipher.c) = 2bf8f287540f2448b4af0b894aeacf8b
MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/cipher.h) = e1b48bd7a4e37c1b106f968d8377b843
@@ -35,21 +35,21 @@ MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/deattack.h) = db63f71b6c19484dd8ce5041cc6b646
MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/fingerprint.c) = 782318f23ec96a679f140a475ee38638
MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/fingerprint.h) = 17d73906c4f0c1cddb3c1c7e98d02785
MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/getput.h) = bf729289671363abc3882e1e0c34d270
-MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/hostfile.c) = df76ac8ab45dc2bd796b3b0af16fcbef
+MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/hostfile.c) = a165685e4989eb99d31a84eba3acb55c
MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/includes.h) = 1dc9df93b0be59b6351755ea7817be09
MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/lib/Makefile) = 66b181f50f06eb76ecc6c59acf0f3068
MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/log-client.c) = a05d3671346fd5a958cc74d1e2416b63
MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/log-server.c) = d1c4f02578b1a83c972b7acd04ea2fa2
-MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/log.c) = 8389216c70241d8858fd4b4029361166
-MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/login.c) = e6d2ed8545050d71606b4b857c35af5f
+MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/log.c) = 40cc9c89526c10ef6cb2c46c0258727e
+MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/login.c) = ab361f9b7f5bccae2ca67c55445353a0
MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/match.c) = facc507e6b48d09f9df77c2a77b365c3
MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/mpaux.c) = 50ebda88832e2852c1bab39e5e5ac5bb
MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/mpaux.h) = 3dd5ddaa6baccf7f38964e69cd2f9e1c
MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/nchan.c) = 63c2980438954303525580ebcebc0d11
MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/nchan.h) = 884bb0c2b62f274ccbf9c0eafc9d37c2
MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/nchan.ms) = 815e166dc85a329c3cfd98bd8cfda930
-MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/packet.c) = 280c43c49ee1ec3fa14f75268471d3fe
-MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/packet.h) = 52811069d035c6900113732bf22e1456
+MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/packet.c) = 12dbfde0eec29e953e5718469c756e65
+MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/packet.h) = a2889cb1db9ae9e8833a8746e7e3cc18
MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/pty.c) = 42defbf1571c948865056a06d976235f
MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/pty.h) = f2fb71af9954aebec8b3b69320dd6d12
MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/radix.c) = 599f6349035451d48e36334b21696963
@@ -58,31 +58,31 @@ MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/readconf.h) = 9f40c6fa01b174149efbaad4bf21c33
MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/readpass.c) = 282110d41691d426501a24a36c1efd03
MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/rsa.c) = 3b47f0c260e26c118d971fafed604d3f
MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/rsa.h) = ee65e38f1fcc22328c5d5f07b57d6e5f
-MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/scp.1) = a9144b2b272d8ac656b1d63c71644999
-MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/scp.c) = 29ced969b9c1d05f42bfb07b238a8543
+MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/scp.1) = 939fd8b3eb1965e081e557fcd069b89e
+MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/scp.c) = 84865c7072e67bab6900fc814e666e8d
MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/scp/Makefile) = 5cb4c5fcabde5ccc4f9ca475ac3452f4
-MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/servconf.c) = 62079877f586c06b71c384e556a78be2
-MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/servconf.h) = 056da4377475fbcded1ca288a1faf26e
+MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/servconf.c) = 2a4ae4323190d562b1bf5406822c7f43
+MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/servconf.h) = 70595ee9c1fb106695343787e1696bce
MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/serverloop.c) = b2282cf4f899b132134d783f691a2fca
MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/ssh-add.1) = 46ee567cafbde041222984ddead7bd51
MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/ssh-add.c) = b2bcb9fcac8725699faaf8f2d8e6894c
MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/ssh-add/Makefile) = f780e2e9fb5c32d2118ba0e612d681e0
MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/ssh-agent.1) = 33b62903d3aa452fa106b484b016bbc5
-MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/ssh-agent.c) = 20f70bcc11320a47fb847c4c83bd7d1a
+MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/ssh-agent.c) = 5bdf7f32d33ceb9dab8f3b0516e3b012
MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/ssh-agent/Makefile) = c7ec7c4e61b4da3369980f197fdcb501
-MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/ssh-keygen.1) = 746734eab948fff84a44c3383f5a1701
+MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/ssh-keygen.1) = 81623b151c4a8090f6ea1151d8662f5a
MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/ssh-keygen.c) = 439aac7630c0dc54b750ecbe314bc09b
MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/ssh-keygen/Makefile) = 2d597b6e6458d0c0246ba2563dd2498b
-MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/ssh.1) = 3dc212df3c774ec6d50752590cbded15
-MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/ssh.c) = 168eb32dadff717d7778975ac3fbf50a
-MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/ssh.h) = 01527755013e7b8b1dd4756919e51eed
+MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/ssh.1) = f832bb483c82b31f7487a9ac071abbb2
+MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/ssh.c) = 13de482b362f050b3893b95514a6f56d
+MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/ssh.h) = daa7778da5032e411ca567a79782a316
MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/ssh/Makefile) = 41b006d3c04b599619990b47da60f81e
MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/ssh_config) = 9658715526aeaf0bc43528d3159b475f
-MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/sshconnect.c) = d3e7c5124fb7a8570ed543cecf493095
-MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/sshd.8) = e08d1683e931a4b30e0e411d4d3576c8
-MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/sshd.c) = 7f3b23f9e982a63fead1e813ff079b9c
+MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/sshconnect.c) = 0cfc1cefe83aaa075380082920fc3de6
+MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/sshd.8) = 24e8c96c0eff5b2f21844345eb3458ff
+MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/sshd.c) = ffbdc65ddce95238c28a8f26dbb35432
MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/sshd/Makefile) = d1d83d1ece775d3a5cbf8cfaaf2330f3
-MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/sshd_config) = e78b81c34da5c97eee1359cccda908d6
+MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/sshd_config) = f48bdabb5094cb6aaa1f398987cbf9b4
MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/tildexpand.c) = 65ba9200404da3a094823605f57bca12
MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/ttymodes.c) = 570810b08bdb8bc962630c2fbb425a00
MD5 (OpenSSH-1.2.1/src/usr.bin/ssh/ttymodes.h) = a08ab0789c979c7942423e2ab3df79dd
diff --git a/security/openssh/files/bindresvport.c b/security/openssh/files/bindresvport.c
new file mode 100644
index 000000000000..258e8547b388
--- /dev/null
+++ b/security/openssh/files/bindresvport.c
@@ -0,0 +1,151 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+/*static char *sccsid = "from: @(#)bindresvport.c 1.8 88/02/08 SMI";*/
+/*static char *sccsid = "from: @(#)bindresvport.c 2.2 88/07/29 4.0 RPCSRC";*/
+/*from: OpenBSD: bindresvport.c,v 1.7 1996/07/30 16:25:47 downsj Exp */
+static char *rcsid = "$FreeBSD: /tmp/pcvs/ports/security/openssh/files/Attic/bindresvport.c,v 1.1 2000-01-13 23:22:12 green Exp $";
+#endif
+
+/*
+ * Copyright (c) 1987 by Sun Microsystems, Inc.
+ *
+ * Portions Copyright(C) 1996, Jason Downs. All rights reserved.
+ */
+
+#include <sys/types.h>
+#include <sys/errno.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "includes.h"
+
+/*
+ * Bind a socket to a privileged IP port
+ */
+int
+bindresvport(sd, sin)
+ int sd;
+ struct sockaddr_in *sin;
+{
+ struct sockaddr_in myaddr;
+ int sinlen = sizeof(struct sockaddr_in);
+
+ if (sin == (struct sockaddr_in *)0) {
+ sin = &myaddr;
+ memset(sin, 0, sinlen);
+ sin->sin_len = sinlen;
+ sin->sin_family = AF_INET;
+ } else if (sin->sin_family != AF_INET) {
+ errno = EPFNOSUPPORT;
+ return (-1);
+ }
+
+ return (bindresvport2(sd, sin, sinlen));
+}
+
+int
+bindresvport2(sd, sa, addrlen)
+ int sd;
+ struct sockaddr *sa;
+ socklen_t addrlen;
+{
+ int on, old, error, level, optname;
+ u_short port;
+
+ if (sa == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+ switch (sa->sa_family) {
+ case AF_INET:
+ port = ntohs(((struct sockaddr_in *)sa)->sin_port);
+ level = IPPROTO_IP;
+ optname = IP_PORTRANGE;
+ on = IP_PORTRANGE_LOW;
+ break;
+#ifdef INET6
+ case AF_INET6:
+ port = ntohs(((struct sockaddr_in6 *)sa)->sin6_port);
+ level = IPPROTO_IPV6;
+ optname = IPV6_PORTRANGE;
+ on = IPV6_PORTRANGE_LOW;
+ break;
+#endif
+ default:
+ errno = EAFNOSUPPORT;
+ return (-1);
+ }
+
+ if (port == 0) {
+ int oldlen = sizeof(old);
+ error = getsockopt(sd, level, optname, &old, &oldlen);
+ if (error < 0)
+ return(error);
+
+ error = setsockopt(sd, level, optname, &on, sizeof(on));
+ if (error < 0)
+ return(error);
+ }
+
+ error = bind(sd, sa, addrlen);
+
+ switch (sa->sa_family) {
+ case AF_INET:
+ port = ntohs(((struct sockaddr_in *)sa)->sin_port);
+ break;
+#ifdef INET6
+ case AF_INET6:
+ port = ntohs(((struct sockaddr_in6 *)sa)->sin6_port);
+ break;
+#endif
+ default: /* shoud not match here */
+ errno = EAFNOSUPPORT;
+ return (-1);
+ }
+ if (port == 0) {
+ int saved_errno = errno;
+
+ if (error) {
+ if (setsockopt(sd, level, optname,
+ &old, sizeof(old)) < 0)
+ errno = saved_errno;
+ return (error);
+ }
+
+ /* Hmm, what did the kernel assign... */
+ if (getsockname(sd, (struct sockaddr *)sa, &addrlen) < 0)
+ errno = saved_errno;
+ return (error);
+ }
+ return (error);
+}
diff --git a/security/openssh/files/getaddrinfo.c b/security/openssh/files/getaddrinfo.c
new file mode 100644
index 000000000000..a09abd96dc60
--- /dev/null
+++ b/security/openssh/files/getaddrinfo.c
@@ -0,0 +1,1024 @@
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: /tmp/pcvs/ports/security/openssh/files/Attic/getaddrinfo.c,v 1.1 2000-01-13 23:22:12 green Exp $
+ */
+
+/*
+ * "#ifdef FAITH" part is local hack for supporting IPv4-v6 translator.
+ *
+ * Issues to be discussed:
+ * - Thread safe-ness must be checked.
+ * - Return values. There are nonstandard return values defined and used
+ * in the source code. This is because RFC2553 is silent about which error
+ * code must be returned for which situation.
+ * - PF_UNSPEC case would be handled in getipnodebyname() with the AI_ALL flag.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <stdio.h>
+
+#if defined(__KAME__) && defined(INET6)
+# define FAITH
+#endif
+
+#define SUCCESS 0
+#define ANY 0
+#define YES 1
+#define NO 0
+
+static const char in_addrany[] = { 0, 0, 0, 0 };
+static const char in6_addrany[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+static const char in_loopback[] = { 127, 0, 0, 1 };
+static const char in6_loopback[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
+};
+
+static const struct afd {
+ int a_af;
+ int a_addrlen;
+ int a_socklen;
+ int a_off;
+ const char *a_addrany;
+ const char *a_loopback;
+ int a_scoped;
+} afdl [] = {
+#ifdef INET6
+#define N_INET6 0
+ {PF_INET6, sizeof(struct in6_addr),
+ sizeof(struct sockaddr_in6),
+ offsetof(struct sockaddr_in6, sin6_addr),
+ in6_addrany, in6_loopback, 1},
+#define N_INET 1
+#else
+#define N_INET 0
+#endif
+ {PF_INET, sizeof(struct in_addr),
+ sizeof(struct sockaddr_in),
+ offsetof(struct sockaddr_in, sin_addr),
+ in_addrany, in_loopback, 0},
+ {0, 0, 0, 0, NULL, NULL, 0},
+};
+
+struct explore {
+ int e_af;
+ int e_socktype;
+ int e_protocol;
+ const char *e_protostr;
+ int e_wild;
+#define WILD_AF(ex) ((ex)->e_wild & 0x01)
+#define WILD_SOCKTYPE(ex) ((ex)->e_wild & 0x02)
+#define WILD_PROTOCOL(ex) ((ex)->e_wild & 0x04)
+};
+
+static const struct explore explore[] = {
+#ifdef INET6
+ { PF_INET6, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
+ { PF_INET6, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
+ { PF_INET6, SOCK_RAW, ANY, NULL, 0x05 },
+#endif
+ { PF_INET, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
+ { PF_INET, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
+ { PF_INET, SOCK_RAW, ANY, NULL, 0x05 },
+ { -1, 0, 0, NULL, 0 },
+};
+
+#ifdef INET6
+#define PTON_MAX 16
+#else
+#define PTON_MAX 4
+#endif
+
+
+static int str_isnumber __P((const char *));
+static int explore_fqdn __P((const struct addrinfo *, const char *,
+ const char *, struct addrinfo **));
+static int explore_null __P((const struct addrinfo *, const char *,
+ const char *, struct addrinfo **));
+static int explore_numeric __P((const struct addrinfo *, const char *,
+ const char *, struct addrinfo **));
+static int explore_numeric_scope __P((const struct addrinfo *, const char *,
+ const char *, struct addrinfo **));
+static int get_name __P((const char *, const struct afd *, struct addrinfo **,
+ char *, const struct addrinfo *, const char *));
+static int get_canonname __P((const struct addrinfo *,
+ struct addrinfo *, const char *));
+static struct addrinfo *get_ai __P((const struct addrinfo *,
+ const struct afd *, const char *));
+static int get_portmatch __P((const struct addrinfo *, const char *));
+static int get_port __P((struct addrinfo *, const char *, int));
+static const struct afd *find_afd __P((int));
+
+static char *ai_errlist[] = {
+ "Success",
+ "Address family for hostname not supported", /* EAI_ADDRFAMILY */
+ "Temporary failure in name resolution", /* EAI_AGAIN */
+ "Invalid value for ai_flags", /* EAI_BADFLAGS */
+ "Non-recoverable failure in name resolution", /* EAI_FAIL */
+ "ai_family not supported", /* EAI_FAMILY */
+ "Memory allocation failure", /* EAI_MEMORY */
+ "No address associated with hostname", /* EAI_NODATA */
+ "hostname nor servname provided, or not known", /* EAI_NONAME */
+ "servname not supported for ai_socktype", /* EAI_SERVICE */
+ "ai_socktype not supported", /* EAI_SOCKTYPE */
+ "System error returned in errno", /* EAI_SYSTEM */
+ "Invalid value for hints", /* EAI_BADHINTS */
+ "Resolved protocol is unknown", /* EAI_PROTOCOL */
+ "Argument res is NULL", /* EAI_RESNULL */
+ "Unknown error", /* EAI_MAX */
+};
+
+/* XXX macros that make external reference is BAD. */
+
+#define GET_AI(ai, afd, addr) \
+do { \
+ /* external reference: pai, error, and label free */ \
+ (ai) = get_ai(pai, (afd), (addr)); \
+ if ((ai) == NULL) { \
+ error = EAI_MEMORY; \
+ goto free; \
+ } \
+} while (0)
+
+#define GET_PORT(ai, serv) \
+do { \
+ /* external reference: error and label free */ \
+ error = get_port((ai), (serv), 0); \
+ if (error != 0) \
+ goto free; \
+} while (0)
+
+#define GET_CANONNAME(ai, str) \
+do { \
+ /* external reference: pai, error and label free */ \
+ error = get_canonname(pai, (ai), (str)); \
+ if (error != 0) \
+ goto free; \
+} while (0)
+
+#define ERR(err) \
+do { \
+ /* external reference: error, and label bad */ \
+ error = (err); \
+ goto bad; \
+} while (0)
+
+#define MATCH_FAMILY(x, y, w) \
+ ((x) == (y) || ((w) && ((x) == PF_UNSPEC || (y) == PF_UNSPEC)))
+#define MATCH(x, y, w) \
+ ((x) == (y) || ((w) && ((x) == ANY || (y) == ANY)))
+
+char *
+gai_strerror(ecode)
+ int ecode;
+{
+ if (ecode < 0 || ecode > EAI_MAX)
+ ecode = EAI_MAX;
+ return ai_errlist[ecode];
+}
+
+void
+freeaddrinfo(ai)
+ struct addrinfo *ai;
+{
+ struct addrinfo *next;
+
+ do {
+ next = ai->ai_next;
+ if (ai->ai_canonname)
+ free(ai->ai_canonname);
+ /* no need to free(ai->ai_addr) */
+ free(ai);
+ } while ((ai = next) != NULL);
+}
+
+static int
+str_isnumber(p)
+ const char *p;
+{
+ char *q = (char *)p;
+ while (*q) {
+ if (! isdigit(*q))
+ return NO;
+ q++;
+ }
+ return YES;
+}
+
+int
+getaddrinfo(hostname, servname, hints, res)
+ const char *hostname, *servname;
+ const struct addrinfo *hints;
+ struct addrinfo **res;
+{
+ struct addrinfo sentinel;
+ struct addrinfo *cur;
+ int error = 0;
+ struct addrinfo ai;
+ struct addrinfo ai0;
+ struct addrinfo *pai;
+ const struct afd *afd;
+ const struct explore *ex;
+
+ sentinel.ai_next = NULL;
+ cur = &sentinel;
+ pai = &ai;
+ pai->ai_flags = 0;
+ pai->ai_family = PF_UNSPEC;
+ pai->ai_socktype = ANY;
+ pai->ai_protocol = ANY;
+ pai->ai_addrlen = 0;
+ pai->ai_canonname = NULL;
+ pai->ai_addr = NULL;
+ pai->ai_next = NULL;
+
+ if (hostname == NULL && servname == NULL)
+ return EAI_NONAME;
+ if (res == NULL)
+ return EAI_RESNULL; /* xxx */
+ if (hints) {
+ /* error check for hints */
+ if (hints->ai_addrlen || hints->ai_canonname ||
+ hints->ai_addr || hints->ai_next)
+ ERR(EAI_BADHINTS); /* xxx */
+ if (hints->ai_flags & ~AI_MASK)
+ ERR(EAI_BADFLAGS);
+ switch (hints->ai_family) {
+ case PF_UNSPEC:
+ case PF_INET:
+#ifdef INET6
+ case PF_INET6:
+#endif
+ break;
+ default:
+ ERR(EAI_FAMILY);
+ }
+ memcpy(pai, hints, sizeof(*pai));
+
+ /*
+ * if both socktype/protocol are specified, check if they
+ * are meaningful combination.
+ */
+ if (pai->ai_socktype != ANY && pai->ai_protocol != ANY) {
+ int matched = 0;
+
+ for (ex = explore; ex->e_af >= 0; ex++) {
+ if (pai->ai_family != ex->e_af)
+ continue;
+ if (ex->e_socktype == ANY)
+ continue;
+ if (ex->e_protocol == ANY)
+ continue;
+ if (pai->ai_socktype == ex->e_socktype
+ && pai->ai_protocol == ex->e_protocol)
+ matched = 1;
+ else
+ continue;
+ if (matched == 0)
+ ERR(EAI_BADHINTS);
+ }
+ }
+ }
+
+ /* backup original pai contents */
+ ai0 = *pai;
+
+ /*
+ * special cases check for inet and inet6 sockets.
+ * (1) servname is disallowed for raw sockets.
+ * (2) numeric servname is disallowed if socktype/protocol is left
+ * unspecified.
+ */
+ if (MATCH_FAMILY(pai->ai_family, PF_INET, 1)
+#ifdef INET6
+ || MATCH_FAMILY(pai->ai_family, PF_INET6, 1)
+#endif
+ ) {
+ *pai = ai0;
+
+ if (pai->ai_family == PF_UNSPEC)
+#ifdef INET6
+ pai->ai_family = PF_INET6;
+#else
+ pai->ai_family = PF_INET;
+#endif
+ error = get_portmatch(pai, servname);
+ if (error)
+ ERR(error);
+ }
+
+ /* NULL hostname, or numeric hostname */
+ for (ex = explore; ex->e_af >= 0; ex++) {
+ *pai = ai0;
+
+ if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex)))
+ continue;
+ if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex)))
+ continue;
+ if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex)))
+ continue;
+
+ if (pai->ai_family == PF_UNSPEC)
+ pai->ai_family = ex->e_af;
+ if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
+ pai->ai_socktype = ex->e_socktype;
+ if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
+ pai->ai_protocol = ex->e_protocol;
+
+ if (hostname == NULL)
+ error = explore_null(pai, hostname, servname, &cur->ai_next);
+ else
+ error = explore_numeric_scope(pai, hostname, servname, &cur->ai_next);
+
+ if (error)
+ goto free;
+
+ while (cur && cur->ai_next)
+ cur = cur->ai_next;
+ }
+
+ /*
+ * XXX
+ * If numreic representation of AF1 can be interpreted as FQDN
+ * representation of AF2, we need to think again about the code below.
+ */
+ if (sentinel.ai_next)
+ goto good;
+
+ if (pai->ai_flags & AI_NUMERICHOST)
+ ERR(EAI_NONAME);
+ if (hostname == NULL)
+ ERR(EAI_NONAME);
+
+ /*
+ * hostname as alphabetical name.
+ * we would like to prefer AF_INET6 than AF_INET, so we'll make a
+ * outer loop by AFs.
+ */
+ for (afd = afdl; afd->a_af; afd++) {
+ *pai = ai0;
+
+ if (!MATCH_FAMILY(pai->ai_family, afd->a_af, 1))
+ continue;
+
+ for (ex = explore; ex->e_af >= 0; ex++) {
+ *pai = ai0;
+
+ if (pai->ai_family == PF_UNSPEC)
+ pai->ai_family = afd->a_af;
+
+ if (!MATCH_FAMILY(pai->ai_family, ex->e_af,
+ WILD_AF(ex)))
+ continue;
+ if (!MATCH(pai->ai_socktype, ex->e_socktype,
+ WILD_SOCKTYPE(ex))) {
+ continue;
+ }
+ if (!MATCH(pai->ai_protocol, ex->e_protocol,
+ WILD_PROTOCOL(ex))) {
+ continue;
+ }
+
+ if (pai->ai_family == PF_UNSPEC)
+ pai->ai_family = ex->e_af;
+ if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
+ pai->ai_socktype = ex->e_socktype;
+ if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
+ pai->ai_protocol = ex->e_protocol;
+
+ error = explore_fqdn(pai, hostname, servname,
+ &cur->ai_next);
+
+ while (cur && cur->ai_next)
+ cur = cur->ai_next;
+ }
+ }
+
+ /* XXX: if any addrinfo found, SUCCESS return even if (error != 0) */
+ if (sentinel.ai_next) {
+ good:
+ *res = sentinel.ai_next;
+ return SUCCESS;
+ }
+ /* else, failed */
+ free:
+ bad:
+ if (error == 0)
+ error = EAI_FAIL;
+ if (sentinel.ai_next)
+ freeaddrinfo(sentinel.ai_next);
+ *res = NULL;
+ return error;
+}
+
+/*
+ * FQDN hostname, DNS lookup
+ */
+static int
+explore_fqdn(pai, hostname, servname, res)
+ const struct addrinfo *pai;
+ const char *hostname;
+ const char *servname;
+ struct addrinfo **res;
+{
+ int s;
+ struct hostent *hp;
+ int h_error;
+ int af;
+ char *ap;
+ struct addrinfo sentinel, *cur;
+ int i;
+ const struct afd *afd;
+ int error;
+
+ *res = NULL;
+ sentinel.ai_next = NULL;
+ cur = &sentinel;
+
+ /*
+ * filter out AFs that are not supported by the kernel
+ * XXX errno?
+ */
+ s = socket(pai->ai_family, SOCK_DGRAM, 0);
+ if (s < 0)
+ return 0;
+ close(s);
+
+ /*
+ * if the servname does not match socktype/protocol, ignore it.
+ */
+ if (get_portmatch(pai, servname) != 0)
+ return 0;
+
+ afd = find_afd(pai->ai_family);
+ if (afd == NULL)
+ return 0;
+
+ hp = getipnodebyname(hostname, pai->ai_family, AI_ADDRCONFIG,
+ &h_error);
+ if (hp == NULL) {
+ switch (h_error) {
+ case HOST_NOT_FOUND:
+ case NO_DATA:
+ error = EAI_NODATA;
+ break;
+ case TRY_AGAIN:
+ error = EAI_AGAIN;
+ break;
+ case NO_RECOVERY:
+ case NETDB_INTERNAL:
+ default:
+ error = EAI_FAIL;
+ break;
+ }
+ } else if ((hp->h_name == NULL) || (hp->h_name[0] == 0)
+ || (hp->h_addr_list[0] == NULL)) {
+ freehostent(hp);
+ hp = NULL;
+ error = EAI_FAIL;
+ }
+
+ if (hp == NULL)
+ goto free;
+
+ for (i = 0; hp->h_addr_list[i] != NULL; i++) {
+ af = hp->h_addrtype;
+ ap = hp->h_addr_list[i];
+
+ if (af != pai->ai_family)
+ continue;
+
+ if ((pai->ai_flags & AI_CANONNAME) == 0) {
+ GET_AI(cur->ai_next, afd, ap);
+ GET_PORT(cur->ai_next, servname);
+ } else {
+ /*
+ * if AI_CANONNAME and if reverse lookup
+ * fail, return ai anyway to pacify
+ * calling application.
+ *
+ * XXX getaddrinfo() is a name->address
+ * translation function, and it looks
+ * strange that we do addr->name
+ * translation here.
+ */
+ get_name(ap, afd, &cur->ai_next,
+ ap, pai, servname);
+ }
+
+ while (cur && cur->ai_next)
+ cur = cur->ai_next;
+ }
+
+ *res = sentinel.ai_next;
+ return 0;
+
+free:
+ if (hp)
+ freehostent(hp);
+ if (sentinel.ai_next)
+ freeaddrinfo(sentinel.ai_next);
+ return error;
+}
+
+/*
+ * hostname == NULL.
+ * passive socket -> anyaddr (0.0.0.0 or ::)
+ * non-passive socket -> localhost (127.0.0.1 or ::1)
+ */
+static int
+explore_null(pai, hostname, servname, res)
+ const struct addrinfo *pai;
+ const char *hostname;
+ const char *servname;
+ struct addrinfo **res;
+{
+ int s;
+ const struct afd *afd;
+ struct addrinfo *cur;
+ struct addrinfo sentinel;
+ int error;
+
+ *res = NULL;
+ sentinel.ai_next = NULL;
+ cur = &sentinel;
+
+ /*
+ * filter out AFs that are not supported by the kernel
+ * XXX errno?
+ */
+ s = socket(pai->ai_family, SOCK_DGRAM, 0);
+ if (s < 0)
+ return 0;
+ close(s);
+ afd = find_afd(pai->ai_family);
+ if (afd == NULL)
+ return 0;
+
+ GET_AI(cur->ai_next, afd,
+ (pai->ai_flags & AI_PASSIVE) ? afd->a_addrany : afd->a_loopback
+ );
+ /* xxx meaningless?
+ * GET_CANONNAME(cur->ai_next, "anyaddr");
+ * or
+ * GET_CANONNAME(cur->ai_next, "localhost");
+ */
+ /* if the servname does not match socktype/protocol, ignored */
+ GET_PORT(cur->ai_next, servname);
+
+ *res = sentinel.ai_next;
+ return 0;
+
+free:
+ if (sentinel.ai_next)
+ freeaddrinfo(sentinel.ai_next);
+ return error;
+}
+
+/*
+ * numeric hostname
+ */
+static int
+explore_numeric(pai, hostname, servname, res)
+ const struct addrinfo *pai;
+ const char *hostname;
+ const char *servname;
+ struct addrinfo **res;
+{
+ const struct afd *afd;
+ struct addrinfo *cur;
+ struct addrinfo sentinel;
+ int error;
+ char pton[PTON_MAX];
+ int flags;
+
+ *res = NULL;
+ sentinel.ai_next = NULL;
+ cur = &sentinel;
+
+ /*
+ * if the servname does not match socktype/protocol, ignore it.
+ */
+ if (get_portmatch(pai, servname) != 0)
+ return 0;
+
+ afd = find_afd(pai->ai_family);
+ if (afd == NULL)
+ return 0;
+ flags = pai->ai_flags;
+
+ if (inet_pton(afd->a_af, hostname, pton) == 1) {
+ u_int32_t v4a;
+#ifdef INET6
+ struct in6_addr * v6a;
+#endif
+
+ switch (afd->a_af) {
+ case AF_INET:
+ v4a = (u_int32_t)ntohl(((struct in_addr *)pton)->s_addr);
+ if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
+ flags &= ~AI_CANONNAME;
+ v4a >>= IN_CLASSA_NSHIFT;
+ if (v4a == 0 || v4a == IN_LOOPBACKNET)
+ flags &= ~AI_CANONNAME;
+ break;
+#ifdef INET6
+ case AF_INET6:
+ v6a = (struct in6_addr *)pton;
+ if (IN6_IS_ADDR_MULTICAST(v6a))
+ flags &= ~AI_CANONNAME;
+ if (IN6_IS_ADDR_UNSPECIFIED(v6a) ||
+ IN6_IS_ADDR_LOOPBACK(v6a))
+ flags &= ~AI_CANONNAME;
+ if (IN6_IS_ADDR_LINKLOCAL(v6a))
+ flags &= ~AI_CANONNAME;
+
+ /* should also do this for SITELOCAL ?? */
+
+ break;
+#endif
+ }
+
+ if (pai->ai_family == afd->a_af ||
+ pai->ai_family == PF_UNSPEC /*?*/) {
+ if ((flags & AI_CANONNAME) == 0) {
+ GET_AI(cur->ai_next, afd, pton);
+ GET_PORT(cur->ai_next, servname);
+ } else {
+ /*
+ * if AI_CANONNAME and if reverse lookup
+ * fail, return ai anyway to pacify
+ * calling application.
+ *
+ * XXX getaddrinfo() is a name->address
+ * translation function, and it looks
+ * strange that we do addr->name
+ * translation here.
+ */
+ get_name(pton, afd, &cur->ai_next,
+ pton, pai, servname);
+ }
+ while (cur && cur->ai_next)
+ cur = cur->ai_next;
+ } else
+ ERR(EAI_FAMILY); /*xxx*/
+ }
+
+ *res = sentinel.ai_next;
+ return 0;
+
+free:
+bad:
+ if (sentinel.ai_next)
+ freeaddrinfo(sentinel.ai_next);
+ return error;
+}
+
+/*
+ * numeric hostname with scope
+ */
+static int
+explore_numeric_scope(pai, hostname, servname, res)
+ const struct addrinfo *pai;
+ const char *hostname;
+ const char *servname;
+ struct addrinfo **res;
+{
+#ifndef SCOPE_DELIMITER
+ return explore_numeric(pai, hostname, servname, res);
+#else
+ const struct afd *afd;
+ struct addrinfo *cur;
+ int error;
+ char *cp, *hostname2 = NULL;
+ int scope;
+#ifdef INET6
+ struct sockaddr_in6 *sin6;
+#endif
+
+ /*
+ * if the servname does not match socktype/protocol, ignore it.
+ */
+ if (get_portmatch(pai, servname) != 0)
+ return 0;
+
+ afd = find_afd(pai->ai_family);
+ if (afd == NULL)
+ return 0;
+ if (!afd->a_scoped)
+ return explore_numeric(pai, hostname, servname, res);
+
+ cp = strchr(hostname, SCOPE_DELIMITER);
+ if (cp == NULL)
+ return explore_numeric(pai, hostname, servname, res);
+
+ /*
+ * Handle special case of <scoped_address><delimiter><scope id>
+ */
+ hostname2 = strdup(hostname);
+ if (hostname2 == NULL)
+ return EAI_MEMORY;
+ /* terminate at the delimiter */
+ hostname2[cp - hostname] = '\0';
+
+ cp++;
+ switch (pai->ai_family) {
+#ifdef INET6
+ case AF_INET6:
+ scope = if_nametoindex(cp);
+ if (scope == 0) {
+ error = EAI_SYSTEM;
+ goto free;
+ }
+ break;
+#endif
+ }
+
+ error = explore_numeric(pai, hostname2, servname, res);
+ if (error == 0) {
+ for (cur = *res; cur; cur = cur->ai_next) {
+#ifdef INET6
+ if (cur->ai_family != AF_INET6)
+ continue;
+ sin6 = (struct sockaddr_in6 *)cur->ai_addr;
+ if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) ||
+ IN6_IS_ADDR_MC_LINKLOCAL(&sin6->sin6_addr))
+ sin6->sin6_scope_id = scope;
+#endif
+ }
+ }
+
+#ifdef INET6
+free:
+#endif
+ free(hostname2);
+
+ return error;
+#endif
+}
+
+static int
+get_name(addr, afd, res, numaddr, pai, servname)
+ const char *addr;
+ const struct afd *afd;
+ struct addrinfo **res;
+ char *numaddr;
+ const struct addrinfo *pai;
+ const char *servname;
+{
+ struct hostent *hp;
+ struct addrinfo *cur;
+ int error = 0;
+ int h_error;
+
+ hp = getipnodebyaddr(addr, afd->a_addrlen, afd->a_af, &h_error);
+ if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) {
+ if (hp->h_addrtype == afd->a_af)
+ GET_AI(cur, afd, hp->h_addr_list[0]);
+ else /* IPv4 mapped IPv6 addr case */
+ GET_AI(cur, afd, numaddr);
+ GET_PORT(cur, servname);
+ GET_CANONNAME(cur, hp->h_name);
+ } else {
+ GET_AI(cur, afd, numaddr);
+ GET_PORT(cur, servname);
+ }
+
+ if (hp)
+ freehostent(hp);
+ *res = cur;
+ return SUCCESS;
+ free:
+ if (cur)
+ freeaddrinfo(cur);
+ if (hp)
+ freehostent(hp);
+ /* bad: */
+ *res = NULL;
+ return error;
+}
+
+static int
+get_canonname(pai, ai, str)
+ const struct addrinfo *pai;
+ struct addrinfo *ai;
+ const char *str;
+{
+ if ((pai->ai_flags & AI_CANONNAME) != 0) {
+ ai->ai_canonname = (char *)malloc(strlen(str) + 1);
+ if (ai->ai_canonname == NULL)
+ return EAI_MEMORY;
+ strcpy(ai->ai_canonname, str);
+ }
+ return 0;
+}
+
+static struct addrinfo *
+get_ai(pai, afd, addr)
+ const struct addrinfo *pai;
+ const struct afd *afd;
+ const char *addr;
+{
+ char *p;
+ struct addrinfo *ai;
+#ifdef FAITH
+ struct in6_addr faith_prefix;
+ char *fp_str;
+ int translate = 0;
+#endif
+
+#ifdef FAITH
+ /*
+ * Transfrom an IPv4 addr into a special IPv6 addr format for
+ * IPv6->IPv4 translation gateway. (only TCP is supported now)
+ *
+ * +-----------------------------------+------------+
+ * | faith prefix part (12 bytes) | embedded |
+ * | | IPv4 addr part (4 bytes)
+ * +-----------------------------------+------------+
+ *
+ * faith prefix part is specified as ascii IPv6 addr format
+ * in environmental variable GAI.
+ * For FAITH to work correctly, routing to faith prefix must be
+ * setup toward a machine where a FAITH daemon operates.
+ * Also, the machine must enable some mechanizm
+ * (e.g. faith interface hack) to divert those packet with
+ * faith prefixed destination addr to user-land FAITH daemon.
+ */
+ fp_str = getenv("GAI");
+ if (fp_str && inet_pton(AF_INET6, fp_str, &faith_prefix) == 1 &&
+ afd->a_af == AF_INET && pai->ai_socktype == SOCK_STREAM) {
+ u_int32_t v4a;
+ u_int8_t v4a_top;
+
+ memcpy(&v4a, addr, sizeof v4a);
+ v4a_top = v4a >> IN_CLASSA_NSHIFT;
+ if (!IN_MULTICAST(v4a) && !IN_EXPERIMENTAL(v4a) &&
+ v4a_top != 0 && v4a != IN_LOOPBACKNET) {
+ afd = &afdl[N_INET6];
+ memcpy(&faith_prefix.s6_addr[12], addr,
+ sizeof(struct in_addr));
+ translate = 1;
+ }
+ }
+#endif
+
+ ai = (struct addrinfo *)malloc(sizeof(struct addrinfo)
+ + (afd->a_socklen));
+ if (ai == NULL)
+ return NULL;
+
+ memcpy(ai, pai, sizeof(struct addrinfo));
+ ai->ai_addr = (struct sockaddr *)(ai + 1);
+ memset(ai->ai_addr, 0, afd->a_socklen);
+ ai->ai_addr->sa_len = afd->a_socklen;
+ ai->ai_addrlen = afd->a_socklen;
+ ai->ai_addr->sa_family = ai->ai_family = afd->a_af;
+ p = (char *)(ai->ai_addr);
+#ifdef FAITH
+ if (translate == 1)
+ memcpy(p + afd->a_off, &faith_prefix, afd->a_addrlen);
+ else
+#endif
+ memcpy(p + afd->a_off, addr, afd->a_addrlen);
+
+ return ai;
+}
+
+static int
+get_portmatch(ai, servname)
+ const struct addrinfo *ai;
+ const char *servname;
+{
+ /* get_port does not touch first argument. when matchonly == 1. */
+ return get_port((struct addrinfo *)ai, servname, 1);
+}
+
+static int
+get_port(ai, servname, matchonly)
+ struct addrinfo *ai;
+ const char *servname;
+ int matchonly;
+{
+ const char *proto;
+ struct servent *sp;
+ int port;
+ int allownumeric;
+
+ if (servname == NULL)
+ return 0;
+ if (ai->ai_family != AF_INET
+#ifdef INET6
+ && ai->ai_family != AF_INET6
+#endif
+ )
+ return 0;
+
+ switch (ai->ai_socktype) {
+ case SOCK_RAW:
+ return EAI_SERVICE;
+ case SOCK_DGRAM:
+ case SOCK_STREAM:
+ allownumeric = 1;
+ break;
+ case ANY:
+ allownumeric = 0;
+ break;
+ default:
+ return EAI_SOCKTYPE;
+ }
+
+ if (str_isnumber(servname)) {
+ if (!allownumeric)
+ return EAI_SERVICE;
+ port = htons(atoi(servname));
+ if (port < 0 || port > 65535)
+ return EAI_SERVICE;
+ } else {
+ switch (ai->ai_socktype) {
+ case SOCK_DGRAM:
+ proto = "udp";
+ break;
+ case SOCK_STREAM:
+ proto = "tcp";
+ break;
+ default:
+ proto = NULL;
+ break;
+ }
+
+ if ((sp = getservbyname(servname, proto)) == NULL)
+ return EAI_SERVICE;
+ port = sp->s_port;
+ }
+
+ if (!matchonly) {
+ switch (ai->ai_family) {
+ case AF_INET:
+ ((struct sockaddr_in *)ai->ai_addr)->sin_port = port;
+ break;
+#ifdef INET6
+ case AF_INET6:
+ ((struct sockaddr_in6 *)ai->ai_addr)->sin6_port = port;
+ break;
+#endif
+ }
+ }
+
+ return 0;
+}
+
+static const struct afd *
+find_afd(af)
+ int af;
+{
+ const struct afd *afd;
+
+ if (af == PF_UNSPEC)
+ return NULL;
+ for (afd = afdl; afd->a_af; afd++) {
+ if (afd->a_af == af)
+ return afd;
+ }
+ return NULL;
+}
diff --git a/security/openssh/files/getnameinfo.c b/security/openssh/files/getnameinfo.c
new file mode 100644
index 000000000000..67f2ea77fd81
--- /dev/null
+++ b/security/openssh/files/getnameinfo.c
@@ -0,0 +1,228 @@
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: /tmp/pcvs/ports/security/openssh/files/Attic/getnameinfo.c,v 1.1 2000-01-13 23:22:12 green Exp $
+ */
+
+/*
+ * Issues to be discussed:
+ * - Thread safe-ness must be checked
+ * - Return values. There seems to be no standard for return value (RFC2553)
+ * but INRIA implementation returns EAI_xxx defined for getaddrinfo().
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <string.h>
+#include <stddef.h>
+
+#define SUCCESS 0
+#define ANY 0
+#define YES 1
+#define NO 0
+
+static struct afd {
+ int a_af;
+ int a_addrlen;
+ int a_socklen;
+ int a_off;
+} afdl [] = {
+#ifdef INET6
+ {PF_INET6, sizeof(struct in6_addr), sizeof(struct sockaddr_in6),
+ offsetof(struct sockaddr_in6, sin6_addr)},
+#endif
+ {PF_INET, sizeof(struct in_addr), sizeof(struct sockaddr_in),
+ offsetof(struct sockaddr_in, sin_addr)},
+ {0, 0, 0},
+};
+
+struct sockinet {
+ u_char si_len;
+ u_char si_family;
+ u_short si_port;
+};
+
+#define ENI_NOSOCKET 0
+#define ENI_NOSERVHOST 1
+#define ENI_NOHOSTNAME 2
+#define ENI_MEMORY 3
+#define ENI_SYSTEM 4
+#define ENI_FAMILY 5
+#define ENI_SALEN 6
+
+int
+getnameinfo(sa, salen, host, hostlen, serv, servlen, flags)
+ const struct sockaddr *sa;
+ size_t salen;
+ char *host;
+ size_t hostlen;
+ char *serv;
+ size_t servlen;
+ int flags;
+{
+ struct afd *afd;
+ struct servent *sp;
+ struct hostent *hp;
+ u_short port;
+ int family, i;
+ char *addr, *p;
+ u_long v4a;
+ int h_error;
+ char numserv[512];
+ char numaddr[512];
+ int noserv = 0;
+
+ if (sa == NULL)
+ return ENI_NOSOCKET;
+
+ if (sa->sa_len != salen)
+ return ENI_SALEN;
+
+ family = sa->sa_family;
+ for (i = 0; afdl[i].a_af; i++)
+ if (afdl[i].a_af == family) {
+ afd = &afdl[i];
+ goto found;
+ }
+ return ENI_FAMILY;
+
+ found:
+ if (salen != afd->a_socklen)
+ return ENI_SALEN;
+
+ port = ((struct sockinet *)sa)->si_port; /* network byte order */
+ addr = (char *)sa + afd->a_off;
+
+ if (serv == NULL || servlen == 0) {
+ noserv = 1;
+ } else {
+ if (flags & NI_NUMERICSERV)
+ sp = NULL;
+ else {
+ sp = getservbyport(port,
+ (flags & NI_DGRAM) ? "udp" : "tcp");
+ }
+ if (sp) {
+ if (strlen(sp->s_name) > servlen)
+ return ENI_MEMORY;
+ strcpy(serv, sp->s_name);
+ } else {
+ snprintf(numserv, sizeof(numserv), "%d", ntohs(port));
+ if (strlen(numserv) > servlen)
+ return ENI_MEMORY;
+ strcpy(serv, numserv);
+ }
+ }
+
+ switch (sa->sa_family) {
+ case AF_INET:
+ v4a = ntohl(((struct sockaddr_in *)sa)->sin_addr.s_addr);
+ if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
+ flags |= NI_NUMERICHOST;
+ v4a >>= IN_CLASSA_NSHIFT;
+ if (v4a == 0 || v4a == IN_LOOPBACKNET)
+ flags |= NI_NUMERICHOST;
+ break;
+#ifdef INET6
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *sin6;
+ sin6 = (struct sockaddr_in6 *)sa;
+ if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) ||
+ IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
+ flags |= NI_NUMERICHOST;
+ }
+ break;
+#endif
+ }
+ if (host == NULL || hostlen == 0) {
+ if (noserv == 1)
+ return ENI_NOSERVHOST;
+ } else if (flags & NI_NUMERICHOST) {
+ /* NUMERICHOST and NAMEREQD conflicts with each other */
+ if (flags & NI_NAMEREQD)
+ return ENI_NOHOSTNAME;
+ if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
+ == NULL)
+ return ENI_SYSTEM;
+ if (strlen(numaddr) > hostlen)
+ return ENI_MEMORY;
+ strcpy(host, numaddr);
+#ifdef INET6
+ if (afd->a_af == AF_INET6 &&
+ (IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)addr) ||
+ IN6_IS_ADDR_MULTICAST((struct in6_addr *)addr)) &&
+ ((struct sockaddr_in6 *)sa)->sin6_scope_id) {
+ if (flags & NI_WITHSCOPEID) {
+ char *ep = strchr(host, '\0');
+ unsigned int ifindex =
+ ((struct sockaddr_in6 *)sa)->sin6_scope_id;
+ char ifname[IF_NAMESIZE * 2 /* for safety */];
+
+ if ((if_indextoname(ifindex, ifname)) == NULL)
+ return ENI_SYSTEM;
+ if (strlen(host) + 1 /* SCOPE_DELIMITER */
+ + strlen(ifname) > hostlen)
+ return ENI_MEMORY;
+ *ep = SCOPE_DELIMITER;
+ strcpy(ep + 1, ifname);
+ }
+ }
+#endif /* INET6 */
+ } else {
+ hp = getipnodebyaddr(addr, afd->a_addrlen, afd->a_af, &h_error);
+ if (hp) {
+ if (flags & NI_NOFQDN) {
+ p = strchr(hp->h_name, '.');
+ if (p) *p = '\0';
+ }
+ if (strlen(hp->h_name) > hostlen) {
+ freehostent(hp);
+ return ENI_MEMORY;
+ }
+ strcpy(host, hp->h_name);
+ freehostent(hp);
+ } else {
+ if (flags & NI_NAMEREQD)
+ return ENI_NOHOSTNAME;
+ if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
+ == NULL)
+ return ENI_NOHOSTNAME;
+ if (strlen(numaddr) > hostlen)
+ return ENI_MEMORY;
+ strcpy(host, numaddr);
+ }
+ }
+ return SUCCESS;
+}
diff --git a/security/openssh/files/name6.c b/security/openssh/files/name6.c
new file mode 100644
index 000000000000..978796ad15b4
--- /dev/null
+++ b/security/openssh/files/name6.c
@@ -0,0 +1,1262 @@
+/*
+ * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: /tmp/pcvs/ports/security/openssh/files/Attic/name6.c,v 1.1 2000-01-13 23:22:13 green Exp $
+ */
+/* $Id: name6.c,v 1.9 1999/10/29 03:04:26 itojun Exp $ */
+/*
+ * Atsushi Onoe <onoe@sm.sony.co.jp>
+ */
+
+/*
+ * TODO for thread safe
+ * use mutex for _hostconf, _hostconf_init.
+ * rewrite resolvers to be thread safe
+ */
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <netdb.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifndef _PATH_HOSTS
+#define _PATH_HOSTS "/etc/hosts"
+#endif
+
+#ifndef MAXALIASES
+#define MAXALIASES 10
+#endif
+#ifndef MAXADDRS
+#define MAXADDRS 20
+#endif
+#ifndef MAXDNAME
+#define MAXDNAME 1025
+#endif
+
+#ifdef INET6
+#define ADDRLEN(af) ((af) == AF_INET6 ? sizeof(struct in6_addr) : \
+ sizeof(struct in_addr))
+#else
+#define ADDRLEN(af) sizeof(struct in_addr)
+#endif
+
+#define MAPADDR(ab, ina) \
+do { \
+ memcpy(&(ab)->map_inaddr, ina, sizeof(struct in_addr)); \
+ memset((ab)->map_zero, 0, sizeof((ab)->map_zero)); \
+ memset((ab)->map_one, 0xff, sizeof((ab)->map_one)); \
+} while (0)
+#define MAPADDRENABLED(flags) \
+ (((flags) & AI_V4MAPPED) || \
+ (((flags) & AI_V4MAPPED_CFG) && _mapped_addr_enabled()))
+
+union inx_addr {
+ struct in_addr in_addr;
+#ifdef INET6
+ struct in6_addr in6_addr;
+#endif
+ struct {
+ u_char mau_zero[10];
+ u_char mau_one[2];
+ struct in_addr mau_inaddr;
+ } map_addr_un;
+#define map_zero map_addr_un.mau_zero
+#define map_one map_addr_un.mau_one
+#define map_inaddr map_addr_un.mau_inaddr
+};
+
+static struct hostent *_hpcopy(struct hostent *hp, int *errp);
+static struct hostent *_hpaddr(int af, const char *name, void *addr, int *errp);
+static struct hostent *_hpmerge(struct hostent *hp1, struct hostent *hp2, int *errp);
+#ifdef INET6
+static struct hostent *_hpmapv6(struct hostent *hp, int *errp);
+#endif
+static struct hostent *_hpsort(struct hostent *hp);
+static struct hostent *_ghbyname(const char *name, int af, int flags, int *errp);
+static char *_hgetword(char **pp);
+static int _mapped_addr_enabled(void);
+
+static FILE *_files_open(int *errp);
+static struct hostent *_files_ghbyname(const char *name, int af, int *errp);
+static struct hostent *_files_ghbyaddr(const void *addr, int addrlen, int af, int *errp);
+static void _files_shent(int stayopen);
+static void _files_ehent(void);
+static struct hostent *_dns_ghbyname(const char *name, int af, int *errp);
+static struct hostent *_dns_ghbyaddr(const void *addr, int addrlen, int af, int *errp);
+static void _dns_shent(int stayopen);
+static void _dns_ehent(void);
+#ifdef ICMPNL
+static struct hostent *_icmp_ghbyaddr(const void *addr, int addrlen, int af, int *errp);
+#endif /* ICMPNL */
+
+/*
+ * Select order host function.
+ */
+#define MAXHOSTCONF 4
+
+#ifndef HOSTCONF
+# define HOSTCONF "/etc/host.conf"
+#endif /* !HOSTCONF */
+
+struct _hostconf {
+ struct hostent *(*byname)(const char *name, int af, int *errp);
+ struct hostent *(*byaddr)(const void *addr, int addrlen, int af, int *errp);
+};
+
+/* default order */
+static struct _hostconf _hostconf[MAXHOSTCONF] = {
+ { _dns_ghbyname, _dns_ghbyaddr },
+ { _files_ghbyname, _files_ghbyaddr },
+#ifdef ICMPNL
+ { NULL, _icmp_ghbyaddr },
+#endif /* ICMPNL */
+};
+
+static int _hostconf_init_done;
+static void _hostconf_init(void);
+
+/*
+ * Initialize hostconf structure.
+ */
+
+static void
+_hostconf_init(void)
+{
+ FILE *fp;
+ int n;
+ char *p, *line;
+ char buf[BUFSIZ];
+
+ _hostconf_init_done = 1;
+ n = 0;
+ p = HOSTCONF;
+ if ((fp = fopen(p, "r")) == NULL)
+ return;
+ while (n < MAXHOSTCONF && fgets(buf, sizeof(buf), fp)) {
+ line = buf;
+ if ((p = _hgetword(&line)) == NULL)
+ continue;
+ do {
+ if (strcmp(p, "hosts") == 0
+ || strcmp(p, "local") == 0
+ || strcmp(p, "file") == 0
+ || strcmp(p, "files") == 0) {
+ _hostconf[n].byname = _files_ghbyname;
+ _hostconf[n].byaddr = _files_ghbyaddr;
+ n++;
+ }
+ else if (strcmp(p, "dns") == 0
+ || strcmp(p, "bind") == 0) {
+ _hostconf[n].byname = _dns_ghbyname;
+ _hostconf[n].byaddr = _dns_ghbyaddr;
+ n++;
+ }
+#ifdef ICMPNL
+ else if (strcmp(p, "icmp") == 0) {
+ _hostconf[n].byname = NULL;
+ _hostconf[n].byaddr = _icmp_ghbyaddr;
+ n++;
+ }
+#endif /* ICMPNL */
+ } while ((p = _hgetword(&line)) != NULL);
+ }
+ fclose(fp);
+ if (n < 0) {
+ /* no keyword found. do not change default configuration */
+ return;
+ }
+ for (; n < MAXHOSTCONF; n++) {
+ _hostconf[n].byname = NULL;
+ _hostconf[n].byaddr = NULL;
+ }
+}
+
+/*
+ * Check if kernel supports mapped address.
+ * implementation dependent
+ */
+#ifdef __KAME__
+#include <sys/sysctl.h>
+#endif /* __KAME__ */
+
+static int
+_mapped_addr_enabled(void)
+{
+ /* implementation dependent check */
+#if defined(__KAME__) && defined(IPV6CTL_MAPPED_ADDR)
+ int mib[4];
+ size_t len;
+ int val;
+
+ mib[0] = CTL_NET;
+ mib[1] = PF_INET6;
+ mib[2] = IPPROTO_IPV6;
+ mib[3] = IPV6CTL_MAPPED_ADDR;
+ len = sizeof(val);
+ if (sysctl(mib, 4, &val, &len, 0, 0) == 0 && val != 0)
+ return 1;
+#endif /* __KAME__ && IPV6CTL_MAPPED_ADDR */
+ return 0;
+}
+
+/*
+ * Functions defined in RFC2553
+ * getipnodebyname, getipnodebyadr, freehostent
+ */
+
+static struct hostent *
+_ghbyname(const char *name, int af, int flags, int *errp)
+{
+ struct hostent *hp;
+ int i;
+
+ if (flags & AI_ADDRCONFIG) {
+ int s;
+
+ if ((s = socket(af, SOCK_DGRAM, 0)) < 0)
+ return NULL;
+ /*
+ * TODO:
+ * Note that implementation dependent test for address
+ * configuration should be done everytime called
+ * (or apropriate interval),
+ * because addresses will be dynamically assigned or deleted.
+ */
+ close(s);
+ }
+
+ for (i = 0; i < MAXHOSTCONF; i++) {
+ if (_hostconf[i].byname
+ && (hp = (*_hostconf[i].byname)(name, af, errp))
+ != NULL)
+ return hp;
+ }
+
+ return NULL;
+}
+
+struct hostent *
+getipnodebyname(const char *name, int af, int flags, int *errp)
+{
+ struct hostent *hp;
+ union inx_addr addrbuf;
+
+ if (af != AF_INET
+#ifdef INET6
+ && af != AF_INET6
+#endif
+ )
+ {
+ *errp = NO_RECOVERY;
+ return NULL;
+ }
+
+#ifdef INET6
+ /* special case for literal address */
+ if (inet_pton(AF_INET6, name, &addrbuf) == 1) {
+ if (af != AF_INET6) {
+ *errp = HOST_NOT_FOUND;
+ return NULL;
+ }
+ return _hpaddr(af, name, &addrbuf, errp);
+ }
+#endif
+ if (inet_pton(AF_INET, name, &addrbuf) == 1) {
+ if (af != AF_INET) {
+ if (MAPADDRENABLED(flags)) {
+ MAPADDR(&addrbuf, &addrbuf.in_addr);
+ } else {
+ *errp = HOST_NOT_FOUND;
+ return NULL;
+ }
+ }
+ return _hpaddr(af, name, &addrbuf, errp);
+ }
+
+ if (!_hostconf_init_done)
+ _hostconf_init();
+
+ *errp = HOST_NOT_FOUND;
+ hp = _ghbyname(name, af, flags, errp);
+
+#ifdef INET6
+ if (af == AF_INET6
+ && ((flags & AI_ALL) || hp == NULL)
+ && (MAPADDRENABLED(flags))) {
+ struct hostent *hp2 = _ghbyname(name, AF_INET, flags, errp);
+ if (hp == NULL)
+ hp = _hpmapv6(hp2, errp);
+ else {
+ if (hp2 && strcmp(hp->h_name, hp2->h_name) != 0) {
+ freehostent(hp2);
+ hp2 = NULL;
+ }
+ hp = _hpmerge(hp, hp2, errp);
+ }
+ }
+#endif
+ return _hpsort(hp);
+}
+
+struct hostent *
+getipnodebyaddr(const void *src, size_t len, int af, int *errp)
+{
+ struct hostent *hp;
+ int i;
+#ifdef INET6
+ struct in6_addr addrbuf;
+#else
+ struct in_addr addrbuf;
+#endif
+
+ *errp = HOST_NOT_FOUND;
+
+ switch (af) {
+ case AF_INET:
+ if (len != sizeof(struct in_addr)) {
+ *errp = NO_RECOVERY;
+ return NULL;
+ }
+ if ((long)src & ~(sizeof(struct in_addr) - 1)) {
+ memcpy(&addrbuf, src, len);
+ src = &addrbuf;
+ }
+ if (((struct in_addr *)src)->s_addr == 0)
+ return NULL;
+ break;
+#ifdef INET6
+ case AF_INET6:
+ if (len != sizeof(struct in6_addr)) {
+ *errp = NO_RECOVERY;
+ return NULL;
+ }
+ if ((long)src & ~(sizeof(struct in6_addr) / 2 - 1)) { /*XXX*/
+ memcpy(&addrbuf, src, len);
+ src = &addrbuf;
+ }
+ if (IN6_IS_ADDR_UNSPECIFIED((struct in6_addr *)src))
+ return NULL;
+ if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)src)
+ || IN6_IS_ADDR_V4COMPAT((struct in6_addr *)src)) {
+ src = (char *)src +
+ (sizeof(struct in6_addr) - sizeof(struct in_addr));
+ af = AF_INET;
+ len = sizeof(struct in_addr);
+ }
+ break;
+#endif
+ default:
+ *errp = NO_RECOVERY;
+ return NULL;
+ }
+
+ if (!_hostconf_init_done)
+ _hostconf_init();
+ for (i = 0; i < MAXHOSTCONF; i++) {
+ if (_hostconf[i].byaddr
+ && (hp = (*_hostconf[i].byaddr)(src, len, af, errp)) != NULL)
+ return hp;
+ }
+
+ return NULL;
+}
+
+void
+freehostent(struct hostent *ptr)
+{
+ free(ptr);
+}
+
+#if 0
+
+/* XXX: should be deprecated */
+struct hostent *
+getnodebyname(const char *name, int af, int flags)
+{
+ return getipnodebyname(name, af, flags, &h_errno);
+}
+
+#ifdef __warn_references
+__warn_references(getnodebyname,
+ "warning: getnodebyname() deprecated, "
+ "should use getaddrinfo() or getipnodebyname()");
+#endif
+
+struct hostent *
+getnodebyaddr(const void *src, size_t len, int af)
+{
+ return getipnodebyaddr(src, len, af, &h_errno);
+}
+
+#ifdef __warn_references
+__warn_references(getnodebyaddr,
+ "warning: getnodebyaddr() deprecated, "
+ "should use getnameinfo() or getipnodebyaddr()");
+#endif
+
+#endif
+
+/*
+ * Private utility functions
+ */
+
+/*
+ * _hpcopy: allocate and copy hostent structure
+ */
+static struct hostent *
+_hpcopy(struct hostent *hp, int *errp)
+{
+ struct hostent *nhp;
+ char *cp, **pp;
+ int size, addrsize;
+ int nalias = 0, naddr = 0;
+ int al_off;
+ int i;
+
+ if (hp == NULL)
+ return hp;
+
+ /* count size to be allocated */
+ size = sizeof(struct hostent);
+ if (hp->h_name != NULL && *hp->h_name != '\0')
+ size += strlen(hp->h_name) + 1;
+ if ((pp = hp->h_aliases) != NULL) {
+ for (i = 0; *pp != NULL; i++, pp++) {
+ if (**pp != '\0') {
+ size += strlen(*pp) + 1;
+ nalias++;
+ }
+ }
+ }
+ /* adjust alignment */
+ size = ALIGN(size);
+ al_off = size;
+ size += sizeof(char *) * (nalias + 1);
+ addrsize = ALIGN(hp->h_length);
+ if ((pp = hp->h_addr_list) != NULL) {
+ while (*pp++ != NULL)
+ naddr++;
+ }
+ size += addrsize * naddr;
+ size += sizeof(char *) * (naddr + 1);
+
+ /* copy */
+ if ((nhp = (struct hostent *)malloc(size)) == NULL) {
+ *errp = TRY_AGAIN;
+ return NULL;
+ }
+ cp = (char *)&nhp[1];
+ if (hp->h_name != NULL && *hp->h_name != '\0') {
+ nhp->h_name = cp;
+ strcpy(cp, hp->h_name);
+ cp += strlen(cp) + 1;
+ } else
+ nhp->h_name = NULL;
+ nhp->h_aliases = (char **)((char *)nhp + al_off);
+ if ((pp = hp->h_aliases) != NULL) {
+ for (i = 0; *pp != NULL; pp++) {
+ if (**pp != '\0') {
+ nhp->h_aliases[i++] = cp;
+ strcpy(cp, *pp);
+ cp += strlen(cp) + 1;
+ }
+ }
+ }
+ nhp->h_aliases[nalias] = NULL;
+ cp = (char *)&nhp->h_aliases[nalias + 1];
+ nhp->h_addrtype = hp->h_addrtype;
+ nhp->h_length = hp->h_length;
+ nhp->h_addr_list = (char **)cp;
+ if ((pp = hp->h_addr_list) != NULL) {
+ cp = (char *)&nhp->h_addr_list[naddr + 1];
+ for (i = 0; *pp != NULL; pp++) {
+ nhp->h_addr_list[i++] = cp;
+ memcpy(cp, *pp, hp->h_length);
+ cp += addrsize;
+ }
+ }
+ nhp->h_addr_list[naddr] = NULL;
+ return nhp;
+}
+
+/*
+ * _hpaddr: construct hostent structure with one address
+ */
+static struct hostent *
+_hpaddr(int af, const char *name, void *addr, int *errp)
+{
+ struct hostent *hp, hpbuf;
+ char *addrs[2];
+
+ hp = &hpbuf;
+ hp->h_name = (char *)name;
+ hp->h_aliases = NULL;
+ hp->h_addrtype = af;
+ hp->h_length = ADDRLEN(af);
+ hp->h_addr_list = addrs;
+ addrs[0] = (char *)addr;
+ addrs[1] = NULL;
+ return _hpcopy(hp, errp);
+}
+
+/*
+ * _hpmerge: merge 2 hostent structure, arguments will be freed
+ */
+static struct hostent *
+_hpmerge(struct hostent *hp1, struct hostent *hp2, int *errp)
+{
+ int i, j;
+ int naddr, nalias;
+ char **pp;
+ struct hostent *hp, hpbuf;
+ char *aliases[MAXALIASES + 1], *addrs[MAXADDRS + 1];
+ union inx_addr addrbuf[MAXADDRS];
+
+ if (hp1 == NULL)
+ return hp2;
+ if (hp2 == NULL)
+ return hp1;
+
+#define HP(i) (i == 1 ? hp1 : hp2)
+ hp = &hpbuf;
+ hp->h_name = (hp1->h_name != NULL ? hp1->h_name : hp2->h_name);
+ hp->h_aliases = aliases;
+ nalias = 0;
+ for (i = 1; i <= 2; i++) {
+ if ((pp = HP(i)->h_aliases) == NULL)
+ continue;
+ for (; nalias < MAXALIASES && *pp != NULL; pp++) {
+ /* check duplicates */
+ for (j = 0; j < nalias; j++)
+ if (strcasecmp(*pp, aliases[j]) == 0)
+ break;
+ if (j == nalias)
+ aliases[nalias++] = *pp;
+ }
+ }
+ aliases[nalias] = NULL;
+#ifdef INET6
+ if (hp1->h_length != hp2->h_length) {
+ hp->h_addrtype = AF_INET6;
+ hp->h_length = sizeof(struct in6_addr);
+ } else {
+#endif
+ hp->h_addrtype = hp1->h_addrtype;
+ hp->h_length = hp1->h_length;
+#ifdef INET6
+ }
+#endif
+ hp->h_addr_list = addrs;
+ naddr = 0;
+ for (i = 1; i <= 2; i++) {
+ if ((pp = HP(i)->h_addr_list) == NULL)
+ continue;
+ if (HP(i)->h_length == hp->h_length) {
+ while (naddr < MAXADDRS && *pp != NULL)
+ addrs[naddr++] = *pp++;
+ } else {
+ /* copy IPv4 addr as mapped IPv6 addr */
+ while (naddr < MAXADDRS && *pp != NULL) {
+ MAPADDR(&addrbuf[naddr], *pp++);
+ addrs[naddr] = (char *)&addrbuf[naddr];
+ naddr++;
+ }
+ }
+ }
+ addrs[naddr] = NULL;
+ hp = _hpcopy(hp, errp);
+ freehostent(hp1);
+ freehostent(hp2);
+ return hp;
+}
+
+/*
+ * _hpmapv6: convert IPv4 hostent into IPv4-mapped IPv6 addresses
+ */
+#ifdef INET6
+static struct hostent *
+_hpmapv6(struct hostent *hp, int *errp)
+{
+ struct hostent *hp6;
+
+ if (hp == NULL)
+ return NULL;
+ if (hp->h_addrtype == AF_INET6)
+ return hp;
+
+ /* make dummy hostent to convert IPv6 address */
+ if ((hp6 = (struct hostent *)malloc(sizeof(struct hostent))) == NULL) {
+ *errp = TRY_AGAIN;
+ return NULL;
+ }
+ hp6->h_name = NULL;
+ hp6->h_aliases = NULL;
+ hp6->h_addrtype = AF_INET6;
+ hp6->h_length = sizeof(struct in6_addr);
+ hp6->h_addr_list = NULL;
+ return _hpmerge(hp6, hp, errp);
+}
+#endif
+
+/*
+ * _hpsort: sort address by sortlist
+ */
+static struct hostent *
+_hpsort(struct hostent *hp)
+{
+ int i, j, n;
+ u_char *ap, *sp, *mp, **pp;
+ char t;
+ char order[MAXADDRS];
+ int nsort = _res.nsort;
+
+ if (hp == NULL || hp->h_addr_list[1] == NULL || nsort == 0)
+ return hp;
+ for (i = 0; (ap = (u_char *)hp->h_addr_list[i]); i++) {
+ for (j = 0; j < nsort; j++) {
+#ifdef INET6
+ if (_res_ext.sort_list[j].af != hp->h_addrtype)
+ continue;
+ sp = (u_char *)&_res_ext.sort_list[j].addr;
+ mp = (u_char *)&_res_ext.sort_list[j].mask;
+#else
+ sp = (u_char *)&_res.sort_list[j].addr;
+ mp = (u_char *)&_res.sort_list[j].mask;
+#endif
+ for (n = 0; n < hp->h_length; n++) {
+ if ((ap[n] & mp[n]) != sp[n])
+ break;
+ }
+ if (n == hp->h_length)
+ break;
+ }
+ order[i] = j;
+ }
+ n = i;
+ pp = (u_char **)hp->h_addr_list;
+ for (i = 0; i < n - 1; i++) {
+ for (j = i + 1; j < n; j++) {
+ if (order[i] > order[j]) {
+ ap = pp[i];
+ pp[i] = pp[j];
+ pp[j] = ap;
+ t = order[i];
+ order[i] = order[j];
+ order[j] = t;
+ }
+ }
+ }
+ return hp;
+}
+
+static char *
+_hgetword(char **pp)
+{
+ char c, *p, *ret;
+ const char *sp;
+ static const char sep[] = "# \t\n";
+
+ ret = NULL;
+ for (p = *pp; (c = *p) != '\0'; p++) {
+ for (sp = sep; *sp != '\0'; sp++) {
+ if (c == *sp)
+ break;
+ }
+ if (c == '#')
+ p[1] = '\0'; /* ignore rest of line */
+ if (ret == NULL) {
+ if (*sp == '\0')
+ ret = p;
+ } else {
+ if (*sp != '\0') {
+ *p++ = '\0';
+ break;
+ }
+ }
+ }
+ *pp = p;
+ if (ret == NULL || *ret == '\0')
+ return NULL;
+ return ret;
+}
+
+/*
+ * FILES (/etc/hosts)
+ */
+
+static FILE *
+_files_open(int *errp)
+{
+ FILE *fp;
+ fp = fopen(_PATH_HOSTS, "r");
+ if (fp == NULL)
+ *errp = NO_RECOVERY;
+ return fp;
+}
+
+static struct hostent *
+_files_ghbyname(const char *name, int af, int *errp)
+{
+ int match, nalias;
+ char *p, *line, *addrstr, *cname;
+ FILE *fp;
+ struct hostent *rethp, *hp, hpbuf;
+ char *aliases[MAXALIASES + 1], *addrs[2];
+ union inx_addr addrbuf;
+ char buf[BUFSIZ];
+
+ if ((fp = _files_open(errp)) == NULL)
+ return NULL;
+ rethp = hp = NULL;
+
+ while (fgets(buf, sizeof(buf), fp)) {
+ line = buf;
+ if ((addrstr = _hgetword(&line)) == NULL
+ || (cname = _hgetword(&line)) == NULL)
+ continue;
+ match = (strcasecmp(cname, name) == 0);
+ nalias = 0;
+ while ((p = _hgetword(&line)) != NULL) {
+ if (!match)
+ match = (strcasecmp(p, name) == 0);
+ if (nalias < MAXALIASES)
+ aliases[nalias++] = p;
+ }
+ if (!match)
+ continue;
+ if (inet_pton(af, addrstr, &addrbuf) != 1) {
+ *errp = NO_DATA; /* name found */
+ continue;
+ }
+ hp = &hpbuf;
+ hp->h_name = cname;
+ hp->h_aliases = aliases;
+ aliases[nalias] = NULL;
+ hp->h_addrtype = af;
+ hp->h_length = ADDRLEN(af);
+ hp->h_addr_list = addrs;
+ addrs[0] = (char *)&addrbuf;
+ addrs[1] = NULL;
+ hp = _hpcopy(hp, errp);
+ rethp = _hpmerge(rethp, hp, errp);
+ }
+ fclose(fp);
+ return rethp;
+}
+
+static struct hostent *
+_files_ghbyaddr(const void *addr, int addrlen, int af, int *errp)
+{
+ int nalias;
+ char *p, *line;
+ FILE *fp;
+ struct hostent *hp, hpbuf;
+ char *aliases[MAXALIASES + 1], *addrs[2];
+ union inx_addr addrbuf;
+ char buf[BUFSIZ];
+
+ if ((fp = _files_open(errp)) == NULL)
+ return NULL;
+ hp = NULL;
+ while (fgets(buf, sizeof(buf), fp)) {
+ line = buf;
+ if ((p = _hgetword(&line)) == NULL
+ || inet_pton(af, p, &addrbuf) != 1
+ || memcmp(addr, &addrbuf, addrlen) != 0
+ || (p = _hgetword(&line)) == NULL)
+ continue;
+ hp = &hpbuf;
+ hp->h_name = p;
+ hp->h_aliases = aliases;
+ nalias = 0;
+ while ((p = _hgetword(&line)) != NULL) {
+ if (nalias < MAXALIASES)
+ aliases[nalias++] = p;
+ }
+ aliases[nalias] = NULL;
+ hp->h_addrtype = af;
+ hp->h_length = addrlen;
+ hp->h_addr_list = addrs;
+ addrs[0] = (char *)&addrbuf;
+ addrs[1] = NULL;
+ hp = _hpcopy(hp, errp);
+ break;
+ }
+ fclose(fp);
+ return hp;
+}
+
+#ifdef DEBUG
+#define DNS_ASSERT(X) if (!(X)) { fprintf(stderr, "ASSFAIL: %s %d: %s\n", __FILE__, __LINE__, #X); goto badanswer; }
+#else
+#define DNS_ASSERT(X) if (!(X)) { goto badanswer; }
+#endif
+
+static struct hostent *
+_dns_ghbyname(const char *name, int af, int *errp)
+{
+ int n;
+ u_char answer[BUFSIZ];
+ char tbuf[MAXDNAME+1];
+ HEADER *hp;
+ u_char *cp, *eom;
+ int qtype;
+ int type, class, ancount, qdcount;
+ u_long ttl;
+ char hostbuf[BUFSIZ];
+ char *bp;
+ char *alist[MAXALIASES];
+ char *hlist[MAXADDRS];
+ struct hostent hbuf;
+ int buflen;
+ int na, nh;
+
+ if ((_res.options & RES_INIT) == 0) {
+ if (res_init() < 0) {
+ *errp = h_errno;
+ return NULL;
+ }
+ }
+ hbuf.h_aliases = alist;
+ hbuf.h_addrtype = af;
+ hbuf.h_length = ADDRLEN(af);
+ hbuf.h_addr_list = hlist;
+ na = nh = 0;
+
+#ifdef INET6
+ qtype = (af == AF_INET6 ? T_AAAA : T_A);
+#else
+ qtype = T_A;
+#endif
+ n = res_search(name, C_IN, qtype, answer, sizeof(answer));
+ if (n < 0) {
+ *errp = h_errno;
+ return NULL;
+ }
+ hp = (HEADER *)answer;
+ eom = answer + n;
+ ancount = ntohs(hp->ancount);
+ qdcount = ntohs(hp->qdcount);
+ DNS_ASSERT(qdcount == 1);
+ cp = answer + sizeof(HEADER);
+ bp = hostbuf;
+ buflen = sizeof(hostbuf);
+
+ n = dn_expand(answer, eom, cp, bp, buflen);
+ DNS_ASSERT(n >= 0);
+ cp += n + QFIXEDSZ;
+ hbuf.h_name = bp;
+ n = strlen(bp) + 1;
+ bp += n;
+ buflen -= n;
+ while (ancount-- > 0 && cp < eom) {
+ n = dn_expand(answer, eom, cp, bp, buflen);
+ DNS_ASSERT(n >= 0);
+ cp += n; /* name */
+ type = _getshort(cp);
+ cp += 2; /* type */
+ class = _getshort(cp);
+ cp += 2; /* class */
+ ttl = _getlong(cp);
+ cp += 4; /* ttl */
+ n = _getshort(cp);
+ cp += 2; /* len */
+ DNS_ASSERT(class == C_IN);
+ switch (type) {
+ case T_CNAME:
+ if (na >= MAXALIASES-1) {
+ cp += n;
+ break;
+ }
+ n = dn_expand(answer, eom, cp, tbuf, sizeof(tbuf));
+ DNS_ASSERT(n >= 0);
+ cp += n;
+ /* alias */
+ alist[na++] = bp;
+ n = strlen(bp) + 1;
+ bp += n;
+ buflen -= n;
+ /* canon */
+ n = strlen(tbuf) + 1;
+ DNS_ASSERT(n < buflen);
+ strcpy(bp, tbuf);
+ hbuf.h_name = bp;
+ bp += n;
+ buflen -= n;
+ break;
+ case T_A:
+#ifdef INET6
+ case T_AAAA:
+#endif
+ DNS_ASSERT(type == qtype);
+ bp = (char *)ALIGN(bp);
+ DNS_ASSERT(n == hbuf.h_length);
+ DNS_ASSERT(n < buflen);
+ if (nh < MAXADDRS-1) {
+ hlist[nh++] = bp;
+ memcpy(bp, cp, n);
+ bp += n;
+ buflen -= n;
+ }
+ cp += n;
+ break;
+ default:
+ DNS_ASSERT(0);
+ cp += n;
+ break;
+ }
+ }
+ if (nh == 0) {
+ badanswer:
+ *errp = NO_RECOVERY;
+ return NULL;
+ }
+ alist[na] = NULL;
+ hlist[nh] = NULL;
+ return _hpcopy(&hbuf, errp);
+}
+
+static struct hostent *
+_dns_ghbyaddr(const void *addr, int addrlen, int af, int *errp)
+{
+ int n;
+ u_char answer[BUFSIZ];
+ HEADER *hp;
+ u_char c, *cp, *eom;
+ int type, class, ancount, qdcount;
+ u_long ttl;
+ char hostbuf[BUFSIZ];
+ char *bp;
+ char *alist[MAXALIASES];
+ char *hlist[2];
+ struct hostent hbuf;
+ int buflen;
+ int na;
+#ifdef INET6
+ static const char hex[] = "0123456789abcdef";
+#endif
+
+#ifdef INET6
+ /* XXX */
+ if (af == AF_INET6 && IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)addr))
+ return NULL;
+#endif
+
+ if ((_res.options & RES_INIT) == 0) {
+ if (res_init() < 0) {
+ *errp = h_errno;
+ return NULL;
+ }
+ }
+ hbuf.h_name = NULL;
+ hbuf.h_aliases = alist;
+ hbuf.h_addrtype = af;
+ hbuf.h_length = addrlen;
+ hbuf.h_addr_list = hlist;
+ hlist[0] = (char *)addr;
+ hlist[1] = NULL;
+ na = 0;
+
+ n = 0;
+ bp = hostbuf;
+ cp = (u_char *)addr+addrlen-1;
+ switch (af) {
+#ifdef INET6
+ case AF_INET6:
+ for (; n < addrlen; n++, cp--) {
+ c = *cp;
+ *bp++ = hex[c & 0xf];
+ *bp++ = '.';
+ *bp++ = hex[c >> 4];
+ *bp++ = '.';
+ }
+ strcpy(bp, "ip6.int");
+ break;
+#endif
+ default:
+ for (; n < addrlen; n++, cp--) {
+ c = *cp;
+ if (c >= 100)
+ *bp++ = '0' + c / 100;
+ if (c >= 10)
+ *bp++ = '0' + (c % 100) / 10;
+ *bp++ = '0' + c % 10;
+ *bp++ = '.';
+ }
+ strcpy(bp, "in-addr.arpa");
+ break;
+ }
+
+ n = res_query(hostbuf, C_IN, T_PTR, answer, sizeof(answer));
+ if (n < 0) {
+ *errp = h_errno;
+ return NULL;
+ }
+ hp = (HEADER *)answer;
+ eom = answer + n;
+ ancount = ntohs(hp->ancount);
+ qdcount = ntohs(hp->qdcount);
+ DNS_ASSERT(qdcount == 1);
+ cp = answer + sizeof(HEADER);
+ bp = hostbuf;
+ buflen = sizeof(hostbuf);
+
+ n = dn_expand(answer, eom, cp, bp, buflen);
+ DNS_ASSERT(n >= 0);
+ cp += n + QFIXEDSZ;
+ while (ancount-- > 0 && cp < eom) {
+ n = dn_expand(answer, eom, cp, bp, buflen);
+ DNS_ASSERT(n >= 0);
+ cp += n; /* name */
+ type = _getshort(cp);
+ cp += 2; /* type */
+ class = _getshort(cp);
+ cp += 2; /* class */
+ ttl = _getlong(cp);
+ cp += 4; /* ttl */
+ n = _getshort(cp);
+ cp += 2; /* len */
+ DNS_ASSERT(class == C_IN);
+ switch (type) {
+ case T_PTR:
+ n = dn_expand(answer, eom, cp, bp, buflen);
+ DNS_ASSERT(n >= 0);
+ cp += n;
+ if (na >= MAXALIASES-1)
+ break;
+ if (hbuf.h_name == NULL)
+ hbuf.h_name = bp;
+ else
+ alist[na++] = bp;
+ n = strlen(bp) + 1;
+ bp += n;
+ buflen -= n;
+ break;
+ case T_CNAME:
+ cp += n;
+ break;
+ default:
+ badanswer:
+ *errp = NO_RECOVERY;
+ return NULL;
+ }
+ }
+ if (hbuf.h_name == NULL) {
+ *errp = h_errno;
+ return NULL;
+ }
+ alist[na] = NULL;
+ return _hpcopy(&hbuf, errp);
+}
+
+#ifdef ICMPNL
+
+/*
+ * experimental:
+ * draft-ietf-ipngwg-icmp-namelookups-02.txt
+ * ifindex is assumed to be encoded in addr.
+ */
+#include <sys/uio.h>
+#include <netinet/ip6.h>
+#include <netinet/icmp6.h>
+
+struct _icmp_host_cache {
+ struct _icmp_host_cache *hc_next;
+ int hc_ifindex;
+ struct in6_addr hc_addr;
+ char *hc_name;
+};
+
+static char *
+_icmp_fqdn_query(const struct in6_addr *addr, int ifindex)
+{
+ int s;
+ struct icmp6_filter filter;
+ struct msghdr msg;
+ struct cmsghdr *cmsg;
+ struct in6_pktinfo *pkt;
+ char cbuf[256];
+ char buf[1024];
+ int cc;
+ struct icmp6_fqdn_query *fq;
+ struct icmp6_fqdn_reply *fr;
+ struct _icmp_host_cache *hc;
+ struct sockaddr_in6 sin6;
+ struct iovec iov;
+ fd_set s_fds, fds;
+ struct timeval tout;
+ int len;
+ char *name;
+ static int pid;
+ static struct _icmp_host_cache *hc_head;
+
+ for (hc = hc_head; hc; hc = hc->hc_next) {
+ if (hc->hc_ifindex == ifindex
+ && IN6_ARE_ADDR_EQUAL(&hc->hc_addr, addr))
+ return hc->hc_name;
+ }
+
+ if (pid == 0)
+ pid = getpid();
+
+ ICMP6_FILTER_SETBLOCKALL(&filter);
+ ICMP6_FILTER_SETPASS(ICMP6_FQDN_REPLY, &filter);
+
+ FD_ZERO(&s_fds);
+ tout.tv_sec = 0;
+ tout.tv_usec = 200000; /*XXX: 200ms*/
+
+ fq = (struct icmp6_fqdn_query *)buf;
+ fq->icmp6_fqdn_type = ICMP6_FQDN_QUERY;
+ fq->icmp6_fqdn_code = 0;
+ fq->icmp6_fqdn_cksum = 0;
+ fq->icmp6_fqdn_id = (u_short)pid;
+ fq->icmp6_fqdn_unused = 0;
+ fq->icmp6_fqdn_cookie[0] = 0;
+ fq->icmp6_fqdn_cookie[1] = 0;
+
+ memset(&sin6, 0, sizeof(sin6));
+ sin6.sin6_family = AF_INET6;
+ sin6.sin6_addr = *addr;
+
+ memset(&msg, 0, sizeof(msg));
+ msg.msg_name = (caddr_t)&sin6;
+ msg.msg_namelen = sizeof(sin6);
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = NULL;
+ msg.msg_controllen = 0;
+ iov.iov_base = (caddr_t)buf;
+ iov.iov_len = sizeof(struct icmp6_fqdn_query);
+
+ if (ifindex) {
+ msg.msg_control = cbuf;
+ msg.msg_controllen = sizeof(cbuf);
+ cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
+ cmsg->cmsg_level = IPPROTO_IPV6;
+ cmsg->cmsg_type = IPV6_PKTINFO;
+ pkt = (struct in6_pktinfo *)&cmsg[1];
+ memset(&pkt->ipi6_addr, 0, sizeof(struct in6_addr));
+ pkt->ipi6_ifindex = ifindex;
+ cmsg = CMSG_NXTHDR(&msg, cmsg);
+ msg.msg_controllen = (char *)cmsg - cbuf;
+ }
+
+ if ((s = socket(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0)
+ return NULL;
+ (void)setsockopt(s, IPPROTO_ICMPV6, ICMP6_FILTER,
+ (char *)&filter, sizeof(filter));
+ cc = sendmsg(s, &msg, 0);
+ if (cc < 0) {
+ _libc_close(s);
+ return NULL;
+ }
+ FD_SET(s, &s_fds);
+ for (;;) {
+ fds = s_fds;
+ if (select(s + 1, &fds, NULL, NULL, &tout) <= 0) {
+ _libc_close(s);
+ return NULL;
+ }
+ len = sizeof(sin6);
+ cc = recvfrom(s, buf, sizeof(buf), 0,
+ (struct sockaddr *)&sin6, &len);
+ if (cc <= 0) {
+ _libc_close(s);
+ return NULL;
+ }
+ if (cc < sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr))
+ continue;
+ if (!IN6_ARE_ADDR_EQUAL(addr, &sin6.sin6_addr))
+ continue;
+ fr = (struct icmp6_fqdn_reply *)(buf + sizeof(struct ip6_hdr));
+ if (fr->icmp6_fqdn_type == ICMP6_FQDN_REPLY)
+ break;
+ }
+ _libc_close(s);
+ if (fr->icmp6_fqdn_cookie[1] != 0) {
+ /* rfc1788 type */
+ name = buf + sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr) + 4;
+ len = (buf + cc) - name;
+ } else {
+ len = fr->icmp6_fqdn_namelen;
+ name = fr->icmp6_fqdn_name;
+ }
+ if (len <= 0)
+ return NULL;
+ name[len] = 0;
+
+ if ((hc = (struct _icmp_host_cache *)malloc(sizeof(*hc))) == NULL)
+ return NULL;
+ /* XXX: limit number of cached entries */
+ hc->hc_ifindex = ifindex;
+ hc->hc_addr = *addr;
+ hc->hc_name = strdup(name);
+ hc->hc_next = hc_head;
+ hc_head = hc;
+ return hc->hc_name;
+}
+
+static struct hostent *
+_icmp_ghbyaddr(const void *addr, int addrlen, int af, int *errp)
+{
+ char *hname;
+ int ifindex;
+ struct in6_addr addr6;
+
+ if (af != AF_INET6) {
+ /*
+ * Note: rfc1788 defines Who Are You for IPv4,
+ * but no one implements it.
+ */
+ return NULL;
+ }
+
+ memcpy(&addr6, addr, addrlen);
+ ifindex = (addr6.s6_addr[2] << 8) | addr6.s6_addr[3];
+ addr6.s6_addr[2] = addr6.s6_addr[3] = 0;
+
+ if (!IN6_IS_ADDR_LINKLOCAL(&addr6))
+ return NULL; /*XXX*/
+
+ if ((hname = _icmp_fqdn_query(&addr6, ifindex)) == NULL)
+ return NULL;
+ return _hpaddr(af, hname, &addr6, errp);
+}
+#endif /* ICMPNL */
diff --git a/security/openssh/files/netdb.h b/security/openssh/files/netdb.h
new file mode 100644
index 000000000000..1a6d68dc527d
--- /dev/null
+++ b/security/openssh/files/netdb.h
@@ -0,0 +1,259 @@
+/*-
+ * Copyright (c) 1980, 1983, 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * -
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ * -
+ * --Copyright--
+ */
+
+/*
+ * @(#)netdb.h 8.1 (Berkeley) 6/2/93
+ * From: Id: netdb.h,v 8.9 1996/11/19 08:39:29 vixie Exp $
+ * $FreeBSD: /tmp/pcvs/ports/security/openssh/files/Attic/netdb.h,v 1.1 2000-01-13 23:22:14 green Exp $
+ */
+
+#ifndef _NETDB_H_
+#define _NETDB_H_
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#ifndef _PATH_HEQUIV
+# define _PATH_HEQUIV "/etc/hosts.equiv"
+#endif
+#define _PATH_HOSTS "/etc/hosts"
+#define _PATH_NETWORKS "/etc/networks"
+#define _PATH_PROTOCOLS "/etc/protocols"
+#define _PATH_SERVICES "/etc/services"
+
+extern int h_errno;
+
+/*
+ * Structures returned by network data base library. All addresses are
+ * supplied in host order, and returned in network order (suitable for
+ * use in system calls).
+ */
+struct hostent {
+ char *h_name; /* official name of host */
+ char **h_aliases; /* alias list */
+ int h_addrtype; /* host address type */
+ int h_length; /* length of address */
+ char **h_addr_list; /* list of addresses from name server */
+#define h_addr h_addr_list[0] /* address, for backward compatibility */
+};
+
+/*
+ * Assumption here is that a network number
+ * fits in an unsigned long -- probably a poor one.
+ */
+struct netent {
+ char *n_name; /* official name of net */
+ char **n_aliases; /* alias list */
+ int n_addrtype; /* net address type */
+ unsigned long n_net; /* network # */
+};
+
+struct servent {
+ char *s_name; /* official service name */
+ char **s_aliases; /* alias list */
+ int s_port; /* port # */
+ char *s_proto; /* protocol to use */
+};
+
+struct protoent {
+ char *p_name; /* official protocol name */
+ char **p_aliases; /* alias list */
+ int p_proto; /* protocol # */
+};
+
+struct addrinfo {
+ int ai_flags; /* AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST */
+ int ai_family; /* PF_xxx */
+ int ai_socktype; /* SOCK_xxx */
+ int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
+ size_t ai_addrlen; /* length of ai_addr */
+ char *ai_canonname; /* canonical name for hostname */
+ struct sockaddr *ai_addr; /* binary address */
+ struct addrinfo *ai_next; /* next structure in linked list */
+};
+
+/*
+ * Error return codes from gethostbyname() and gethostbyaddr()
+ * (left in extern int h_errno).
+ */
+
+#define NETDB_INTERNAL -1 /* see errno */
+#define NETDB_SUCCESS 0 /* no problem */
+#define HOST_NOT_FOUND 1 /* Authoritative Answer Host not found */
+#define TRY_AGAIN 2 /* Non-Authoritative Host not found, or SERVERFAIL */
+#define NO_RECOVERY 3 /* Non recoverable errors, FORMERR, REFUSED, NOTIMP */
+#define NO_DATA 4 /* Valid name, no data record of requested type */
+#define NO_ADDRESS NO_DATA /* no address, look for MX record */
+
+/*
+ * Error return codes from getaddrinfo()
+ */
+#define EAI_ADDRFAMILY 1 /* address family for hostname not supported */
+#define EAI_AGAIN 2 /* temporary failure in name resolution */
+#define EAI_BADFLAGS 3 /* invalid value for ai_flags */
+#define EAI_FAIL 4 /* non-recoverable failure in name resolution */
+#define EAI_FAMILY 5 /* ai_family not supported */
+#define EAI_MEMORY 6 /* memory allocation failure */
+#define EAI_NODATA 7 /* no address associated with hostname */
+#define EAI_NONAME 8 /* hostname nor servname provided, or not known */
+#define EAI_SERVICE 9 /* servname not supported for ai_socktype */
+#define EAI_SOCKTYPE 10 /* ai_socktype not supported */
+#define EAI_SYSTEM 11 /* system error returned in errno */
+#define EAI_BADHINTS 12
+#define EAI_PROTOCOL 13
+#define EAI_RESNULL 14
+#define EAI_MAX 15
+
+/*
+ * Flag values for getaddrinfo()
+ */
+#define AI_PASSIVE 0x00000001 /* get address to use bind() */
+#define AI_CANONNAME 0x00000002 /* fill ai_canonname */
+#define AI_NUMERICHOST 0x00000004 /* prevent name resolution */
+/* valid flags for addrinfo */
+#define AI_MASK (AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST)
+
+#define AI_ALL 0x00000100 /* IPv6 and IPv4-mapped (with AI_V4MAPPED) */
+#define AI_V4MAPPED_CFG 0x00000200 /* accept IPv4-mapped if kernel supports */
+#define AI_ADDRCONFIG 0x00000400 /* only if any address is assigned */
+#define AI_V4MAPPED 0x00000800 /* accept IPv4-mapped IPv6 address */
+/* special recommended flags for getipnodebyname */
+#define AI_DEFAULT (AI_V4MAPPED_CFG | AI_ADDRCONFIG)
+
+/*
+ * Constants for getnameinfo()
+ */
+#define NI_MAXHOST 1025
+#define NI_MAXSERV 32
+
+/*
+ * Flag values for getnameinfo()
+ */
+#define NI_NOFQDN 0x00000001
+#define NI_NUMERICHOST 0x00000002
+#define NI_NAMEREQD 0x00000004
+#define NI_NUMERICSERV 0x00000008
+#define NI_DGRAM 0x00000010
+#define NI_WITHSCOPEID 0x00000020
+
+/*
+ * Scope delimit character
+ */
+#define SCOPE_DELIMITER '@'
+
+__BEGIN_DECLS
+void endhostent __P((void));
+void endnetent __P((void));
+void endprotoent __P((void));
+void endservent __P((void));
+void freehostent __P((struct hostent *));
+struct hostent *gethostbyaddr __P((const char *, int, int));
+struct hostent *gethostbyname __P((const char *));
+struct hostent *gethostbyname2 __P((const char *, int));
+struct hostent *gethostent __P((void));
+struct hostent *getipnodebyaddr __P((const void *, size_t, int, int *));
+struct hostent *getipnodebyname __P((const char *, int, int, int *));
+struct netent *getnetbyaddr __P((unsigned long, int));
+struct netent *getnetbyname __P((const char *));
+struct netent *getnetent __P((void));
+struct protoent *getprotobyname __P((const char *));
+struct protoent *getprotobynumber __P((int));
+struct protoent *getprotoent __P((void));
+struct servent *getservbyname __P((const char *, const char *));
+struct servent *getservbyport __P((int, const char *));
+struct servent *getservent __P((void));
+void herror __P((const char *));
+__const char *hstrerror __P((int));
+void sethostent __P((int));
+/* void sethostfile __P((const char *)); */
+void setnetent __P((int));
+void setprotoent __P((int));
+int getaddrinfo __P((const char *, const char *,
+ const struct addrinfo *, struct addrinfo **));
+int getnameinfo __P((const struct sockaddr *, size_t, char *,
+ size_t, char *, size_t, int));
+void freeaddrinfo __P((struct addrinfo *));
+char *gai_strerror __P((int));
+void setservent __P((int));
+
+/*
+ * PRIVATE functions specific to the FreeBSD implementation
+ */
+
+/* DO NOT USE THESE, THEY ARE SUBJECT TO CHANGE AND ARE NOT PORTABLE!!! */
+void _sethosthtent __P((int));
+void _endhosthtent __P((void));
+void _sethostdnsent __P((int));
+void _endhostdnsent __P((void));
+void _setnethtent __P((int));
+void _endnethtent __P((void));
+void _setnetdnsent __P((int));
+void _endnetdnsent __P((void));
+struct hostent * _gethostbyhtname __P((const char *, int));
+struct hostent * _gethostbydnsname __P((const char *, int));
+struct hostent * _gethostbynisname __P((const char *, int));
+struct hostent * _gethostbyhtaddr __P((const char *, int, int));
+struct hostent * _gethostbydnsaddr __P((const char *, int, int));
+struct hostent * _gethostbynisaddr __P((const char *, int, int));
+struct netent * _getnetbyhtname __P((const char *));
+struct netent * _getnetbydnsname __P((const char *));
+struct netent * _getnetbynisname __P((const char *));
+struct netent * _getnetbyhtaddr __P((unsigned long, int));
+struct netent * _getnetbydnsaddr __P((unsigned long, int));
+struct netent * _getnetbynisaddr __P((unsigned long, int));
+void _map_v4v6_address __P((const char *src, char *dst));
+void _map_v4v6_hostent __P((struct hostent *hp, char **bp, int *len));
+__END_DECLS
+
+#endif /* !_NETDB_H_ */
diff --git a/security/openssh/files/patch-ab b/security/openssh/files/patch-ab
index 60e0dd4334ee..e2da3f1e9758 100644
--- a/security/openssh/files/patch-ab
+++ b/security/openssh/files/patch-ab
@@ -1,6 +1,6 @@
---- /usr/ports/distfiles/OpenSSH-1.2/src/usr.bin/ssh/Makefile.inc Mon Oct 25 16:27:26 1999
-+++ Makefile.inc Mon Nov 29 01:06:23 1999
-@@ -2,10 +2,14 @@
+--- Makefile.inc.orig Fri Jan 14 08:35:05 2000
++++ Makefile.inc Fri Jan 14 08:40:03 2000
+@@ -2,10 +2,17 @@
.include <bsd.obj.mk>
@@ -16,6 +16,9 @@
+.if !defined(MAKEFILE_INC_FIRST_PASS)
+MAKEFILE_INC_FIRST_PASS= 0
+CFLAGS+= -I${PREFIX}/include
++.if defined(USE_INET6)
++CFLAGS+= -DINET6
++.endif
LDADD+= -L${.CURDIR}/../lib -lssh
DPADD+= ${.CURDIR}/../lib/libssh.a
.endif
diff --git a/security/openssh/files/patch-ac b/security/openssh/files/patch-ac
index f6ad51c27c10..42a204e9484f 100644
--- a/security/openssh/files/patch-ac
+++ b/security/openssh/files/patch-ac
@@ -1,5 +1,5 @@
---- /usr/ports/distfiles/OpenSSH-1.2/src/usr.bin/ssh/includes.h Tue Nov 2 16:21:02 1999
-+++ ./includes.h Tue Nov 23 19:20:38 1999
+--- /usr/ports/distfiles/OpenSSH-1.2.1/src/usr.bin/ssh/includes.h Sun Nov 28 16:37:35 1999
++++ includes.h Thu Jan 13 18:03:48 2000
@@ -24,12 +24,12 @@
#include <sys/select.h>
#include <sys/param.h>
@@ -22,3 +22,37 @@
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
+@@ -65,5 +64,33 @@
+ * client program. Socketpairs do not seem to work on all systems.
+ */
+ #define USE_PIPES 1
++
++#if defined(__FreeBSD__) && __FreeBSD__ <= 3
++/*
++ * Data types.
++ */
++typedef u_char sa_family_t;
++typedef u_int32_t socklen_t;
++
++/*
++ * bsd-api-new-02a: protocol-independent placeholder for socket addresses
++ */
++#define _SS_MAXSIZE 128
++#define _SS_ALIGNSIZE (sizeof(int64_t))
++#define _SS_PAD1SIZE (_SS_ALIGNSIZE - sizeof(u_char) * 2)
++#define _SS_PAD2SIZE (_SS_MAXSIZE - sizeof(u_char) * 2 - \
++ _SS_PAD1SIZE - _SS_ALIGNSIZE)
++
++struct sockaddr_storage {
++ u_char __ss_len; /* address length */
++ sa_family_t __ss_family; /* address family */
++ char __ss_pad1[_SS_PAD1SIZE];
++ int64_t __ss_align; /* force desired structure storage alignment */
++ char __ss_pad2[_SS_PAD2SIZE];
++};
++#else
++#define ss_len __ss_len
++#define ss_family __ss_family
++#endif
+
+ #endif /* INCLUDES_H */
diff --git a/security/openssh/files/patch-ad b/security/openssh/files/patch-ad
index eb55f8ef07af..ee8482f484c0 100644
--- a/security/openssh/files/patch-ad
+++ b/security/openssh/files/patch-ad
@@ -1,16 +1,20 @@
---- lib/Makefile.orig Tue Dec 7 22:50:49 1999
-+++ lib/Makefile Tue Dec 7 22:53:22 1999
-@@ -4,7 +4,8 @@
+--- lib/Makefile.orig Fri Jan 14 04:55:08 2000
++++ lib/Makefile Fri Jan 14 08:01:17 2000
+@@ -4,7 +4,12 @@
SRCS= authfd.c authfile.c bufaux.c buffer.c canohost.c channels.c \
cipher.c compat.c compress.c crc32.c deattack.c fingerprint.c \
hostfile.c log.c match.c mpaux.c nchan.c packet.c readpass.c \
- rsa.c tildexpand.c ttymodes.c uidswap.c xmalloc.c atomicio.c
+ rsa.c tildexpand.c ttymodes.c uidswap.c xmalloc.c atomicio.c \
+ strlcat.c strlcpy.c
++
++.if !defined(USE_INET6)
++SRCS+= getaddrinfo.c getnameinfo.c name6.c rcmd.c bindresvport.c
++.endif
NOPROFILE= yes
NOPIC= yes
-@@ -13,6 +14,7 @@
+@@ -13,6 +18,7 @@
@echo -n
.include <bsd.own.mk>
diff --git a/security/openssh/files/patch-an b/security/openssh/files/patch-an
index 2c39339acaa0..9bbdf3348585 100644
--- a/security/openssh/files/patch-an
+++ b/security/openssh/files/patch-an
@@ -1,6 +1,6 @@
---- sshd.c.orig Tue Dec 7 22:56:55 1999
-+++ sshd.c Tue Dec 7 22:58:36 1999
-@@ -24,6 +24,8 @@
+--- sshd.c.orig Fri Jan 7 01:32:03 2000
++++ sshd.c Fri Jan 7 01:40:05 2000
+@@ -26,6 +26,8 @@
#include "servconf.h"
#include "uidswap.h"
#include "compat.h"
@@ -9,7 +9,7 @@
#ifdef LIBWRAP
#include <tcpd.h>
-@@ -32,6 +34,16 @@
+@@ -34,6 +36,16 @@
int deny_severity = LOG_WARNING;
#endif /* LIBWRAP */
@@ -26,7 +26,7 @@
#ifndef O_NOCTTY
#define O_NOCTTY 0
#endif
-@@ -118,6 +130,32 @@
+@@ -128,6 +140,32 @@
the private key. */
RSA *public_key;
@@ -39,7 +39,7 @@
+const size_t MAGIC_CONNECTIONS_SIZE = 1;
+
+static __inline int
-+magic_hash(struct sockaddr_in *sin) {
++magic_hash(struct sockaddr *sa) {
+
+ return 0;
+}
@@ -59,17 +59,17 @@
/* Prototypes for various functions defined later in this file. */
void do_connection();
void do_authentication(char *user);
-@@ -278,6 +316,7 @@
- extern char *optarg;
+@@ -301,6 +339,7 @@
extern int optind;
- int opt, aux, sock_in, sock_out, newsock, i, pid, on = 1;
-+ int connections_per_period_exceeded = 0;
+ int opt, sock_in = 0, sock_out = 0, newsock, i, fdsetsz, pid, on = 1;
+ socklen_t fromlen;
++ int connections_per_period_exceeded = 0;
int remote_major, remote_minor;
int silentrsa = 0;
- struct pollfd fds;
-@@ -543,6 +582,12 @@
- /* Arrange SIGCHLD to be caught. */
- signal(SIGCHLD, main_sigchld_handler);
+ fd_set *fdset;
+@@ -620,6 +659,12 @@
+ fdsetsz = howmany(maxfd, NFDBITS) * sizeof(fd_mask);
+ fdset = (fd_set *)xmalloc(fdsetsz);
+ /* Initialize the magic_connections table. It's magical! */
+ magic_connections = calloc(MAGIC_CONNECTIONS_SIZE,
@@ -80,8 +80,8 @@
/*
* Stay listening for connections until the system crashes or
* the daemon is killed with a signal.
-@@ -572,9 +617,31 @@
- error("accept: %.100s", strerror(errno));
+@@ -651,9 +696,31 @@
+ error("newsock del O_NONBLOCK: %s", strerror(errno));
continue;
}
+ if (options.connections_per_period != 0) {
@@ -89,7 +89,7 @@
+ struct magic_connection *mc;
+
+ (void)gettimeofday(&connections_end, NULL);
-+ mc = &magic_connections[magic_hash(&sin)];
++ mc = &magic_connections[magic_hash(ai->ai_addr)];
+ diff = timevaldiff(&mc->connections_begin, &connections_end);
+ if (diff.tv_sec >= options.connections_period) {
+ /*
@@ -114,7 +114,7 @@
*/
if (debug_flag) {
/*
-@@ -588,6 +655,12 @@
+@@ -667,6 +734,12 @@
sock_out = newsock;
pid = getpid();
break;
@@ -122,12 +122,12 @@
+ log("Connection rate limit of %u/%us has been exceeded; "
+ "dropping connection from %s.",
+ options.connections_per_period, options.connections_period,
-+ inet_ntoa(sin.sin_addr));
++ ntop);
+ connections_per_period_exceeded = 0;
} else {
/*
* Normal production daemon. Fork, and have
-@@ -1065,6 +1138,14 @@
+@@ -1152,6 +1225,14 @@
return 0;
}
}
@@ -142,7 +142,7 @@
/* We found no reason not to let this user try to log on... */
return 1;
}
-@@ -1100,6 +1181,9 @@
+@@ -1187,6 +1268,9 @@
pwcopy.pw_gid = pw->pw_gid;
pwcopy.pw_dir = xstrdup(pw->pw_dir);
pwcopy.pw_shell = xstrdup(pw->pw_shell);
@@ -152,9 +152,9 @@
pw = &pwcopy;
/*
-@@ -1889,6 +1973,10 @@
- struct sockaddr_in from;
- int fromlen;
+@@ -1983,6 +2067,10 @@
+ struct sockaddr_storage from;
+ socklen_t fromlen;
struct pty_cleanup_context cleanup_context;
+#ifdef LOGIN_CAP
+ login_cap_t *lc;
@@ -163,7 +163,7 @@
/* Get remote host name. */
hostname = get_canonical_hostname();
-@@ -1953,6 +2041,12 @@
+@@ -2047,6 +2135,12 @@
/* Check if .hushlogin exists. */
snprintf(line, sizeof line, "%.200s/.hushlogin", pw->pw_dir);
quiet_login = stat(line, &st) >= 0;
@@ -176,7 +176,7 @@
/*
* If the user has logged in before, display the time of last
-@@ -1976,6 +2070,20 @@
+@@ -2070,6 +2164,20 @@
else
printf("Last login: %s from %s\r\n", time_string, buf);
}
@@ -197,7 +197,7 @@
/*
* Print /etc/motd unless a command was specified or printing
* it was disabled in server options or login(1) will be
-@@ -1984,14 +2092,22 @@
+@@ -2078,14 +2186,22 @@
*/
if (command == NULL && options.print_motd && !quiet_login &&
!options.use_login) {
@@ -221,7 +221,7 @@
/* Do common processing for the child, such as execing the command. */
do_child(command, pw, term, display, auth_proto, auth_data, ttyname);
/* NOTREACHED */
-@@ -2127,7 +2243,8 @@
+@@ -2221,7 +2337,8 @@
const char *display, const char *auth_proto,
const char *auth_data, const char *ttyname)
{
@@ -231,7 +231,7 @@
char buf[256];
FILE *f;
unsigned int envsize, i;
-@@ -2135,15 +2252,34 @@
+@@ -2229,15 +2346,34 @@
extern char **environ;
struct stat st;
char *argv[10];
@@ -271,7 +271,7 @@
}
/* Set login name in the kernel. */
if (setlogin(pw->pw_name) < 0)
-@@ -2153,6 +2289,13 @@
+@@ -2247,6 +2383,13 @@
/* Login(1) does this as well, and it needs uid 0 for the "-h"
switch, so we let login(1) to this for us. */
if (!options.use_login) {
@@ -285,7 +285,7 @@
if (getuid() == 0 || geteuid() == 0) {
if (setgid(pw->pw_gid) < 0) {
perror("setgid");
-@@ -2175,7 +2318,14 @@
+@@ -2269,7 +2412,14 @@
* Get the shell from the password data. An empty shell field is
* legal, and means /bin/sh.
*/
@@ -300,7 +300,7 @@
#ifdef AFS
/* Try to get AFS tokens for the local cell. */
-@@ -2199,7 +2349,12 @@
+@@ -2293,7 +2443,12 @@
child_set_env(&env, &envsize, "USER", pw->pw_name);
child_set_env(&env, &envsize, "LOGNAME", pw->pw_name);
child_set_env(&env, &envsize, "HOME", pw->pw_dir);
@@ -313,17 +313,17 @@
snprintf(buf, sizeof buf, "%.200s/%.50s",
_PATH_MAILDIR, pw->pw_name);
-@@ -2289,6 +2444,9 @@
+@@ -2383,13 +2538,17 @@
*/
endpwent();
- endhostent();
+
+#ifdef LOGIN_CAP
-+ login_close(lc);
++ login_close(lc);
+#endif /* LOGIN_CAP */
-
++
/*
* Close any extra open file descriptors so that we don\'t have them
-@@ -2296,7 +2454,7 @@
+ * hanging around in clients. Note that we want to do this after
* initgroups, because at least on Solaris 2.3 it leaves file
* descriptors open.
*/
@@ -332,7 +332,7 @@
close(i);
/* Change current directory to the user\'s home directory. */
-@@ -2315,6 +2473,26 @@
+@@ -2408,6 +2567,26 @@
* in this order).
*/
if (!options.use_login) {
diff --git a/security/openssh/files/patch-ao b/security/openssh/files/patch-ao
index 7ca746e1fb3a..0e5eac8dee2b 100644
--- a/security/openssh/files/patch-ao
+++ b/security/openssh/files/patch-ao
@@ -1,9 +1,9 @@
---- /usr/ports/distfiles/OpenSSH-1.2/src/usr.bin/ssh/sshd_config Thu Nov 11 17:58:39 1999
-+++ sshd_config Sun Dec 5 13:37:20 1999
-@@ -2,12 +2,13 @@
-
+--- sshd_config.orig Fri Jan 7 01:27:30 2000
++++ sshd_config Fri Jan 7 01:31:01 2000
+@@ -3,12 +3,13 @@
Port 22
- ListenAddress 0.0.0.0
+ #ListenAddress 0.0.0.0
+ #ListenAddress ::
-HostKey /etc/ssh_host_key
+HostKey __PREFIX__/etc/ssh_host_key
ServerKeyBits 768
diff --git a/security/openssh/files/patch-at b/security/openssh/files/patch-at
new file mode 100644
index 000000000000..fbb18bc12079
--- /dev/null
+++ b/security/openssh/files/patch-at
@@ -0,0 +1,14 @@
+--- sshconnect.c- Fri Jan 14 08:44:43 2000
++++ sshconnect.c Fri Jan 14 08:44:56 2000
+@@ -1078,9 +1078,11 @@
+ case AF_INET:
+ local = (ntohl(((struct sockaddr_in *)hostaddr)->sin_addr.s_addr) >> 24) == IN_LOOPBACKNET;
+ break;
++#ifdef INET6
+ case AF_INET6:
+ local = IN6_IS_ADDR_LOOPBACK(&(((struct sockaddr_in6 *)hostaddr)->sin6_addr));
+ break;
++#endif
+ default:
+ local = 0;
+ break;
diff --git a/security/openssh/files/rcmd.c b/security/openssh/files/rcmd.c
new file mode 100644
index 000000000000..b33e44967e3e
--- /dev/null
+++ b/security/openssh/files/rcmd.c
@@ -0,0 +1,653 @@
+/*
+ * Copyright (c) 1983, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: /tmp/pcvs/ports/security/openssh/files/Attic/rcmd.c,v 1.1 2000-01-13 23:22:15 green Exp $
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rcmd.c 8.3 (Berkeley) 3/26/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <signal.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <errno.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#ifdef YP
+#include <rpc/rpc.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+#endif
+
+#include "includes.h"
+
+/* wrapper for KAME-special getnameinfo() */
+#ifndef NI_WITHSCOPEID
+#define NI_WITHSCOPEID 0
+#endif
+
+extern int innetgr __P(( const char *, const char *, const char *, const char * ));
+
+#define max(a, b) ((a > b) ? a : b)
+
+int __ivaliduser __P((FILE *, u_int32_t, const char *, const char *));
+static int __icheckhost __P((void *, char *, int, int));
+
+#define INET6_ADDRSTRLEN 46
+char paddr[INET6_ADDRSTRLEN];
+
+int
+rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
+ char **ahost;
+ u_short rport;
+ const char *locuser, *remuser, *cmd;
+ int *fd2p;
+{
+ struct addrinfo hints, *res, *ai;
+ struct sockaddr_storage from;
+ fd_set reads;
+ long oldmask;
+ pid_t pid;
+ int s, aport, lport, timo, error;
+ char c;
+ int refused;
+ char num[8];
+
+ pid = getpid();
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_flags = AI_CANONNAME;
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = 0;
+ (void)snprintf(num, sizeof(num), "%d", ntohs(rport));
+ error = getaddrinfo(*ahost, num, &hints, &res);
+ if (error) {
+ fprintf(stderr, "rcmd: getaddrinfo: %s\n",
+ gai_strerror(error));
+ if (error == EAI_SYSTEM)
+ fprintf(stderr, "rcmd: getaddrinfo: %s\n",
+ strerror(errno));
+ return (-1);
+ }
+ if (res->ai_canonname)
+ *ahost = res->ai_canonname;
+ ai = res;
+ refused = 0;
+ oldmask = sigblock(sigmask(SIGURG));
+ for (timo = 1, lport = IPPORT_RESERVED - 1;;) {
+ s = rresvport_af(&lport, ai->ai_family);
+ if (s < 0) {
+ if (errno == EAGAIN)
+ (void)fprintf(stderr,
+ "rcmd: socket: All ports in use\n");
+ else
+ (void)fprintf(stderr, "rcmd: socket: %s\n",
+ strerror(errno));
+ sigsetmask(oldmask);
+ freeaddrinfo(res);
+ return (-1);
+ }
+ fcntl(s, F_SETOWN, pid);
+ if (connect(s, ai->ai_addr, ai->ai_addrlen) >= 0)
+ break;
+ (void)close(s);
+ if (errno == EADDRINUSE) {
+ lport--;
+ continue;
+ }
+ if (errno == ECONNREFUSED)
+ refused = 1;
+ if (ai->ai_next != NULL) {
+ int oerrno = errno;
+
+ getnameinfo(ai->ai_addr, ai->ai_addrlen,
+ paddr, sizeof(paddr),
+ NULL, 0,
+ NI_NUMERICHOST|NI_WITHSCOPEID);
+ (void)fprintf(stderr, "connect to address %s: ",
+ paddr);
+ errno = oerrno;
+ perror(0);
+ ai = ai->ai_next;
+ getnameinfo(ai->ai_addr, ai->ai_addrlen,
+ paddr, sizeof(paddr),
+ NULL, 0,
+ NI_NUMERICHOST|NI_WITHSCOPEID);
+ fprintf(stderr, "Trying %s...\n", paddr);
+ continue;
+ }
+ if (refused && timo <= 16) {
+ (void)sleep(timo);
+ timo *= 2;
+ ai = res;
+ refused = 0;
+ continue;
+ }
+ freeaddrinfo(res);
+ (void)fprintf(stderr, "%s: %s\n", *ahost, strerror(errno));
+ sigsetmask(oldmask);
+ return (-1);
+ }
+ lport--;
+ if (fd2p == 0) {
+ write(s, "", 1);
+ lport = 0;
+ } else {
+ char num[8];
+ int s2 = rresvport_af(&lport, ai->ai_family), s3;
+ int len = ai->ai_addrlen;
+ int nfds;
+
+ if (s2 < 0)
+ goto bad;
+ listen(s2, 1);
+ (void)snprintf(num, sizeof(num), "%d", lport);
+ if (write(s, num, strlen(num)+1) != strlen(num)+1) {
+ (void)fprintf(stderr,
+ "rcmd: write (setting up stderr): %s\n",
+ strerror(errno));
+ (void)close(s2);
+ goto bad;
+ }
+ nfds = max(s, s2)+1;
+ if(nfds > FD_SETSIZE) {
+ fprintf(stderr, "rcmd: too many files\n");
+ (void)close(s2);
+ goto bad;
+ }
+again:
+ FD_ZERO(&reads);
+ FD_SET(s, &reads);
+ FD_SET(s2, &reads);
+ errno = 0;
+ if (select(nfds, &reads, 0, 0, 0) < 1 || !FD_ISSET(s2, &reads)){
+ if (errno != 0)
+ (void)fprintf(stderr,
+ "rcmd: select (setting up stderr): %s\n",
+ strerror(errno));
+ else
+ (void)fprintf(stderr,
+ "select: protocol failure in circuit setup\n");
+ (void)close(s2);
+ goto bad;
+ }
+ s3 = accept(s2, (struct sockaddr *)&from, &len);
+ switch (from.ss_family) {
+ case AF_INET:
+ aport = ntohs(((struct sockaddr_in *)&from)->sin_port);
+ break;
+#ifdef INET6
+ case AF_INET6:
+ aport = ntohs(((struct sockaddr_in6 *)&from)->sin6_port);
+ break;
+#endif
+ default:
+ aport = 0; /* error */
+ break;
+ }
+ /*
+ * XXX careful for ftp bounce attacks. If discovered, shut them
+ * down and check for the real auxiliary channel to connect.
+ */
+ if (aport == 20) {
+ close(s3);
+ goto again;
+ }
+ (void)close(s2);
+ if (s3 < 0) {
+ (void)fprintf(stderr,
+ "rcmd: accept: %s\n", strerror(errno));
+ lport = 0;
+ goto bad;
+ }
+ *fd2p = s3;
+ if (aport >= IPPORT_RESERVED || aport < IPPORT_RESERVED / 2) {
+ (void)fprintf(stderr,
+ "socket: protocol failure in circuit setup.\n");
+ goto bad2;
+ }
+ }
+ (void)write(s, locuser, strlen(locuser)+1);
+ (void)write(s, remuser, strlen(remuser)+1);
+ (void)write(s, cmd, strlen(cmd)+1);
+ if (read(s, &c, 1) != 1) {
+ (void)fprintf(stderr,
+ "rcmd: %s: %s\n", *ahost, strerror(errno));
+ goto bad2;
+ }
+ if (c != 0) {
+ while (read(s, &c, 1) == 1) {
+ (void)write(STDERR_FILENO, &c, 1);
+ if (c == '\n')
+ break;
+ }
+ goto bad2;
+ }
+ sigsetmask(oldmask);
+ freeaddrinfo(res);
+ return (s);
+bad2:
+ if (lport)
+ (void)close(*fd2p);
+bad:
+ (void)close(s);
+ sigsetmask(oldmask);
+ freeaddrinfo(res);
+ return (-1);
+}
+
+int
+rresvport(port)
+ int *port;
+{
+ return rresvport_af(port, AF_INET);
+}
+
+int
+rresvport_af(alport, family)
+ int *alport, family;
+{
+ int i, s, len, err;
+ struct sockaddr_storage ss;
+ u_short *sport;
+
+ memset(&ss, 0, sizeof(ss));
+ ss.ss_family = family;
+ switch (family) {
+ case AF_INET:
+ ss.ss_len = sizeof(struct sockaddr_in);
+ sport = &((struct sockaddr_in *)&ss)->sin_port;
+ ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
+ break;
+#ifdef INET6
+ case AF_INET6:
+ ss.ss_len = sizeof(struct sockaddr_in6);
+ sport = &((struct sockaddr_in6 *)&ss)->sin6_port;
+ ((struct sockaddr_in6 *)&ss)->sin6_addr = in6addr_any;
+ break;
+#endif
+ default:
+ errno = EAFNOSUPPORT;
+ return -1;
+ }
+
+ s = socket(ss.ss_family, SOCK_STREAM, 0);
+ if (s < 0)
+ return (-1);
+#if 0 /* compat_exact_traditional_rresvport_semantics */
+ sin.sin_port = htons((u_short)*alport);
+ if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0)
+ return (s);
+ if (errno != EADDRINUSE) {
+ (void)close(s);
+ return (-1);
+ }
+#endif
+ *sport = 0;
+ if (bindresvport2(s, (struct sockaddr *)&ss, ss.ss_len) == -1) {
+ (void)close(s);
+ return (-1);
+ }
+ *alport = (int)ntohs(*sport);
+ return (s);
+}
+
+int __check_rhosts_file = 1;
+char *__rcmd_errstr;
+
+int
+ruserok(rhost, superuser, ruser, luser)
+ const char *rhost, *ruser, *luser;
+ int superuser;
+{
+ return ruserok_af(rhost, superuser, ruser, luser, AF_INET);
+}
+
+int
+ruserok_af(rhost, superuser, ruser, luser, af)
+ const char *rhost, *ruser, *luser;
+ int superuser, af;
+{
+ struct hostent *hp;
+ union {
+ struct in_addr addr_in;
+#ifdef INET6
+ struct in6_addr addr_in6;
+#endif
+ } addr;
+ char **ap;
+ int ret, h_error;
+
+ if ((hp = getipnodebyname(rhost, af, AI_DEFAULT, &h_error)) == NULL)
+ return (-1);
+ ret = -1;
+ for (ap = hp->h_addr_list; *ap; ++ap) {
+ bcopy(*ap, &addr, hp->h_length);
+ if (iruserok_af(&addr, superuser, ruser, luser, af) == 0) {
+ ret = 0;
+ break;
+ }
+ }
+ freehostent(hp);
+ return (ret);
+}
+
+/*
+ * New .rhosts strategy: We are passed an ip address. We spin through
+ * hosts.equiv and .rhosts looking for a match. When the .rhosts only
+ * has ip addresses, we don't have to trust a nameserver. When it
+ * contains hostnames, we spin through the list of addresses the nameserver
+ * gives us and look for a match.
+ *
+ * Returns 0 if ok, -1 if not ok.
+ */
+int
+iruserok(raddr, superuser, ruser, luser)
+ unsigned long raddr;
+ int superuser;
+ const char *ruser, *luser;
+{
+ return iruserok_af(&raddr, superuser, ruser, luser, AF_INET);
+}
+
+int
+iruserok_af(raddr, superuser, ruser, luser, af)
+ void *raddr;
+ int superuser;
+ const char *ruser, *luser;
+ int af;
+{
+ register char *cp;
+ struct stat sbuf;
+ struct passwd *pwd;
+ FILE *hostf;
+ uid_t uid;
+ int first;
+ char pbuf[MAXPATHLEN];
+ int len = 0;
+
+ switch (af) {
+ case AF_INET:
+ len = sizeof(struct in_addr);
+ break;
+#ifdef INET6
+ case AF_INET6:
+ len = sizeof(struct in6_addr);
+ break;
+#endif
+ }
+
+ first = 1;
+ hostf = superuser ? NULL : fopen(_PATH_HEQUIV, "r");
+again:
+ if (hostf) {
+ if (__ivaliduser_af(hostf, raddr, luser, ruser, af, len)
+ == 0) {
+ (void)fclose(hostf);
+ return (0);
+ }
+ (void)fclose(hostf);
+ }
+ if (first == 1 && (__check_rhosts_file || superuser)) {
+ first = 0;
+ if ((pwd = getpwnam(luser)) == NULL)
+ return (-1);
+ (void)strcpy(pbuf, pwd->pw_dir);
+ (void)strcat(pbuf, "/.rhosts");
+
+ /*
+ * Change effective uid while opening .rhosts. If root and
+ * reading an NFS mounted file system, can't read files that
+ * are protected read/write owner only.
+ */
+ uid = geteuid();
+ (void)seteuid(pwd->pw_uid);
+ hostf = fopen(pbuf, "r");
+ (void)seteuid(uid);
+
+ if (hostf == NULL)
+ return (-1);
+ /*
+ * If not a regular file, or is owned by someone other than
+ * user or root or if writeable by anyone but the owner, quit.
+ */
+ cp = NULL;
+ if (lstat(pbuf, &sbuf) < 0)
+ cp = ".rhosts lstat failed";
+ else if (!S_ISREG(sbuf.st_mode))
+ cp = ".rhosts not regular file";
+ else if (fstat(fileno(hostf), &sbuf) < 0)
+ cp = ".rhosts fstat failed";
+ else if (sbuf.st_uid && sbuf.st_uid != pwd->pw_uid)
+ cp = "bad .rhosts owner";
+ else if (sbuf.st_mode & (S_IWGRP|S_IWOTH))
+ cp = ".rhosts writeable by other than owner";
+ /* If there were any problems, quit. */
+ if (cp) {
+ __rcmd_errstr = cp;
+ (void)fclose(hostf);
+ return (-1);
+ }
+ goto again;
+ }
+ return (-1);
+}
+
+/*
+ * XXX
+ * Don't make static, used by lpd(8).
+ *
+ * Returns 0 if ok, -1 if not ok.
+ */
+int
+__ivaliduser(hostf, raddr, luser, ruser)
+ FILE *hostf;
+ u_int32_t raddr;
+ const char *luser, *ruser;
+{
+ return __ivaliduser_af(hostf, &raddr, luser, ruser, AF_INET,
+ sizeof(raddr));
+}
+
+int
+__ivaliduser_af(hostf, raddr, luser, ruser, af, len)
+ FILE *hostf;
+ void *raddr;
+ const char *luser, *ruser;
+ int af, len;
+{
+ register char *user, *p;
+ int ch;
+ char buf[MAXHOSTNAMELEN + 128]; /* host + login */
+ char hname[MAXHOSTNAMELEN];
+ struct hostent *hp;
+ /* Presumed guilty until proven innocent. */
+ int userok = 0, hostok = 0;
+ int h_error;
+#ifdef YP
+ char *ypdomain;
+
+ if (yp_get_default_domain(&ypdomain))
+ ypdomain = NULL;
+#else
+#define ypdomain NULL
+#endif
+ /* We need to get the damn hostname back for netgroup matching. */
+ if ((hp = getipnodebyaddr((char *)raddr, len, af, &h_error)) == NULL)
+ return (-1);
+ strncpy(hname, hp->h_name, sizeof(hname));
+ hname[sizeof(hname) - 1] = '\0';
+ freehostent(hp);
+
+ while (fgets(buf, sizeof(buf), hostf)) {
+ p = buf;
+ /* Skip lines that are too long. */
+ if (strchr(p, '\n') == NULL) {
+ while ((ch = getc(hostf)) != '\n' && ch != EOF);
+ continue;
+ }
+ if (*p == '\n' || *p == '#') {
+ /* comment... */
+ continue;
+ }
+ while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') {
+ *p = isupper((unsigned char)*p) ? tolower((unsigned char)*p) : *p;
+ p++;
+ }
+ if (*p == ' ' || *p == '\t') {
+ *p++ = '\0';
+ while (*p == ' ' || *p == '\t')
+ p++;
+ user = p;
+ while (*p != '\n' && *p != ' ' &&
+ *p != '\t' && *p != '\0')
+ p++;
+ } else
+ user = p;
+ *p = '\0';
+ /*
+ * Do +/- and +@/-@ checking. This looks really nasty,
+ * but it matches SunOS's behavior so far as I can tell.
+ */
+ switch(buf[0]) {
+ case '+':
+ if (!buf[1]) { /* '+' matches all hosts */
+ hostok = 1;
+ break;
+ }
+ if (buf[1] == '@') /* match a host by netgroup */
+ hostok = innetgr((char *)&buf[2],
+ (char *)&hname, NULL, ypdomain);
+ else /* match a host by addr */
+ hostok = __icheckhost(raddr,(char *)&buf[1],
+ af, len);
+ break;
+ case '-': /* reject '-' hosts and all their users */
+ if (buf[1] == '@') {
+ if (innetgr((char *)&buf[2],
+ (char *)&hname, NULL, ypdomain))
+ return(-1);
+ } else {
+ if (__icheckhost(raddr,(char *)&buf[1],af,len))
+ return(-1);
+ }
+ break;
+ default: /* if no '+' or '-', do a simple match */
+ hostok = __icheckhost(raddr, buf, af, len);
+ break;
+ }
+ switch(*user) {
+ case '+':
+ if (!*(user+1)) { /* '+' matches all users */
+ userok = 1;
+ break;
+ }
+ if (*(user+1) == '@') /* match a user by netgroup */
+ userok = innetgr(user+2, NULL, ruser, ypdomain);
+ else /* match a user by direct specification */
+ userok = !(strcmp(ruser, user+1));
+ break;
+ case '-': /* if we matched a hostname, */
+ if (hostok) { /* check for user field rejections */
+ if (!*(user+1))
+ return(-1);
+ if (*(user+1) == '@') {
+ if (innetgr(user+2, NULL,
+ ruser, ypdomain))
+ return(-1);
+ } else {
+ if (!strcmp(ruser, user+1))
+ return(-1);
+ }
+ }
+ break;
+ default: /* no rejections: try to match the user */
+ if (hostok)
+ userok = !(strcmp(ruser,*user ? user : luser));
+ break;
+ }
+ if (hostok && userok)
+ return(0);
+ }
+ return (-1);
+}
+
+/*
+ * Returns "true" if match, 0 if no match.
+ */
+static int
+__icheckhost(raddr, lhost, af, len)
+ void *raddr;
+ register char *lhost;
+ int af, len;
+{
+ register struct hostent *hp;
+ char laddr[BUFSIZ]; /* xxx */
+ register char **pp;
+ int h_error;
+ int match;
+
+ /* Try for raw ip address first. */
+ if (inet_pton(af, lhost, laddr) == 1) {
+ if (memcmp(raddr, laddr, len) == 0)
+ return (1);
+ else
+ return (0);
+ }
+
+ /* Better be a hostname. */
+ if ((hp = getipnodebyname(lhost, af, AI_DEFAULT, &h_error)) == NULL)
+ return (0);
+
+ /* Spin through ip addresses. */
+ match = 0;
+ for (pp = hp->h_addr_list; *pp; ++pp)
+ if (!bcmp(raddr, *pp, len)) {
+ match = 1;
+ break;
+ }
+
+ freehostent(hp);
+ return (match);
+}