aboutsummaryrefslogtreecommitdiffstats
path: root/chinese/telnet
diff options
context:
space:
mode:
authorkevlo <kevlo@FreeBSD.org>2000-08-05 00:33:54 +0800
committerkevlo <kevlo@FreeBSD.org>2000-08-05 00:33:54 +0800
commitea94492440e4e34dbc605bf32533c10af99982f8 (patch)
treea5b817f734f2d224fabc6765a43222950973861f /chinese/telnet
parent2ec15efed65c73a9f08ecb8ba34fc4d5743eaf7c (diff)
downloadfreebsd-ports-gnome-ea94492440e4e34dbc605bf32533c10af99982f8.tar.gz
freebsd-ports-gnome-ea94492440e4e34dbc605bf32533c10af99982f8.tar.zst
freebsd-ports-gnome-ea94492440e4e34dbc605bf32533c10af99982f8.zip
Fix core dump problem
Diffstat (limited to 'chinese/telnet')
-rw-r--r--chinese/telnet/files/patch-aa764
1 files changed, 764 insertions, 0 deletions
diff --git a/chinese/telnet/files/patch-aa b/chinese/telnet/files/patch-aa
new file mode 100644
index 000000000000..3252b93de2c9
--- /dev/null
+++ b/chinese/telnet/files/patch-aa
@@ -0,0 +1,764 @@
+--- commands.c.orig Mon Dec 28 09:42:46 1998
++++ commands.c Fri Aug 4 17:13:25 2000
+@@ -29,6 +29,8 @@
+ * 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/chinese/telnet/files/patch-aa,v 1.1 2000-08-04 16:33:54 kevlo Exp $
+ */
+
+ #ifndef lint
+@@ -50,6 +52,7 @@
+ #include <fcntl.h>
+ #endif /* CRAY */
+
++#include <string.h>
+ #include <signal.h>
+ #include <netdb.h>
+ #include <ctype.h>
+@@ -58,6 +61,7 @@
+ #include <errno.h>
+
+ #include <arpa/telnet.h>
++#include <arpa/inet.h>
+
+ #include "general.h"
+
+@@ -74,7 +78,7 @@
+ # endif /* vax */
+ #endif /* !defined(CRAY) && !defined(sysV88) */
+ #include <netinet/ip.h>
+-
++#include <netinet/ip6.h>
+
+ #ifndef MAXHOSTNAMELEN
+ #define MAXHOSTNAMELEN 64
+@@ -93,6 +97,8 @@
+ extern char **genget();
+ extern int Ambiguous();
+
++static int switch_af(struct addrinfo **aip);
++
+ static call();
+
+ typedef struct {
+@@ -2092,26 +2098,98 @@
+ }
+ #endif
+
+-unsigned long inet_addr();
++static const char *
++sockaddr_ntop(sa)
++ struct sockaddr *sa;
++{
++ void *addr;
++ static char addrbuf[INET6_ADDRSTRLEN];
++
++ switch (sa->sa_family) {
++ case AF_INET:
++ addr = &((struct sockaddr_in *)sa)->sin_addr;
++ break;
++#ifdef INET6
++ case AF_INET6:
++ addr = &((struct sockaddr_in6 *)sa)->sin6_addr;
++ break;
++#endif
++ default:
++ return NULL;
++ }
++ inet_ntop(sa->sa_family, addr, addrbuf, sizeof(addrbuf));
++ return addrbuf;
++}
++
++#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
++static int
++setpolicy(net, res, policy)
++ int net;
++ struct addrinfo *res;
++ char *policy;
++{
++ char *buf;
++ int level;
++ int optname;
++
++ if (policy == NULL)
++ return 0;
++
++ buf = ipsec_set_policy(policy, strlen(policy));
++ if (buf == NULL) {
++ printf("%s\n", ipsec_strerror());
++ return -1;
++ }
++ level = res->ai_family == AF_INET ? IPPROTO_IP : IPPROTO_IPV6;
++ optname = res->ai_family == AF_INET ? IP_IPSEC_POLICY : IPV6_IPSEC_POLICY;
++ if (setsockopt(net, level, optname, buf, ipsec_get_policylen(buf)) < 0){
++ perror("setsockopt");
++ return -1;
++ }
++
++ free(buf);
++}
++#endif
++
++#ifdef INET6
++/*
++ * When an Address Family related error happend, check if retry with
++ * another AF is possible or not.
++ * Return 1, if retry with another af is OK. Else, return 0.
++ */
++static int
++switch_af(aip)
++ struct addrinfo **aip;
++{
++ int nextaf;
++ struct addrinfo *ai;
++
++ ai = *aip;
++ nextaf = (ai->ai_family == AF_INET) ? AF_INET6 : AF_INET;
++ do
++ ai=ai->ai_next;
++ while (ai != NULL && ai->ai_family != nextaf);
++ *aip = ai;
++ if (*aip != NULL) {
++ return 1;
++ }
++ return 0;
++}
++#endif
+
+ int
+ tn(argc, argv)
+ int argc;
+ char *argv[];
+ {
+- register struct hostent *host = 0;
+- struct sockaddr_in sin;
+- struct servent *sp = 0;
+- unsigned long temp;
+- extern char *inet_ntoa();
+-#if defined(IP_OPTIONS) && defined(IPPROTO_IP)
+ char *srp = 0, *strrchr();
+- unsigned long sourceroute(), srlen;
+-#endif
++ int proto, opt;
++ int sourceroute(), srlen;
++ int srcroute = 0, result;
+ char *cmd, *hostp = 0, *portp = 0, *user = 0;
+-
+- /* clear the socket address prior to use */
+- bzero((char *)&sin, sizeof(sin));
++ char *src_addr = NULL;
++ struct addrinfo hints, *res, *res0 = NULL, *src_res, *src_res0 = NULL;
++ int error = 0, af_error = 0;
+
+ if (connected) {
+ printf("?Already connected to %s\n", hostname);
+@@ -2144,6 +2222,14 @@
+ autologin = 1;
+ continue;
+ }
++ if (strcmp(*argv, "-s") == 0) {
++ --argc; ++argv;
++ if (argc == 0)
++ goto usage;
++ src_addr = *argv++;
++ --argc;
++ continue;
++ }
+ if (hostp == 0) {
+ hostp = *argv++;
+ --argc;
+@@ -2155,116 +2241,138 @@
+ continue;
+ }
+ usage:
+- printf("usage: telnet [-l user] [-a] host-name [port]\n");
++ printf("usage: telnet [-l user] [-a] [-s src_addr] host-name [port]\n");
+ setuid(getuid());
+ return 0;
+ }
+ if (hostp == 0)
+ goto usage;
+
+-#if defined(IP_OPTIONS) && defined(IPPROTO_IP)
++ if (src_addr != NULL) {
++ memset(&hints, 0, sizeof(hints));
++ hints.ai_flags = AI_NUMERICHOST;
++ hints.ai_family = family;
++ hints.ai_socktype = SOCK_STREAM;
++ error = getaddrinfo(src_addr, 0, &hints, &src_res);
++ if (error == EAI_NODATA) {
++ hints.ai_flags = 0;
++ error = getaddrinfo(src_addr, 0, &hints, &src_res);
++ }
++ if (error != 0) {
++ fprintf(stderr, "%s: %s\n", src_addr, gai_strerror(error));
++ if (error == EAI_SYSTEM)
++ fprintf(stderr, "%s: %s\n", src_addr, strerror(errno));
++ setuid(getuid());
++ return 0;
++ }
++ src_res0 = src_res;
++ }
+ if (hostp[0] == '@' || hostp[0] == '!') {
+- if ((hostname = strrchr(hostp, ':')) == NULL)
++ if (
++#ifdef INET6
++ family == AF_INET6 ||
++#endif
++ (hostname = strrchr(hostp, ':')) == NULL)
+ hostname = strrchr(hostp, '@');
+ hostname++;
++ srcroute = 1;
++ } else
++ hostname = hostp;
++ if (!portp) {
++ telnetport = 1;
++ portp = "telnet";
++ } else if (*portp == '-') {
++ portp++;
++ telnetport = 1;
++ } else
++ telnetport = 0;
++
++ memset(&hints, 0, sizeof(hints));
++ hints.ai_flags = AI_NUMERICHOST;
++ hints.ai_family = family;
++ hints.ai_socktype = SOCK_STREAM;
++ error = getaddrinfo(hostname, portp, &hints, &res);
++ if (error) {
++ hints.ai_flags = AI_CANONNAME;
++ error = getaddrinfo(hostname, portp, &hints, &res);
++ }
++ if (error != 0) {
++ fprintf(stderr, "%s: %s\n", hostname, gai_strerror(error));
++ if (error == EAI_SYSTEM)
++ fprintf(stderr, "%s: %s\n", hostname, strerror(errno));
++ setuid(getuid());
++ goto fail;
++ }
++ if (hints.ai_flags == AI_NUMERICHOST) {
++ /* hostname has numeric */
++ int gni_err = 1;
++
++ if (doaddrlookup)
++ gni_err = getnameinfo(res->ai_addr, res->ai_addr->sa_len,
++ _hostname, sizeof(_hostname) - 1, NULL, 0,
++ NI_NAMEREQD);
++ if (gni_err != 0)
++ (void) strncpy(_hostname, hostp, sizeof(_hostname) - 1);
++ _hostname[sizeof(_hostname)-1] = '\0';
++ hostname = _hostname;
++ } else {
++ /* hostname has FQDN */
++ if (srcroute != 0)
++ (void) strncpy(_hostname, hostname, sizeof(_hostname) - 1);
++ else if (res->ai_canonname != NULL)
++ strcpy(_hostname, res->ai_canonname);
++ else
++ (void) strncpy(_hostname, hostp, sizeof(_hostname) - 1);
++ _hostname[sizeof(_hostname)-1] = '\0';
++ hostname = _hostname;
++ }
++ res0 = res;
++ af_again:
++ if (srcroute != 0) {
++ static char hostbuf[BUFSIZ];
++
++ if (af_error == 0) { /* save intermediate hostnames for retry */
++ strncpy(hostbuf, hostp, BUFSIZ - 1);
++ hostbuf[BUFSIZ - 1] = '\0';
++ } else
++ hostp = hostbuf;
+ srp = 0;
+- temp = sourceroute(hostp, &srp, &srlen);
+- if (temp == 0) {
+- herror(srp);
++ result = sourceroute(res, hostp, &srp, &srlen, &proto, &opt);
++ if (result == 0) {
++#ifdef INET6
++ if (family == AF_UNSPEC && af_error == 0 &&
++ switch_af(&res) == 1) {
++ af_error = 1;
++ goto af_again;
++ }
++#endif
+ setuid(getuid());
+- return 0;
+- } else if (temp == -1) {
++ goto fail;
++ } else if (result == -1) {
+ printf("Bad source route option: %s\n", hostp);
+ setuid(getuid());
+- return 0;
+- } else {
+- sin.sin_addr.s_addr = temp;
+- sin.sin_family = AF_INET;
++ goto fail;
+ }
+- } else {
+-#endif
+- temp = inet_addr(hostp);
+- if (temp != INADDR_NONE) {
+- sin.sin_addr.s_addr = temp;
+- sin.sin_family = AF_INET;
+- if (doaddrlookup)
+- host = gethostbyaddr((char *)&temp, sizeof(temp), AF_INET);
+- if (host)
+- (void) strncpy(_hostname, host->h_name, sizeof(_hostname));
+- else
+- (void) strncpy(_hostname, hostp, sizeof(_hostname));
+- _hostname[sizeof(_hostname)-1] = '\0';
+- hostname = _hostname;
+- } else {
+- host = gethostbyname(hostp);
+- if (host) {
+- sin.sin_family = host->h_addrtype;
+-#if defined(h_addr) /* In 4.3, this is a #define */
+- memmove((caddr_t)&sin.sin_addr,
+- host->h_addr_list[0], host->h_length);
+-#else /* defined(h_addr) */
+- memmove((caddr_t)&sin.sin_addr, host->h_addr, host->h_length);
+-#endif /* defined(h_addr) */
+- strncpy(_hostname, host->h_name, sizeof(_hostname));
+- _hostname[sizeof(_hostname)-1] = '\0';
+- hostname = _hostname;
+- } else {
+- herror(hostp);
+- setuid(getuid());
+- return 0;
+- }
+- }
+-#if defined(IP_OPTIONS) && defined(IPPROTO_IP)
+ }
+-#endif
+- if (portp) {
+- if (*portp == '-') {
+- portp++;
+- telnetport = 1;
+- } else
+- telnetport = 0;
+- sin.sin_port = atoi(portp);
+- if (sin.sin_port == 0) {
+- sp = getservbyname(portp, "tcp");
+- if (sp)
+- sin.sin_port = sp->s_port;
+- else {
+- printf("%s: bad port number\n", portp);
+- setuid(getuid());
+- return 0;
+- }
+- } else {
+-#if !defined(htons)
+- u_short htons P((unsigned short));
+-#endif /* !defined(htons) */
+- sin.sin_port = htons(sin.sin_port);
+- }
+- } else {
+- if (sp == 0) {
+- sp = getservbyname("telnet", "tcp");
+- if (sp == 0) {
+- fprintf(stderr, "telnet: tcp/telnet: unknown service\n");
+- setuid(getuid());
+- return 0;
+- }
+- sin.sin_port = sp->s_port;
+- }
+- telnetport = 1;
+- }
+- printf("Trying %s...\n", inet_ntoa(sin.sin_addr));
+ do {
+- net = socket(AF_INET, SOCK_STREAM, 0);
++ printf("Trying %s...\n", sockaddr_ntop(res->ai_addr));
++ net = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+ setuid(getuid());
+ if (net < 0) {
++#ifdef INET6
++ if (family == AF_UNSPEC && af_error == 0 &&
++ switch_af(&res) == 1) {
++ af_error = 1;
++ goto af_again;
++ }
++#endif
+ perror("telnet: socket");
+- return 0;
++ goto fail;
+ }
+-#if defined(IP_OPTIONS) && defined(IPPROTO_IP)
+- if (srp && setsockopt(net, IPPROTO_IP, IP_OPTIONS, (char *)srp, srlen) < 0)
+- perror("setsockopt (IP_OPTIONS)");
+-#endif
++ if (srp && setsockopt(net, proto, opt, (char *)srp, srlen) < 0)
++ perror("setsockopt (source route)");
+ #if defined(IPPROTO_IP) && defined(IP_TOS)
+- {
++ if (res->ai_family == PF_INET) {
+ # if defined(HAS_GETTOS)
+ struct tosent *tp;
+ if (tos < 0 && (tp = gettosbyname("telnet", "tcp")))
+@@ -2284,30 +2392,63 @@
+ perror("setsockopt (SO_DEBUG)");
+ }
+
+- if (connect(net, (struct sockaddr *)&sin, sizeof (sin)) < 0) {
+-#if defined(h_addr) /* In 4.3, this is a #define */
+- if (host && host->h_addr_list[1]) {
+- int oerrno = errno;
+-
+- fprintf(stderr, "telnet: connect to address %s: ",
+- inet_ntoa(sin.sin_addr));
+- errno = oerrno;
+- perror((char *)0);
+- host->h_addr_list++;
+- memcpy((caddr_t)&sin.sin_addr,
+- host->h_addr_list[0], host->h_length);
++ if (src_addr != NULL) {
++ for (src_res = src_res0; src_res != 0; src_res = src_res->ai_next)
++ if (src_res->ai_family == res->ai_family)
++ break;
++ if (src_res == NULL)
++ src_res = src_res0;
++ if (bind(net, src_res->ai_addr, src_res->ai_addrlen) == -1) {
++#ifdef INET6
++ if (family == AF_UNSPEC && af_error == 0 &&
++ switch_af(&res) == 1) {
++ af_error = 1;
++ (void) NetClose(net);
++ goto af_again;
++ }
++#endif
++ perror("bind");
++ (void) NetClose(net);
++ goto fail;
++ }
++ }
++#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
++ if (setpolicy(net, res, ipsec_policy_in) < 0) {
++ (void) NetClose(net);
++ goto fail;
++ }
++ if (setpolicy(net, res, ipsec_policy_out) < 0) {
++ (void) NetClose(net);
++ goto fail;
++ }
++#endif
++
++ if (connect(net, res->ai_addr, res->ai_addrlen) < 0) {
++ struct addrinfo *next;
++
++ next = res->ai_next;
++ /* If already an af failed, only try same af. */
++ if (af_error != 0)
++ while (next != NULL && next->ai_family != res->ai_family)
++ next = next->ai_next;
++ warn("connect to address %s", sockaddr_ntop(res->ai_addr));
++ if (next != NULL) {
++ res = next;
+ (void) NetClose(net);
+ continue;
+ }
+-#endif /* defined(h_addr) */
+- perror("telnet: Unable to connect to remote host");
+- return 0;
++ warnx("Unable to connect to remote host");
++ (void) NetClose(net);
++ goto fail;
+ }
+ connected++;
+ #if defined(AUTHENTICATION)
+ auth_encrypt_connect(connected);
+ #endif /* defined(AUTHENTICATION) */
+ } while (connected == 0);
++ freeaddrinfo(res0);
++ if (src_res0 != NULL)
++ freeaddrinfo(src_res0);
+ cmdrc(hostp, hostname);
+ if (autologin && user == NULL) {
+ struct passwd *pw;
+@@ -2331,6 +2472,12 @@
+ (void) NetClose(net);
+ ExitString("Connection closed by foreign host.\n",1);
+ /*NOTREACHED*/
++ fail:
++ if (res0 != NULL)
++ freeaddrinfo(res0);
++ if (src_res0 != NULL)
++ freeaddrinfo(src_res0);
++ return 0;
+ }
+
+ #define HELPINDENT (sizeof ("connect"))
+@@ -2646,8 +2793,6 @@
+ fclose(rcfile);
+ }
+
+-#if defined(IP_OPTIONS) && defined(IPPROTO_IP)
+-
+ /*
+ * Source route is handed in as
+ * [!]@hop1@hop2...[@|:]dst
+@@ -2661,6 +2806,10 @@
+ * be the address to connect() to.
+ *
+ * Arguments:
++ *
++ * res: ponter to addrinfo structure which contains sockaddr to
++ * the host to connect to.
++ *
+ * arg: pointer to route list to decipher
+ *
+ * cpp: If *cpp is not equal to NULL, this is a
+@@ -2670,9 +2819,18 @@
+ * lenp: pointer to an integer that contains the
+ * length of *cpp if *cpp != NULL.
+ *
++ * protop: pointer to an integer that should be filled in with
++ * appropriate protocol for setsockopt, as socket
++ * protocol family.
++ *
++ * optp: pointer to an integer that should be filled in with
++ * appropriate option for setsockopt, as socket protocol
++ * family.
++ *
+ * Return values:
+ *
+- * Returns the address of the host to connect to. If the
++ * If the return value is 1, then all operations are
++ * successful. If the
+ * return value is -1, there was a syntax error in the
+ * option, either unknown characters, or too many hosts.
+ * If the return value is 0, one of the hostnames in the
+@@ -2686,21 +2844,32 @@
+ * *lenp: This will be filled in with how long the option
+ * pointed to by *cpp is.
+ *
++ * *protop: This will be filled in with appropriate protocol for
++ * setsockopt, as socket protocol family.
++ *
++ * *optp: This will be filled in with appropriate option for
++ * setsockopt, as socket protocol family.
+ */
+- unsigned long
+-sourceroute(arg, cpp, lenp)
++int
++sourceroute(ai, arg, cpp, lenp, protop, optp)
++ struct addrinfo *ai;
+ char *arg;
+ char **cpp;
+ int *lenp;
++ int *protop;
++ int *optp;
+ {
+- static char lsr[44];
++ static char buf[1024 + ALIGNBYTES]; /*XXX*/
++ struct cmsghdr *cmsg;
+ #ifdef sysV88
+ static IOPTN ipopt;
+ #endif
+- char *cp, *cp2, *lsrp, *lsrep;
++ char *cp, *cp2, *lsrp, *ep;
+ register int tmp;
+- struct in_addr sin_addr;
+- register struct hostent *host = 0;
++ struct sockaddr_in *sin;
++ struct sockaddr_in6 *sin6;
++ struct addrinfo hints, *res;
++ int error;
+ register char c;
+
+ /*
+@@ -2708,23 +2877,46 @@
+ * at least 7 bytes for the option.
+ */
+ if (cpp == NULL || lenp == NULL)
+- return((unsigned long)-1);
+- if (*cpp != NULL && *lenp < 7)
+- return((unsigned long)-1);
++ return -1;
++ if (*cpp != NULL) {
++ switch (res->ai_family) {
++ case AF_INET:
++ if (*lenp < 7)
++ return -1;
++ break;
++#ifdef INET6
++ case AF_INET6:
++ if (*lenp < CMSG_SPACE(sizeof(struct ip6_rthdr) +
++ sizeof(struct in6_addr)))
++ return -1;
++ break;
++#endif
++ }
++ }
+ /*
+ * Decide whether we have a buffer passed to us,
+ * or if we need to use our own static buffer.
+ */
+ if (*cpp) {
+ lsrp = *cpp;
+- lsrep = lsrp + *lenp;
++ ep = lsrp + *lenp;
+ } else {
+- *cpp = lsrp = lsr;
+- lsrep = lsrp + 44;
++ *cpp = lsrp = (char *)ALIGN(buf);
++ ep = lsrp + 1024;
+ }
+
+ cp = arg;
+
++#ifdef INET6
++ if (ai->ai_family == AF_INET6) {
++ cmsg = inet6_rthdr_init(*cpp, IPV6_RTHDR_TYPE_0);
++ if (*cp != '@')
++ return -1;
++ *protop = IPPROTO_IPV6;
++ *optp = IPV6_PKTOPTIONS;
++ } else
++#endif
++ {
+ /*
+ * Next, decide whether we have a loose source
+ * route or a strict source route, and fill in
+@@ -2745,19 +2937,26 @@
+ #endif
+
+ if (*cp != '@')
+- return((unsigned long)-1);
++ return -1;
+
+ #ifndef sysV88
+ lsrp++; /* skip over length, we'll fill it in later */
+ *lsrp++ = 4;
+ #endif
++ *protop = IPPROTO_IP;
++ *optp = IP_OPTIONS;
++ }
+
+ cp++;
+-
+- sin_addr.s_addr = 0;
+-
++ memset(&hints, 0, sizeof(hints));
++ hints.ai_family = ai->ai_family;
++ hints.ai_socktype = SOCK_STREAM;
+ for (c = 0;;) {
+- if (c == ':')
++ if (
++#ifdef INET6
++ ai->ai_family != AF_INET6 &&
++#endif
++ c == ':')
+ cp2 = 0;
+ else for (cp2 = cp; c = *cp2; cp2++) {
+ if (c == ',') {
+@@ -2766,7 +2965,11 @@
+ cp2++;
+ } else if (c == '@') {
+ *cp2++ = '\0';
+- } else if (c == ':') {
++ } else if (
++#ifdef INET6
++ ai->ai_family != AF_INET6 &&
++#endif
++ c == ':') {
+ *cp2++ = '\0';
+ } else
+ continue;
+@@ -2775,21 +2978,32 @@
+ if (!c)
+ cp2 = 0;
+
+- if ((tmp = inet_addr(cp)) != -1) {
+- sin_addr.s_addr = tmp;
+- } else if (host = gethostbyname(cp)) {
+-#if defined(h_addr)
+- memcpy((caddr_t)&sin_addr,
+- host->h_addr_list[0], host->h_length);
+-#else
+- memcpy((caddr_t)&sin_addr, host->h_addr, host->h_length);
+-#endif
+- } else {
++ hints.ai_flags = AI_NUMERICHOST;
++ error = getaddrinfo(cp, NULL, &hints, &res);
++ if (error == EAI_NODATA) {
++ hints.ai_flags = 0;
++ error = getaddrinfo(cp, NULL, &hints, &res);
++ }
++ if (error != 0) {
++ fprintf(stderr, "%s: %s\n", cp, gai_strerror(error));
++ if (error == EAI_SYSTEM)
++ fprintf(stderr, "%s: %s\n", cp,
++ strerror(errno));
+ *cpp = cp;
+ return(0);
+ }
+- memcpy(lsrp, (char *)&sin_addr, 4);
++#ifdef INET6
++ if (res->ai_family == AF_INET6) {
++ sin6 = (struct sockaddr_in6 *)res->ai_addr;
++ inet6_rthdr_add(cmsg, &sin6->sin6_addr,
++ IPV6_RTHDR_LOOSE);
++ } else
++#endif
++ {
++ sin = (struct sockaddr_in *)res->ai_addr;
++ memcpy(lsrp, (char *)&sin->sin_addr, 4);
+ lsrp += 4;
++ }
+ if (cp2)
+ cp = cp2;
+ else
+@@ -2797,14 +3011,31 @@
+ /*
+ * Check to make sure there is space for next address
+ */
+- if (lsrp + 4 > lsrep)
+- return((unsigned long)-1);
+- }
++#ifdef INET6
++ if (res->ai_family == AF_INET6) {
++ if (((char *)CMSG_DATA(cmsg) +
++ sizeof(struct ip6_rthdr) +
++ ((inet6_rthdr_segments(cmsg) + 1) *
++ sizeof(struct in6_addr))) > ep)
++ return -1;
++ } else
++#endif
++ if (lsrp + 4 > ep)
++ return -1;
++ freeaddrinfo(res);
++ }
++#ifdef INET6
++ if (res->ai_family == AF_INET6) {
++ inet6_rthdr_lasthop(cmsg, IPV6_RTHDR_LOOSE);
++ *lenp = cmsg->cmsg_len;
++ } else
++#endif
++ {
+ #ifndef sysV88
+ if ((*(*cpp+IPOPT_OLEN) = lsrp - *cpp) <= 7) {
+ *cpp = 0;
+ *lenp = 0;
+- return((unsigned long)-1);
++ return -1;
+ }
+ *lsrp++ = IPOPT_NOP; /* 32 bit word align it */
+ *lenp = lsrp - *cpp;
+@@ -2813,11 +3044,12 @@
+ if (ipopt.io_len <= 5) { /* Is 3 better ? */
+ *cpp = 0;
+ *lenp = 0;
+- return((unsigned long)-1);
++ return -1;
+ }
+ *lenp = sizeof(ipopt);
+ *cpp = (char *) &ipopt;
+ #endif
+- return(sin_addr.s_addr);
++ }
++ freeaddrinfo(res);
++ return 1;
+ }
+-#endif