summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJun-ichiro itojun Hagino <itojun@cvs.openbsd.org>1999-12-11 09:08:10 +0000
committerJun-ichiro itojun Hagino <itojun@cvs.openbsd.org>1999-12-11 09:08:10 +0000
commit940de116193b0bb58e1f997e389620cdf0e3e4c9 (patch)
tree5f7900b5d12fe6e648e8ab6afa5ff5a885694498
parent69769019608a9abf3cf9e3adf079ff14cc278787 (diff)
IPv6/IPv4 dual stack support. uses getaddrinfo() and getnameinfo()
throughout the code so please look at it with care (for auditing). XXX source routing is not available for IPv6 (even before I modify, it was not available for IPv4 anyways)
-rw-r--r--usr.bin/telnet/commands.c247
-rw-r--r--usr.bin/telnet/telnet.14
-rw-r--r--usr.bin/telnet/telnet_locl.h4
3 files changed, 78 insertions, 177 deletions
diff --git a/usr.bin/telnet/commands.c b/usr.bin/telnet/commands.c
index 8b1386b8a3f..6433aa4552d 100644
--- a/usr.bin/telnet/commands.c
+++ b/usr.bin/telnet/commands.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: commands.c,v 1.22 1999/12/07 01:10:29 deraadt Exp $ */
+/* $OpenBSD: commands.c,v 1.23 1999/12/11 09:08:08 itojun Exp $ */
/* $NetBSD: commands.c,v 1.14 1996/03/24 22:03:48 jtk Exp $ */
/*
@@ -2266,7 +2266,8 @@ tn(argc, argv)
int argc;
char *argv[];
{
- register struct hostent *host = 0, *alias = 0;
+ struct addrinfo hints, *res, *res0;
+ int error;
#if defined(AF_INET6)
struct sockaddr_in6 sin6;
#endif
@@ -2281,6 +2282,7 @@ tn(argc, argv)
char *srp = 0;
int srlen;
#endif
+ int retry;
char *cmd, *hostp = 0, *portp = 0, *user = 0, *aliasp = 0;
int family, port;
@@ -2359,70 +2361,28 @@ tn(argc, argv)
} else {
abort();
}
- } else {
-#endif
- memset (&sin, 0, sizeof(sin));
-#if defined(HAVE_INET_PTON) && defined(AF_INET6)
- memset (&sin6, 0, sizeof(sin6));
-
- if(inet_pton(AF_INET6, hostp, &sin6.sin6_addr)) {
- sin6.sin6_family = family = AF_INET6;
- sa = (struct sockaddr *)&sin6;
- sa_size = sizeof(sin6);
- strcpy(_hostname, hostp);
- hostname =_hostname;
- } else
-#endif
- if(inet_aton(hostp, &sin.sin_addr)){
- sin.sin_family = family = AF_INET;
- sa = (struct sockaddr *)&sin;
- sa_size = sizeof(sin);
- strcpy(_hostname, hostp);
- hostname = _hostname;
- } else {
-#ifdef HAVE_GETHOSTBYNAME2
- host = gethostbyname2(hostp, AF_INET6);
- if(host == NULL)
- host = gethostbyname2(hostp, AF_INET);
-#else
- host = gethostbyname(hostp);
-#endif
- if (host) {
- strncpy(_hostname, host->h_name, sizeof(_hostname));
- family = host->h_addrtype;
-
- switch(family) {
- case AF_INET:
- memset(&sin, 0, sizeof(sin));
- sa_size = sizeof(sin);
- sa = (struct sockaddr *)&sin;
- sin.sin_family = family;
- sin.sin_addr = *((struct in_addr *)(*host->h_addr_list));
- break;
-#if defined(AF_INET6) && defined(HAVE_STRUCT_SOCKADDR_IN6)
- case AF_INET6:
- memset(&sin6, 0, sizeof(sin6));
- sa_size = sizeof(sin6);
- sa = (struct sockaddr *)&sin6;
- sin6.sin6_family = family;
- sin6.sin6_addr = *((struct in6_addr *)(*host->h_addr_list));
- break;
+ } else
#endif
- default:
- fprintf(stderr, "Bad address family: %d\n", family);
- return 0;
- }
-
- _hostname[sizeof(_hostname)-1] = '\0';
- hostname = _hostname;
- } else {
- herror(hostp);
- return 0;
- }
- }
-#if defined(IP_OPTIONS) && defined(IPPROTO_IP)
+ {
+ hostname = hostp;
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_CANONNAME;
+ if (portp == NULL) {
+ portp = "telnet";
+ } else if (*portp == '-') {
+ portp++;
+ telnetport = 1;
+ }
+ error = getaddrinfo(hostp, portp, &hints, &res0);
+ if (error) {
+ warn("%s: %s", hostp, gai_strerror(error));
+ herror(hostp);
+ return 0;
+ }
}
-#endif
+#if 0
if (portp) {
if (*portp == '-') {
portp++;
@@ -2452,76 +2412,51 @@ tn(argc, argv)
}
telnetport = 1;
}
- switch(family) {
- case AF_INET:
- sin.sin_port = port;
- printf("Trying %s...\r\n", inet_ntoa(sin.sin_addr));
- break;
-#if defined(AF_INET6) && defined(HAVE_STRUCT_SOCKADDR_IN6)
- case AF_INET6: {
-#ifndef INET6_ADDRSTRLEN
-#define INET6_ADDRSTRLEN 46
#endif
- char buf[INET6_ADDRSTRLEN];
-
- sin6.sin6_port = port;
-#ifdef HAVE_INET_NTOP
- printf("Trying %s...\r\n", inet_ntop(AF_INET6,
- &sin6.sin6_addr,
- buf,
- sizeof(buf)));
-#endif
- break;
- }
-#endif
- default:
- abort();
- }
+ net = -1;
+ retry = 0;
+ for (res = res0; res; res = res->ai_next) {
+ if (1 /* retry */) {
+ char hbuf[MAXHOSTNAMELEN];
- do {
- net = socket(family, SOCK_STREAM, 0);
- if (net < 0) {
- perror("telnet: socket");
- return 0;
+ getnameinfo(res->ai_addr, res->ai_addrlen, hbuf, sizeof(hbuf),
+ NULL, 0, NI_NUMERICHOST);
+ printf("Trying %s...\r\n", hbuf);
}
+ net = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+ if (net < 0)
+ continue;
+
if (aliasp) {
- memset ((caddr_t)&ladr, 0, sizeof (ladr));
- temp = inet_addr(aliasp);
- if (temp != INADDR_NONE) {
- ladr.sin_addr.s_addr = temp;
- ladr.sin_family = AF_INET;
- alias = gethostbyaddr((char *)&temp, sizeof(temp), AF_INET);
- } else {
- alias = gethostbyname(aliasp);
- if (alias) {
- ladr.sin_family = alias->h_addrtype;
-#if defined(h_addr) /* In 4.3, this is a #define */
- memmove((caddr_t)&ladr.sin_addr,
- alias->h_addr_list[0], alias->h_length);
-#else /* defined(h_addr) */
- memmove((caddr_t)&ladr.sin_addr, alias->h_addr,
- alias->h_length);
-#endif /* defined(h_addr) */
- } else {
- herror(aliasp);
- return 0;
- }
+ struct addrinfo ahints, *ares;
+
+ memset(&ahints, 0, sizeof(ahints));
+ ahints.ai_family = PF_UNSPEC;
+ ahints.ai_socktype = SOCK_STREAM;
+ ahints.ai_flags = AI_PASSIVE;
+ error = getaddrinfo(aliasp, "0", &ahints, &ares);
+ if (error) {
+ warn("%s: %s", aliasp, gai_strerror(error));
+ close(net);
+ freeaddrinfo(ares);
+ continue;
}
- ladr.sin_port = htons(0);
-
- if (bind (net, (struct sockaddr *)&ladr, sizeof(ladr)) < 0) {
- perror(aliasp);;
+ if (bind(net, res->ai_addr, res->ai_addrlen) < 0) {
+ perror(aliasp);
(void) close(net); /* dump descriptor */
- return 0;
+ freeaddrinfo(ares);
+ continue;
}
- }
- #if defined(IP_OPTIONS) && defined(IPPROTO_IP)
- if (srp && setsockopt(net, IPPROTO_IP, IP_OPTIONS, (char *)srp, srlen) < 0)
+ freeaddrinfo(ares);
+ }
+#if defined(IP_OPTIONS) && defined(IPPROTO_IP)
+ if (srp && res->ai_family == AF_INET
+ && setsockopt(net, IPPROTO_IP, IP_OPTIONS, (char *)srp, srlen) < 0)
perror("setsockopt (IP_OPTIONS)");
#endif
#if defined(IPPROTO_IP) && defined(IP_TOS)
- {
+ if (res->ai_family == AF_INET) {
# if defined(HAS_GETTOS)
struct tosent *tp;
if (tos < 0 && (tp = gettosbyname("telnet", "tcp")))
@@ -2541,63 +2476,29 @@ tn(argc, argv)
perror("setsockopt (SO_DEBUG)");
}
- if (connect(net, sa, sa_size) < 0) {
- int retry = 0;
+ if (connect(net, res->ai_addr, res->ai_addrlen) < 0) {
+ char hbuf[MAXHOSTNAMELEN];
- if (host && host->h_addr_list[1]) {
- int oerrno = errno;
- retry = 1;
-
- switch(family) {
- case AF_INET :
- fprintf(stderr, "telnet: connect to address %s: ",
- inet_ntoa(sin.sin_addr));
- sin.sin_addr = *((struct in_addr *)(*++host->h_addr_list));
- break;
-#if defined(AF_INET6) && defined(HAVE_STRUCT_SOCKADDR_IN6)
- case AF_INET6: {
- char buf[INET6_ADDRSTRLEN];
-
- fprintf(stderr, "telnet: connect to address %s: ",
- inet_ntop(AF_INET6, &sin6.sin6_addr, buf,
- sizeof(buf)));
- sin6.sin6_addr = *((struct in6_addr *)(*++host->h_addr_list));
- break;
- }
-#endif
- default:
- abort();
- }
-
- errno = oerrno;
- perror(NULL);
+ getnameinfo(res->ai_addr, res->ai_addrlen, hbuf, sizeof(hbuf),
+ NULL, 0, NI_NUMERICHOST);
+ fprintf(stderr, "telnet: connect to address %s: ", hbuf);
- switch(family) {
- case AF_INET :
- printf("Trying %s...\r\n", inet_ntoa(sin.sin_addr));
- break;
-#if defined(AF_INET6) && defined(HAVE_STRUCT_SOCKADDR_IN6)
- case AF_INET6: {
- printf("Trying %s...\r\n", inet_ntop(AF_INET6,
- &sin6.sin6_addr,
- buf,
- sizeof(buf)));
- break;
- }
-#endif
- }
-
- (void) NetClose(net);
- continue;
- }
- perror("telnet: Unable to connect to remote host");
- return 0;
+ close(net);
+ net = -1;
+ retry++;
+ continue;
}
+
connected++;
#if defined(AUTHENTICATION) || defined(ENCRYPTION)
auth_encrypt_connect(connected);
#endif /* defined(AUTHENTICATION) */
- } while (connected == 0);
+ break;
+ }
+ freeaddrinfo(res0);
+ if (net < 0) {
+ return 0;
+ }
cmdrc(hostp, hostname);
if (autologin && user == NULL) {
struct passwd *pw;
diff --git a/usr.bin/telnet/telnet.1 b/usr.bin/telnet/telnet.1
index 21eb941c68a..4fc389c485a 100644
--- a/usr.bin/telnet/telnet.1
+++ b/usr.bin/telnet/telnet.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: telnet.1,v 1.19 1999/10/17 20:24:35 aaron Exp $
+.\" $OpenBSD: telnet.1,v 1.20 1999/12/11 09:08:09 itojun Exp $
.\" $NetBSD: telnet.1,v 1.5 1996/02/28 21:04:12 thorpej Exp $
.\"
.\" Copyright (c) 1983, 1990, 1993
@@ -1491,3 +1491,5 @@ the terminal's
.Ic eof
character is only recognized (and sent to the remote system)
when it is the first character on a line.
+.Pp
+Source routing is not supported yet for IPv6.
diff --git a/usr.bin/telnet/telnet_locl.h b/usr.bin/telnet/telnet_locl.h
index bbb39ed00ba..fb29f5383a2 100644
--- a/usr.bin/telnet/telnet_locl.h
+++ b/usr.bin/telnet/telnet_locl.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: telnet_locl.h,v 1.1 1998/03/12 04:57:44 art Exp $ */
+/* $OpenBSD: telnet_locl.h,v 1.2 1999/12/11 09:08:09 itojun Exp $ */
/* $KTH: telnet_locl.h,v 1.13 1997/11/03 21:37:55 assar Exp $ */
/*
@@ -86,7 +86,5 @@
#include "defines.h"
#include "types.h"
-#undef AF_INET6 /* XXX - it has not been tested and it doesn't exist yet */
-
/* prototypes */