head	1.3;
access;
symbols
	RELEASE_8_3_0:1.3
	RELEASE_9_0_0:1.3
	RELEASE_7_4_0:1.3
	RELEASE_8_2_0:1.3
	RELEASE_6_EOL:1.3
	RELEASE_8_1_0:1.3
	RELEASE_7_3_0:1.3
	RELEASE_8_0_0:1.3
	RELEASE_7_2_0:1.3
	RELEASE_7_1_0:1.3
	RELEASE_6_4_0:1.3
	RELEASE_5_EOL:1.3
	RELEASE_7_0_0:1.3
	RELEASE_6_3_0:1.3
	PRE_XORG_7:1.3
	RELEASE_4_EOL:1.3
	RELEASE_6_2_0:1.3
	RELEASE_6_1_0:1.3
	RELEASE_5_5_0:1.3
	RELEASE_6_0_0:1.3
	RELEASE_5_4_0:1.3
	RELEASE_4_11_0:1.3
	RELEASE_5_3_0:1.3
	RELEASE_4_10_0:1.3
	RELEASE_5_2_1:1.3
	RELEASE_5_2_0:1.3
	RELEASE_4_9_0:1.3
	RELEASE_5_1_0:1.3
	RELEASE_4_8_0:1.2
	RELEASE_5_0_0:1.2
	RELEASE_4_7_0:1.2
	RELEASE_4_6_2:1.2
	RELEASE_4_6_1:1.2
	RELEASE_4_6_0:1.2
	RELEASE_5_0_DP1:1.2
	RELEASE_4_5_0:1.2
	RELEASE_4_4_0:1.2
	RELEASE_4_3_0:1.2
	RELEASE_4_2_0:1.2
	RELEASE_4_1_1:1.1;
locks; strict;
comment	@# @;


1.3
date	2003.05.04.10.36.29;	author leeym;	state Exp;
branches;
next	1.2;

1.2
date	2000.10.03.14.31.28;	author kevlo;	state Exp;
branches;
next	1.1;

1.1
date	2000.08.04.16.33.54;	author kevlo;	state Exp;
branches;
next	;


desc
@@


1.3
log
@1. simplify the patch
2. stop trying when /usr/src/usr.bin/telnet doesn't exists

Submitted by:	1. ijliao
@
text
@--- sys_bsd.c.orig	Sun May  4 16:03:33 2003
+++ sys_bsd.c	Sun May  4 16:04:12 2003
@@@@ -572,7 +572,7 @@@@
 	else
 		lmode &= ~LPASS8;
 #else
-	if (f & MODE_INBIN)
+	if (1)
 		tmp_tc.c_iflag &= ~ISTRIP;
 	else
 		tmp_tc.c_iflag |= ISTRIP;
@


1.2
log
@- Update ports to work more smoothly
- Change maintainer

PR: 21721
Submitted by: MAINTAINER
@
text
@d1 3
a3 3
--- sys_bsd.c.orig	Sat Sep 30 21:08:50 2000
+++ sys_bsd.c	Sat Sep 30 21:10:24 2000
@@@@ -593,10 +593,7 @@@@
d8 4
a11 7
-		tmp_tc.c_iflag &= ~ISTRIP;
-	else
-		tmp_tc.c_iflag |= ISTRIP;
+	tmp_tc.c_iflag &= ~ISTRIP;
 	if (f & MODE_OUTBIN) {
 		tmp_tc.c_cflag &= ~(CSIZE|PARENB);
 		tmp_tc.c_cflag |= CS8;
@


1.1
log
@Fix core dump problem
@
text
@d1 14
a14 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: src/usr.bin/telnet/commands.c,v 1.21.2.2 2000/07/20 15:03:28 ume 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
@

