summaryrefslogtreecommitdiffstats
path: root/usr.bin
diff options
context:
space:
mode:
authorshin <shin@FreeBSD.org>2000-01-27 09:28:38 +0000
committershin <shin@FreeBSD.org>2000-01-27 09:28:38 +0000
commitce15efb7c04858f00b57c16093d4a3043809048e (patch)
tree8b3d00f78a4a5a34cc3b17e29c28b4472d93a35c /usr.bin
parentdcbae417f8f4365a5eea807290162acd308b720d (diff)
downloadFreeBSD-src-ce15efb7c04858f00b57c16093d4a3043809048e.zip
FreeBSD-src-ce15efb7c04858f00b57c16093d4a3043809048e.tar.gz
another tcp apps IPv6 updates.(should be make world safe)
ftp, telnet, ftpd, faithd also telnet related sync with crypto, secure, kerberosIV Obtained from: KAME project
Diffstat (limited to 'usr.bin')
-rw-r--r--usr.bin/ftp/Makefile1
-rw-r--r--usr.bin/ftp/extern.h2
-rw-r--r--usr.bin/ftp/fetch.c107
-rw-r--r--usr.bin/ftp/ftp.122
-rw-r--r--usr.bin/ftp/ftp.c416
-rw-r--r--usr.bin/ftp/ftp_var.h11
-rw-r--r--usr.bin/ftp/main.c69
-rw-r--r--usr.bin/ftp/util.c17
-rw-r--r--usr.bin/telnet/Makefile6
-rw-r--r--usr.bin/telnet/commands.c428
-rw-r--r--usr.bin/telnet/externs.h10
-rw-r--r--usr.bin/telnet/main.c46
-rw-r--r--usr.bin/telnet/telnet.111
13 files changed, 802 insertions, 344 deletions
diff --git a/usr.bin/ftp/Makefile b/usr.bin/ftp/Makefile
index bbd82e2..b5a59cc 100644
--- a/usr.bin/ftp/Makefile
+++ b/usr.bin/ftp/Makefile
@@ -10,6 +10,7 @@ PROG= ftp
SRCS= cmds.c cmdtab.c complete.c domacro.c fetch.c ftp.c main.c ruserpass.c \
util.c
+CFLAGS+=-DINET6 -g
LDADD+= -ledit -ltermcap
DPADD+= ${LIBEDIT} ${LIBTERMCAP}
diff --git a/usr.bin/ftp/extern.h b/usr.bin/ftp/extern.h
index a8ac97b..7841f7b 100644
--- a/usr.bin/ftp/extern.h
+++ b/usr.bin/ftp/extern.h
@@ -73,7 +73,7 @@ int getreply __P((int));
int globulize __P((char **));
char *gunique __P((const char *));
void help __P((int, char **));
-char *hookup __P((const char *, int));
+char *hookup __P((const char *, char *));
void idle __P((int, char **));
int initconn __P((void));
void intr __P((void));
diff --git a/usr.bin/ftp/fetch.c b/usr.bin/ftp/fetch.c
index 1d73c0f..62b64e9 100644
--- a/usr.bin/ftp/fetch.c
+++ b/usr.bin/ftp/fetch.c
@@ -57,6 +57,7 @@ __RCSID_SOURCE("$NetBSD: fetch.c,v 1.16.2.1 1997/11/18 01:00:22 mellon Exp $");
#include <ctype.h>
#include <err.h>
+#include <errno.h>
#include <netdb.h>
#include <fcntl.h>
#include <signal.h>
@@ -67,6 +68,11 @@ __RCSID_SOURCE("$NetBSD: fetch.c,v 1.16.2.1 1997/11/18 01:00:22 mellon Exp $");
#include "ftp_var.h"
+/* wrapper for KAME-special getnameinfo() */
+#ifndef NI_WITHSCOPEID
+#define NI_WITHSCOPEID 0
+#endif
+
static int url_get __P((const char *, const char *));
void aborthttp __P((int));
@@ -91,9 +97,11 @@ url_get(origline, proxyenv)
const char *origline;
const char *proxyenv;
{
- struct sockaddr_in sin;
+ struct addrinfo hints;
+ struct addrinfo *res;
+ char nameinfo[2 * INET6_ADDRSTRLEN + 1];
int i, out, isftpurl;
- u_int16_t port;
+ char *port;
volatile int s;
size_t len;
char c, *cp, *ep, *portnum, *path, buf[4096];
@@ -101,6 +109,7 @@ url_get(origline, proxyenv)
char *line, *proxy, *host;
volatile sig_t oldintr;
off_t hashbytes;
+ int error;
s = -1;
proxy = NULL;
@@ -172,68 +181,69 @@ url_get(origline, proxyenv)
path = line;
}
- portnum = strchr(host, ':'); /* find portnum */
- if (portnum != NULL)
+ if (*host == '[' && (portnum = strrchr(host, ']'))) { /* IPv6 URL */
*portnum++ = '\0';
-
+ host++;
+ if (*portnum == ':')
+ portnum++;
+ else
+ portnum = NULL;
+ } else {
+ portnum = strrchr(host, ':'); /* find portnum */
+ if (portnum != NULL)
+ *portnum++ = '\0';
+ }
+
if (debug)
printf("host %s, port %s, path %s, save as %s.\n",
host, portnum, path, savefile);
- memset(&sin, 0, sizeof(sin));
- sin.sin_family = AF_INET;
-
- if (isdigit((unsigned char)host[0])) {
- if (inet_aton(host, &sin.sin_addr) == 0) {
- warnx("Invalid IP address: %s", host);
- goto cleanup_url_get;
- }
- } else {
- struct hostent *hp;
-
- hp = gethostbyname(host);
- if (hp == NULL) {
- warnx("%s: %s", host, hstrerror(h_errno));
- goto cleanup_url_get;
- }
- if (hp->h_addrtype != AF_INET) {
- warnx("%s: not an Internet address?", host);
- goto cleanup_url_get;
- }
- memcpy(&sin.sin_addr, hp->h_addr, hp->h_length);
- }
-
if (! EMPTYSTRING(portnum)) {
- char *ep;
- long nport;
-
- nport = strtol(portnum, &ep, 10);
- if (nport < 1 || nport > 0xffff || *ep != '\0') {
- warnx("Invalid port: %s", portnum);
- goto cleanup_url_get;
- }
- port = htons(nport);
+ port = portnum;
} else
port = httpport;
- sin.sin_port = port;
- s = socket(AF_INET, SOCK_STREAM, 0);
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ error = getaddrinfo(host, port, &hints, &res);
+ if (error) {
+ warnx("%s: %s", host, gai_strerror(error));
+ if (error = EAI_SYSTEM)
+ warnx("%s: %s", host, strerror(errno));
+ goto cleanup_url_get;
+ }
+
+ while (1)
+ {
+ s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (s == -1) {
warn("Can't create socket");
goto cleanup_url_get;
}
if (dobind && bind(s, (struct sockaddr *)&bindto,
- sizeof(bindto)) == -1) {
- warn("Can't bind to %s", inet_ntoa(bindto.sin_addr));
+ ((struct sockaddr *)&bindto)->sa_len) == -1) {
+ getnameinfo((struct sockaddr *)&bindto,
+ ((struct sockaddr *)&bindto)->sa_len,
+ nameinfo, sizeof(nameinfo), NULL, 0,
+ NI_NUMERICHOST|NI_WITHSCOPEID);
+ /* XXX check error? */
+ warn("Can't bind to %s", nameinfo);
goto cleanup_url_get;
}
- if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) == -1) {
- warn("Can't connect to %s", host);
+ if (connect(s, res->ai_addr, res->ai_addrlen) < 0) {
+ close(s);
+ res = res->ai_next;
+ if (res)
+ continue;
goto cleanup_url_get;
}
+ break;
+ }
+
/*
* Construct and send the request. We're expecting a return
* status of "200". Proxy requests don't want leading /.
@@ -645,3 +655,14 @@ parsed_url:
disconnect(0, NULL);
return (rval);
}
+
+int
+isurl(p)
+ const char *p;
+{
+ if (strncasecmp(p, FTP_URL, sizeof(FTP_URL) - 1) == 0
+ || strncasecmp(p, HTTP_URL, sizeof(HTTP_URL) - 1) == 0) {
+ return 1;
+ }
+ return 0;
+}
diff --git a/usr.bin/ftp/ftp.1 b/usr.bin/ftp/ftp.1
index 59b371f..a112709 100644
--- a/usr.bin/ftp/ftp.1
+++ b/usr.bin/ftp/ftp.1
@@ -34,7 +34,7 @@
.\"
.\" @(#)ftp.1 8.3 (Berkeley) 10/9/94
.\"
-.Dd August 18, 1997
+.Dd January 27, 2000
.Dt FTP 1
.Os BSD 4.2
.Sh NAME
@@ -61,6 +61,7 @@ is the user interface to the
standard File Transfer Protocol.
The program allows a user to transfer files to and from a
remote network site.
+The version supports IPv6 (Internet protocol version 6), as well as IPv4.
.Pp
The latter three usage formats will fetch a file using either the
HTTP or FTP protocols into the current directory.
@@ -682,7 +683,18 @@ through a gateway router or host that controls the directionality of
traffic.
(Note that though ftp servers are required to support the
.Dv PASV
-command by RFC 1123, some do not.)
+command by RFC 1123, some do not.
+Please note that if you are connecting to IPv6 ftp server,
+the program will use
+.Dv EPSV/EPRT
+pair and
+.Dv LPSV/LPRT
+pair,
+instead of
+.Dv PASV
+and
+.Dv PORT .
+The meaning is the same.)
.It Ic preserve
Toggle preservation of modification times on retrieved files.
.It Ic progress
@@ -1402,6 +1414,8 @@ fetching of files, ftp and http URLs, and modification time
preservation were implemented in
.Nx 1.3
by Luke Mewburn, with assistance from Jason Thorpe.
+.Pp
+IPv6 support was added by WIDE/KAME Project.
.Sh BUGS
Correct execution of many commands depends upon proper behavior
by the remote server.
@@ -1416,3 +1430,7 @@ to and from
.Bx 4.2
servers using the ascii type.
Avoid this problem by using the binary image type.
+.Pp
+Proxying functionalities, such as
+.Ev ftp_proxy ,
+may not work for IPv6 connection.
diff --git a/usr.bin/ftp/ftp.c b/usr.bin/ftp/ftp.c
index d2edd01..3c7da3f 100644
--- a/usr.bin/ftp/ftp.c
+++ b/usr.bin/ftp/ftp.c
@@ -71,68 +71,93 @@ __RCSID_SOURCE("$NetBSD: ftp.c,v 1.29.2.1 1997/11/18 01:01:04 mellon Exp $");
#include "ftp_var.h"
-struct sockaddr_in hisctladdr;
-struct sockaddr_in data_addr;
+/* wrapper for KAME-special getnameinfo() */
+#ifndef NI_WITHSCOPEID
+#define NI_WITHSCOPEID 0
+#endif
+
+extern int h_errno;
+
int data = -1;
int abrtflag = 0;
jmp_buf ptabort;
int ptabflg;
int ptflag = 0;
-struct sockaddr_in myctladdr;
-
FILE *cin, *cout;
+union sockunion {
+ struct sockinet {
+ u_char si_len;
+ u_char si_family;
+ u_short si_port;
+ } su_si;
+ struct sockaddr_in su_sin;
+ struct sockaddr_in6 su_sin6;
+};
+#define su_len su_si.si_len
+#define su_family su_si.si_family
+#define su_port su_si.si_port
+
+union sockunion myctladdr, hisctladdr, data_addr;
+
char *
hookup(host, port)
const char *host;
- int port;
+ char *port;
{
- struct hostent *hp = NULL;
- int s, len, tos;
+ int s, len, tos, error;
+ struct addrinfo hints, *res, *res0;
static char hostnamebuf[MAXHOSTNAMELEN];
- memset((void *)&hisctladdr, 0, sizeof(hisctladdr));
- if (inet_aton(host, &hisctladdr.sin_addr) != 0) {
- hisctladdr.sin_family = AF_INET;
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_flags = AI_CANONNAME;
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = 0;
+ error = getaddrinfo(host, port, &hints, &res0);
+ if (error) {
+ warnx("%s: %s", host, gai_strerror(error));
+ if (error == EAI_SYSTEM)
+ warnx("%s: %s", host, strerror(errno));
+ code = -1;
+ return (0);
+ }
+
+ res = res0;
+ if (res->ai_canonname)
+ hostname = res->ai_canonname;
+ else {
(void) strncpy(hostnamebuf, host, sizeof(hostnamebuf));
- } else {
- hp = gethostbyname(host);
- if (hp == NULL) {
- warnx("%s: %s", host, hstrerror(h_errno));
- code = -1;
- return ((char *) 0);
- }
- hisctladdr.sin_family = hp->h_addrtype;
- memcpy(&hisctladdr.sin_addr, hp->h_addr_list[0],
- MIN(hp->h_length,sizeof(hisctladdr.sin_addr)));
- (void) strncpy(hostnamebuf, hp->h_name, sizeof(hostnamebuf));
+ hostname = hostnamebuf;
}
- hostnamebuf[sizeof(hostnamebuf) - 1] = '\0';
- hostname = hostnamebuf;
- hisctladdr.sin_port = port;
while (1) {
- if ((s = socket(hisctladdr.sin_family, SOCK_STREAM, 0)) == -1) {
+ s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+ if (s < 0) {
warn("socket");
code = -1;
return (0);
}
- if (dobind && bind(s, (struct sockaddr *)&bindto,
- sizeof(bindto)) == -1) {
+ if (dobind &&
+ bind(s, (struct sockaddr *)&bindto,
+ ((struct sockaddr *)&bindto)->sa_len) == -1) {
warn("bind");
- code = -1;
- goto bad;
+ goto next;
}
- if (connect(s, (struct sockaddr *)&hisctladdr,
- sizeof(hisctladdr)) == 0)
+ if (connect(s, res->ai_addr, res->ai_addrlen) == 0)
break;
- if (hp && *++hp->h_addr_list) {
- warnc(errno, "connect to address %s",
- inet_ntoa(hisctladdr.sin_addr));
- memcpy(&hisctladdr.sin_addr, hp->h_addr_list[0],
- MIN(hp->h_length,sizeof(hisctladdr.sin_addr)));
- printf("Trying %s...\n",
- inet_ntoa(hisctladdr.sin_addr));
+ next:
+ if (res->ai_next) {
+ char hname[INET6_ADDRSTRLEN];
+ getnameinfo(res->ai_addr, res->ai_addrlen,
+ hname, sizeof(hname) - 1, NULL, 0,
+ NI_NUMERICHOST|NI_WITHSCOPEID);
+ warn("connect to address %s", hname);
+ res = res->ai_next;
+ getnameinfo(res->ai_addr, res->ai_addrlen,
+ hname, sizeof(hname) - 1, NULL, 0,
+ NI_NUMERICHOST|NI_WITHSCOPEID);
+ printf("Trying %s...\n", hname);
(void)close(s);
continue;
}
@@ -140,6 +165,7 @@ hookup(host, port)
code = -1;
goto bad;
}
+ memcpy(&hisctladdr, res->ai_addr, res->ai_addrlen);
len = sizeof(myctladdr);
if (getsockname(s, (struct sockaddr *)&myctladdr, &len) < 0) {
warn("getsockname");
@@ -147,9 +173,12 @@ hookup(host, port)
goto bad;
}
#ifdef IP_TOS
- tos = IPTOS_LOWDELAY;
+ if (myctladdr.su_family == AF_INET)
+ {
+ tos = IPTOS_LOWDELAY;
if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0)
warn("setsockopt TOS (ignored)");
+ }
#endif
cin = fdopen(s, "r");
cout = fdopen(s, "w");
@@ -324,11 +353,25 @@ getreply(expecteof)
}
if (dig < 4 && isdigit((unsigned char)c))
code = code * 10 + (c - '0');
- if (!pflag && code == 227)
- pflag = 1;
- if (dig > 4 && pflag == 1 && isdigit((unsigned char)c))
+ switch (pflag) {
+ case 0:
+ if (code == 227 || code == 228) {
+ /* result for PASV/LPSV */
+ pflag = 1;
+ /* fall through */
+ } else if (code == 229) {
+ /* result for EPSV */
+ pflag = 1;
+ pflag = 100;
+ break;
+ } else
+ break;
+ case 1:
+ if (!(dig > 4 && isdigit((unsigned char)c)))
+ break;
pflag = 2;
- if (pflag == 2) {
+ /* fall through */
+ case 2:
if (c != '\r' && c != ')' &&
pt < &pasv[sizeof(pasv)-1])
*pt++ = c;
@@ -336,6 +379,11 @@ getreply(expecteof)
*pt = '\0';
pflag = 3;
}
+ break;
+ case 100:
+ if (dig > 4 && c == '(')
+ pflag = 2;
+ break;
}
if (dig == 4 && c == '-') {
if (continuation)
@@ -1080,17 +1128,29 @@ initconn()
char *p, *a;
int result, len, tmpno = 0;
int on = 1;
- int a0, a1, a2, a3, p0, p1;
- int ports;
+ int error, ports;
+ u_int af;
+ u_int hal, h[16];
+ u_int pal, prt[2];
+ char *pasvcmd;
+
+#ifdef INET6
+ if (myctladdr.su_family == AF_INET6
+ && (IN6_IS_ADDR_LINKLOCAL(&myctladdr.su_sin6.sin6_addr)
+ || IN6_IS_ADDR_SITELOCAL(&myctladdr.su_sin6.sin6_addr))) {
+ warnx("use of scoped address can be troublesome");
+ }
+#endif
if (passivemode) {
- data = socket(AF_INET, SOCK_STREAM, 0);
+ data_addr = myctladdr;
+ data = socket(data_addr.su_family, SOCK_STREAM, 0);
if (data < 0) {
warn("socket");
return (1);
}
if (dobind && bind(data, (struct sockaddr *)&bindto,
- sizeof(bindto)) == -1) {
+ ((struct sockaddr *)&bindto)->sa_len) == -1) {
warn("bind");
goto bad;
}
@@ -1098,47 +1158,166 @@ initconn()
setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on,
sizeof(on)) < 0)
warn("setsockopt (ignored)");
- if (command("PASV") != COMPLETE) {
+ switch (data_addr.su_family) {
+ case AF_INET:
+ result = command(pasvcmd = "EPSV");
+ if (code / 10 == 22 && code != 229) {
+ puts("wrong server: return code must be 229");
+ result = COMPLETE + 1;
+ }
+ if (result != COMPLETE)
+ result = command(pasvcmd = "PASV");
+ break;
+#ifdef INET6
+ case AF_INET6:
+ result = command(pasvcmd = "EPSV");
+ if (code / 10 == 22 && code != 229) {
+ puts("wrong server: return code must be 229");
+ result = COMPLETE + 1;
+ }
+ if (result != COMPLETE)
+ result = command(pasvcmd = "LPSV");
+ break;
+#endif
+ default:
+ result = COMPLETE + 1;
+ }
+ if (result != COMPLETE) {
puts("Passive mode refused.");
goto bad;
}
+#define pack2(var, offset) \
+ (((var[(offset) + 0] & 0xff) << 8) | ((var[(offset) + 1] & 0xff) << 0))
+#define pack4(var, offset) \
+ (((var[(offset) + 0] & 0xff) << 24) | ((var[(offset) + 1] & 0xff) << 16) \
+ | ((var[(offset) + 2] & 0xff) << 8) | ((var[(offset) + 3] & 0xff) << 0))
/*
* What we've got at this point is a string of comma
* separated one-byte unsigned integer values.
+ * In PASV case,
* The first four are the an IP address. The fifth is
* the MSB of the port number, the sixth is the LSB.
* From that we'll prepare a sockaddr_in.
+ * In other case, the format is more complicated.
*/
+ if (strcmp(pasvcmd, "PASV") == 0) {
+ if (code / 10 == 22 && code != 227) {
+ puts("wrong server: return code must be 227");
+ error = 1;
+ goto bad;
+ }
+ error = sscanf(pasv, "%d,%d,%d,%d,%d,%d",
+ &h[0], &h[1], &h[2], &h[3],
+ &prt[0], &prt[1]);
+ if (error == 6) {
+ error = 0;
+ data_addr.su_sin.sin_addr.s_addr =
+ htonl(pack4(h, 0));
+ } else
+ error = 1;
+ } else if (strcmp(pasvcmd, "LPSV") == 0) {
+ if (code / 10 == 22 && code != 228) {
+ puts("wrong server: return code must be 228");
+ error = 1;
+ goto bad;
+ }
+ switch (data_addr.su_family) {
+ case AF_INET:
+ error = sscanf(pasv,
+"%d,%d,%d,%d,%d,%d,%d,%d,%d",
+ &af, &hal,
+ &h[0], &h[1], &h[2], &h[3],
+ &pal, &prt[0], &prt[1]);
+ if (error == 9 && af == 4 && hal == 4 && pal == 2) {
+ error = 0;
+ data_addr.su_sin.sin_addr.s_addr =
+ htonl(pack4(h, 0));
+ } else
+ error = 1;
+ break;
+#ifdef INET6
+ case AF_INET6:
+ error = sscanf(pasv,
+"%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
+ &af, &hal,
+ &h[0], &h[1], &h[2], &h[3],
+ &h[4], &h[5], &h[6], &h[7],
+ &h[8], &h[9], &h[10], &h[11],
+ &h[12], &h[13], &h[14], &h[15],
+ &pal, &prt[0], &prt[1]);
+ if (error != 21 || af != 6 || hal != 16 || pal != 2) {
+ error = 1;
+ break;
+ }
- if (sscanf(pasv, "%d,%d,%d,%d,%d,%d",
- &a0, &a1, &a2, &a3, &p0, &p1) != 6) {
+ error = 0;
+ {
+ u_int32_t *p32;
+ p32 = (u_int32_t *)&data_addr.su_sin6.sin6_addr;
+ p32[0] = htonl(pack4(h, 0));
+ p32[1] = htonl(pack4(h, 4));
+ p32[2] = htonl(pack4(h, 8));
+ p32[3] = htonl(pack4(h, 12));
+ }
+ break;
+#endif
+ default:
+ error = 1;
+ }
+ } else if (strcmp(pasvcmd, "EPSV") == 0) {
+ char delim[4];
+ char *tcpport;
+
+ prt[0] = 0;
+ if (code / 10 == 22 && code != 229) {
+ puts("wrong server: return code must be 229");
+ error = 1;
+ goto bad;
+ }
+ error = sscanf(pasv, "%c%c%c%d%c",
+ &delim[0], &delim[1], &delim[2],
+ &prt[1], &delim[3]);
+ if (error != 5) {
+ error = 1;
+ goto epsv_done;
+ }
+ if (delim[0] != delim[1] || delim[0] != delim[2]
+ || delim[0] != delim[3]) {
+ error = 1;
+ goto epsv_done;
+ }
+
+ data_addr = hisctladdr;
+ /* quickhack */
+ prt[0] = (prt[1] & 0xff00) >> 8;
+ prt[1] &= 0xff;
+ error = 0;
+epsv_done:
+ } else
+ error = 1;
+
+ if (error) {
puts(
"Passive mode address scan failure. Shouldn't happen!");
goto bad;
- }
+ };
- memset(&data_addr, 0, sizeof(data_addr));
- data_addr.sin_family = AF_INET;
- a = (char *)&data_addr.sin_addr.s_addr;
- a[0] = a0 & 0xff;
- a[1] = a1 & 0xff;
- a[2] = a2 & 0xff;
- a[3] = a3 & 0xff;
- p = (char *)&data_addr.sin_port;
- p[0] = p0 & 0xff;
- p[1] = p1 & 0xff;
+ data_addr.su_port = htons(pack2(prt, 0));
if (connect(data, (struct sockaddr *)&data_addr,
- sizeof(data_addr)) < 0) {
+ data_addr.su_len) < 0) {
warn("connect");
goto bad;
}
#ifdef IP_TOS
+ if (data_addr.su_family == AF_INET)
+ {
on = IPTOS_THROUGHPUT;
if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on,
sizeof(int)) < 0)
warn("setsockopt TOS (ignored)");
+ }
#endif
return (0);
}
@@ -1146,10 +1325,10 @@ initconn()
noport:
data_addr = myctladdr;
if (sendport)
- data_addr.sin_port = 0; /* let system pick one */
+ data_addr.su_port = 0; /* let system pick one */
if (data != -1)
(void)close(data);
- data = socket(AF_INET, SOCK_STREAM, 0);
+ data = socket(data_addr.su_family, SOCK_STREAM, 0);
if (data < 0) {
warn("socket");
if (tmpno)
@@ -1163,12 +1342,27 @@ noport:
goto bad;
}
#ifdef IP_PORTRANGE
+ if (data_addr.su_family == AF_INET)
+ {
+
ports = restricted_data_ports ? IP_PORTRANGE_HIGH : IP_PORTRANGE_DEFAULT;
if (setsockopt(data, IPPROTO_IP, IP_PORTRANGE, (char *)&ports,
sizeof(ports)) < 0)
warn("setsockopt PORTRANGE (ignored)");
+ }
+#endif
+#ifdef INET6
+#ifdef IPV6_PORTRANGE
+ if (data_addr.su_family == AF_INET6) {
+ ports = restricted_data_ports ? IPV6_PORTRANGE_HIGH
+ : IPV6_PORTRANGE_DEFAULT;
+ if (setsockopt(data, IPPROTO_IPV6, IPV6_PORTRANGE,
+ (char *)&ports, sizeof(ports)) < 0)
+ warn("setsockopt PORTRANGE (ignored)");
+ }
+#endif
#endif
- if (bind(data, (struct sockaddr *)&data_addr, sizeof(data_addr)) < 0) {
+ if (bind(data, (struct sockaddr *)&data_addr, data_addr.su_len) < 0) {
warn("bind");
goto bad;
}
@@ -1184,13 +1378,79 @@ noport:
if (listen(data, 1) < 0)
warn("listen");
if (sendport) {
- a = (char *)&data_addr.sin_addr;
- p = (char *)&data_addr.sin_port;
+ char hname[INET6_ADDRSTRLEN];
+ int af;
+ struct sockaddr_in data_addr4;
+ union sockunion *daddr;
+
+#ifdef INET6
+ if (data_addr.su_family == AF_INET6 &&
+ IN6_IS_ADDR_V4MAPPED(&data_addr.su_sin6.sin6_addr)) {
+ memset(&data_addr4, 0, sizeof(data_addr4));
+ data_addr4.sin_len = sizeof(struct sockaddr_in);
+ data_addr4.sin_family = AF_INET;
+ data_addr4.sin_port = data_addr.su_port;
+ memcpy((caddr_t)&data_addr4.sin_addr,
+ (caddr_t)&data_addr.su_sin6.sin6_addr.s6_addr[12],
+ sizeof(struct in_addr));
+ daddr = (union sockunion *)&data_addr4;
+ } else
+#endif
+ daddr = &data_addr;
+
+
+
#define UC(b) (((int)b)&0xff)
- result =
- command("PORT %d,%d,%d,%d,%d,%d",
- UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
- UC(p[0]), UC(p[1]));
+
+ switch (daddr->su_family) {
+ case AF_INET:
+#ifdef INET6
+ case AF_INET6:
+#endif
+ af = (daddr->su_family == AF_INET) ? 1 : 2;
+ if (getnameinfo((struct sockaddr *)daddr,
+ daddr->su_len, hname,
+ sizeof(hname) - 1, NULL, 0,
+ NI_NUMERICHOST|NI_WITHSCOPEID)) {
+ result = ERROR;
+ } else {
+ result = command("EPRT |%d|%s|%d|",
+ af, hname, ntohs(daddr->su_port));
+ }
+ break;
+ default:
+ result = COMPLETE + 1;
+ break;
+ }
+ if (result == COMPLETE)
+ goto skip_port;
+
+ p = (char *)&daddr->su_port;
+ switch (daddr->su_family) {
+ case AF_INET:
+ a = (char *)&daddr->su_sin.sin_addr;
+ result = command("PORT %d,%d,%d,%d,%d,%d",
+ UC(a[0]),UC(a[1]),UC(a[2]),UC(a[3]),
+ UC(p[0]), UC(p[1]));
+ break;
+#ifdef INET6
+ case AF_INET6:
+ a = (char *)&daddr->su_sin6.sin6_addr;
+ result = command(
+"LPRT %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
+ 6, 16,
+ UC(a[0]),UC(a[1]),UC(a[2]),UC(a[3]),
+ UC(a[4]),UC(a[5]),UC(a[6]),UC(a[7]),
+ UC(a[8]),UC(a[9]),UC(a[10]),UC(a[11]),
+ UC(a[12]),UC(a[13]),UC(a[14]),UC(a[15]),
+ 2, UC(p[0]), UC(p[1]));
+ break;
+#endif
+ default:
+ result = COMPLETE + 1; /* xxx */
+ }
+ skip_port:
+
if (result == ERROR && sendport == -1) {
sendport = 0;
tmpno = 1;
@@ -1201,9 +1461,12 @@ noport:
if (tmpno)
sendport = 1;
#ifdef IP_TOS
+ if (data_addr.su_family == AF_INET)
+ {
on = IPTOS_THROUGHPUT;
if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0)
warn("setsockopt TOS (ignored)");
+ }
#endif
return (0);
bad:
@@ -1217,10 +1480,10 @@ FILE *
dataconn(lmode)
const char *lmode;
{
- struct sockaddr_in from;
+ union sockunion from;
int s, fromlen, tos;
- fromlen = sizeof(from);
+ fromlen = myctladdr.su_len;
if (passivemode)
return (fdopen(data, lmode));
@@ -1234,9 +1497,12 @@ dataconn(lmode)
(void)close(data);
data = s;
#ifdef IP_TOS
+ if (data_addr.su_family == AF_INET)
+ {
tos = IPTOS_THROUGHPUT;
if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0)
warn("setsockopt TOS (ignored)");
+ }
#endif
return (fdopen(data, lmode));
}
@@ -1267,8 +1533,8 @@ pswitch(flag)
static struct comvars {
int connect;
char name[MAXHOSTNAMELEN];
- struct sockaddr_in mctl;
- struct sockaddr_in hctl;
+ union sockunion mctl;
+ union sockunion hctl;
FILE *in;
FILE *out;
int tpe;
diff --git a/usr.bin/ftp/ftp_var.h b/usr.bin/ftp/ftp_var.h
index d26d22d..cd9b0bd 100644
--- a/usr.bin/ftp/ftp_var.h
+++ b/usr.bin/ftp/ftp_var.h
@@ -41,6 +41,7 @@
*/
#include <sys/param.h>
+#include <sys/socket.h>
#include <setjmp.h>
#include <stringlist.h>
#include <netinet/in.h>
@@ -96,7 +97,7 @@ int preserve; /* preserve modification time on files */
int progress; /* display transfer progress bar */
int code; /* return/reply code for ftp command */
int crflag; /* if 1, strip car. rets. on ascii gets */
-char pasv[64]; /* passive port for proxy data connection */
+char pasv[BUFSIZ]; /* passive port for proxy data connection */
int passivemode; /* passive mode enabled */
int restricted_data_ports; /* enable quarantine FTP area */
char *altarg; /* argv[1] with no shell-like preprocessing */
@@ -138,12 +139,12 @@ char *hostname; /* name of host connected to */
int unix_server; /* server is unix, can use binary for ascii */
int unix_proxy; /* proxy is unix, can use binary for ascii */
-u_int16_t ftpport; /* port number to use for ftp connections */
-u_int16_t httpport; /* port number to use for http connections */
-u_int16_t gateport; /* port number to use for gateftp connections */
+char *ftpport; /* port number to use for ftp connections */
+char *httpport; /* port number to use for http connections */
+char *gateport; /* port number to use for gateftp connections */
int dobind; /* bind to specific address */
-struct sockaddr_in bindto; /* address to bind to */
+struct sockaddr_storage bindto; /* address to bind to */
jmp_buf toplevel; /* non-local goto stuff for cmd scanner */
diff --git a/usr.bin/ftp/main.c b/usr.bin/ftp/main.c
index 3717308..aeb7487 100644
--- a/usr.bin/ftp/main.c
+++ b/usr.bin/ftp/main.c
@@ -58,6 +58,7 @@ __RCSID_SOURCE("$NetBSD: main.c,v 1.26 1997/10/14 16:31:22 christos Exp $");
#include <arpa/inet.h>
#include <err.h>
+#include <errno.h>
#include <locale.h>
#include <netdb.h>
#include <pwd.h>
@@ -86,33 +87,14 @@ main(argc, argv)
(void) setlocale(LC_ALL, "");
- sp = getservbyname("ftp", "tcp");
- if (sp == 0)
- ftpport = htons(FTP_PORT); /* good fallback */
- else
- ftpport = sp->s_port;
- sp = getservbyname("http", "tcp");
- if (sp == 0)
- httpport = htons(HTTP_PORT); /* good fallback */
- else
- httpport = sp->s_port;
- gateport = 0;
+ ftpport = "ftp";
+ httpport = "http";
+ gateport = NULL;
cp = getenv("FTPSERVERPORT");
- if (cp != NULL) {
- port = strtol(cp, &ep, 10);
- if (port < 1 || port > 0xffff || *ep != '\0')
- warnx("bad FTPSERVERPORT port number: %s (ignored)",
- cp);
- else
- gateport = htons(port);
- }
- if (gateport == 0) {
- sp = getservbyname("ftpgate", "tcp");
- if (sp == 0)
- gateport = htons(GATE_PORT);
- else
- gateport = sp->s_port;
- }
+ if (cp != NULL)
+ gateport = cp;
+ if (!gateport)
+ gateport = "ftpgate";
doglob = 1;
interactive = 1;
autologin = 1;
@@ -203,11 +185,7 @@ main(argc, argv)
break;
case 'P':
- port = strtol(optarg, &ep, 10);
- if (port < 1 || port > 0xffff || *ep != '\0')
- warnx("bad port number: %s (ignored)", optarg);
- else
- ftpport = htons(port);
+ ftpport = optarg;
break;
case 's':
@@ -244,17 +222,24 @@ main(argc, argv)
sendport = -1; /* not using ports */
if (dobind) {
- memset((void *)&bindto, 0, sizeof(bindto));
- if (inet_aton(src_addr, &bindto.sin_addr) == 1)
- bindto.sin_family = AF_INET;
- else {
- struct hostent *hp = gethostbyname(src_addr);
- if (hp == NULL)
- errx(1, "%s: %s", src_addr, hstrerror(h_errno));
- bindto.sin_family = hp->h_addrtype;
- memcpy(&bindto.sin_addr, hp->h_addr_list[0],
- MIN(hp->h_length,sizeof(bindto.sin_addr)));
+ struct addrinfo hints;
+ struct addrinfo *res;
+ char *ftpdataport = "ftp-data";
+ int error;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ error = getaddrinfo(src_addr, NULL, &hints, &res);
+ if (error) {
+ fprintf(stderr, "%s: %s", src_addr,
+ gai_strerror(error));
+ if (error == EAI_SYSTEM)
+ errx(1, "%s", strerror(errno));
+ exit(1);
}
+ memcpy(&bindto, res->ai_addr, res->ai_addrlen);
+ freeaddrinfo(res);
}
/*
@@ -280,7 +265,7 @@ main(argc, argv)
#endif
if (argc > 0) {
- if (strchr(argv[0], ':') != NULL) {
+ if (isurl(argv[0])) {
anonftp = 1; /* Handle "automatic" transfers. */
rval = auto_fetch(argc, argv);
if (rval >= 0) /* -1 == connected and cd-ed */
diff --git a/usr.bin/ftp/util.c b/usr.bin/ftp/util.c
index a34ca34..a62565c 100644
--- a/usr.bin/ftp/util.c
+++ b/usr.bin/ftp/util.c
@@ -76,7 +76,7 @@ setpeer(argc, argv)
char *argv[];
{
char *host;
- u_int16_t port;
+ char *port;
if (connected) {
printf("Already connected to %s, use close first.\n",
@@ -95,19 +95,8 @@ setpeer(argc, argv)
port = gateport;
else
port = ftpport;
- if (argc > 2) {
- char *ep;
- long nport;
-
- nport = strtol(argv[2], &ep, 10);
- if (nport < 1 || nport > 0xffff || *ep != '\0') {
- printf("%s: bad port number '%s'.\n", argv[0], argv[2]);
- printf("usage: %s host-name [port]\n", argv[0]);
- code = -1;
- return;
- }
- port = htons(nport);
- }
+ if (argc > 2)
+ port = strdup(argv[2]);
if (gatemode) {
if (gateserver == NULL || *gateserver == '\0')
diff --git a/usr.bin/telnet/Makefile b/usr.bin/telnet/Makefile
index 658a2b7..b4faf30 100644
--- a/usr.bin/telnet/Makefile
+++ b/usr.bin/telnet/Makefile
@@ -31,6 +31,7 @@
# SUCH DAMAGE.
#
# @(#)Makefile 8.1 (Berkeley) 6/6/93
+# $FreeBSD$
#
PROG= telnet
@@ -39,11 +40,12 @@ CFLAGS+=-DKLUDGELINEMODE -DUSE_TERMIO #-DAUTHENTICATION -DENCRYPTION
CFLAGS+=-DENV_HACK
CFLAGS+=-DSKEY
CFLAGS+=-I${.CURDIR}/../../lib
+CFLAGS+=-DIPSEC -DINET6
#CFLAGS+= -DKRB4
-DPADD= ${LIBTERMCAP} ${LIBTELNET}
-LDADD= -ltermcap -ltelnet
+DPADD= ${LIBTERMCAP} ${LIBTELNET} ${LIBIPSEC}
+LDADD= -ltermcap -ltelnet -lipsec
#DPADD+= ${LIBKRB} ${LIBDES}
#LDADD+= -lkrb -ldes
diff --git a/usr.bin/telnet/commands.c b/usr.bin/telnet/commands.c
index a4677e0..a640bec 100644
--- a/usr.bin/telnet/commands.c
+++ b/usr.bin/telnet/commands.c
@@ -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$
*/
#ifndef lint
@@ -76,7 +78,7 @@ static char sccsid[] = "@(#)commands.c 8.2 (Berkeley) 12/15/93";
# endif /* vax */
#endif /* !defined(CRAY) && !defined(sysV88) */
#include <netinet/ip.h>
-
+#include <netinet/ip6.h>
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 64
@@ -2094,24 +2096,76 @@ ayt_status()
}
#endif
+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
+
int
tn(argc, argv)
int argc;
char *argv[];
{
- register struct hostent *host = 0;
- struct sockaddr_in sin, src_sin;
- struct servent *sp = 0;
- unsigned long temp;
-#if defined(IP_OPTIONS) && defined(IPPROTO_IP)
+ struct sockaddr_storage ss, src_ss;
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;
char *src_addr = NULL;
+ struct addrinfo hints, *res;
+ int error = 0;
/* clear the socket address prior to use */
- bzero((char *)&sin, sizeof(sin));
+ memset((char *)&ss, 0, sizeof(ss));
if (connected) {
printf("?Already connected to %s\n", hostname);
@@ -2171,128 +2225,106 @@ tn(argc, argv)
goto usage;
if (src_addr != NULL) {
- bzero((char *)&src_sin, sizeof(src_sin));
- src_sin.sin_family = AF_INET;
- if (!inet_aton(src_addr, &src_sin.sin_addr)) {
- host = gethostbyname2(src_addr, AF_INET);
- if (host == NULL) {
- herror(src_addr);
+ 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, &res);
+ if (error == EAI_NONAME) {
+ hints.ai_flags = 0;
+ error = getaddrinfo(src_addr, 0, &hints, &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));
return 0;
- }
- if (host->h_length != sizeof(src_sin.sin_addr)) {
- fprintf(stderr, "telnet: gethostbyname2: invalid address\n");
- return 0;
- }
- memcpy((void *)&src_sin.sin_addr, (void *)host->h_addr_list[0],
- sizeof(src_sin.sin_addr));
}
+ memcpy((void *)&src_ss, (void *)res->ai_addr, res->ai_addrlen);
+ freeaddrinfo(res);
}
-
-#if defined(IP_OPTIONS) && defined(IPPROTO_IP)
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 == 0) {
+ int gni_err = 1;
+
+ if (doaddrlookup)
+ gni_err = getnameinfo(res->ai_addr, res->ai_addr->sa_len,
+ _hostname, sizeof(_hostname) - 1, NULL, 0,
+ 0);
+ if (gni_err != 0)
+ (void) strncpy(_hostname, hostp, sizeof(_hostname) - 1);
+ _hostname[sizeof(_hostname)-1] = '\0';
+ hostname = _hostname;
+ } else if (error == EAI_NONAME) {
+ 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());
+ return 0;
+ }
+ memcpy((void *)&ss, (void *)res->ai_addr, res->ai_addrlen);
+ 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;
+ }
+ if (srcroute != 0) {
srp = 0;
- temp = sourceroute(hostp, &srp, &srlen);
- if (temp == 0) {
- herror(srp);
+ result = sourceroute(res, hostp, &srp, &srlen, &proto, &opt);
+ if (result == 0) {
setuid(getuid());
+ freeaddrinfo(res);
return 0;
- } else if (temp == -1) {
+ } else if (result == -1) {
printf("Bad source route option: %s\n", hostp);
setuid(getuid());
+ freeaddrinfo(res);
return 0;
- } else {
- sin.sin_addr.s_addr = temp;
- sin.sin_family = AF_INET;
}
- } 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],
- MIN(host->h_length, sizeof(sin.sin_addr)));
-#else /* defined(h_addr) */
- memmove((caddr_t)&sin.sin_addr, host->h_addr,
- MIN(host->h_length, sizeof(sin.sin_addr)));
-#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));
+ printf("Trying %s...\n", sockaddr_ntop(res->ai_addr));
do {
- net = socket(AF_INET, SOCK_STREAM, 0);
+ net = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
setuid(getuid());
if (net < 0) {
perror("telnet: socket");
return 0;
}
-#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")))
@@ -2313,28 +2345,31 @@ tn(argc, argv)
}
if (src_addr != NULL) {
- if (bind(net, (struct sockaddr *)&src_sin, sizeof(src_sin)) == -1) {
+ if (bind(net, (struct sockaddr *)&src_ss,
+ ((struct sockaddr *)&src_ss)->sa_len) == -1) {
perror("bind");
return 0;
}
}
+#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
+ if (setpolicy(net, res, ipsec_policy_in) < 0)
+ return 0;
+ if (setpolicy(net, res, ipsec_policy_out) < 0)
+ return 0;
+#endif
- 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]) {
+ if (connect(net, res->ai_addr, res->ai_addrlen) < 0) {
+ if (res->ai_next) {
int oerrno = errno;
fprintf(stderr, "telnet: connect to address %s: ",
- inet_ntoa(sin.sin_addr));
+ sockaddr_ntop(res->ai_addr));
errno = oerrno;
perror((char *)0);
- host->h_addr_list++;
- memcpy((caddr_t)&sin.sin_addr, host->h_addr_list[0],
- MIN(host->h_length, sizeof(sin.sin_addr)));
+ res = res->ai_next;
(void) NetClose(net);
continue;
}
-#endif /* defined(h_addr) */
perror("telnet: Unable to connect to remote host");
return 0;
}
@@ -2343,6 +2378,7 @@ tn(argc, argv)
auth_encrypt_connect(connected);
#endif /* defined(AUTHENTICATION) */
} while (connected == 0);
+ freeaddrinfo(res);
cmdrc(hostp, hostname);
if (autologin && user == NULL) {
struct passwd *pw;
@@ -2681,8 +2717,6 @@ cmdrc(m1, m2)
fclose(rcfile);
}
-#if defined(IP_OPTIONS) && defined(IPPROTO_IP)
-
/*
* Source route is handed in as
* [!]@hop1@hop2...[@|:]dst
@@ -2696,6 +2730,10 @@ cmdrc(m1, m2)
* 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
@@ -2705,9 +2743,18 @@ cmdrc(m1, m2)
* 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
@@ -2721,21 +2768,32 @@ cmdrc(m1, m2)
* *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]; /*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;
/*
@@ -2744,22 +2802,46 @@ sourceroute(arg, cpp, lenp)
*/
if (cpp == NULL || lenp == NULL)
return((unsigned long)-1);
- if (*cpp != NULL && *lenp < 7)
- return((unsigned long)-1);
+ if (*cpp != NULL) {
+ switch (res->ai_family) {
+ case AF_INET:
+ if (*lenp < 7)
+ return((unsigned long)-1);
+ break;
+#ifdef INET6
+ case AF_INET6:
+ if (*lenp < (sizeof(struct cmsghdr) +
+ sizeof(struct ip6_rthdr) +
+ sizeof(struct in6_addr)))
+ return((unsigned long)-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 = 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
@@ -2786,13 +2868,20 @@ sourceroute(arg, cpp, lenp)
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 == ',') {
@@ -2801,7 +2890,11 @@ sourceroute(arg, cpp, lenp)
cp2++;
} else if (c == '@') {
*cp2++ = '\0';
- } else if (c == ':') {
+ } else if (
+#ifdef INET6
+ ai->ai_family != AF_INET6 &&
+#endif
+ c == ':') {
*cp2++ = '\0';
} else
continue;
@@ -2810,22 +2903,32 @@ sourceroute(arg, cpp, lenp)
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],
- MIN(host->h_length,sizeof(sin_addr)));
-#else
- memcpy((caddr_t)&sin_addr, host->h_addr,
- MIN(host->h_length,sizeof(sin_addr)));
-#endif
- } else {
+ hints.ai_flags = AI_NUMERICHOST;
+ error = getaddrinfo(cp, NULL, &hints, &res);
+ if (error == EAI_NONAME) {
+ 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
@@ -2833,9 +2936,27 @@ sourceroute(arg, cpp, lenp)
/*
* Check to make sure there is space for next address
*/
- if (lsrp + 4 > lsrep)
+#ifdef INET6
+ if (res->ai_family == AF_INET6) {
+ if (((char *)cmsg +
+ sizeof(struct cmsghdr) +
+ sizeof(struct ip6_rthdr) +
+ ((inet6_rthdr_segments(cmsg) + 1) *
+ sizeof(struct in6_addr))) > ep)
return((unsigned long)-1);
+ } else
+#endif
+ if (lsrp + 4 > ep)
+ return((unsigned long)-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;
@@ -2854,6 +2975,7 @@ sourceroute(arg, cpp, lenp)
*lenp = sizeof(ipopt);
*cpp = (char *) &ipopt;
#endif
- return(sin_addr.s_addr);
+ }
+ freeaddrinfo(res);
+ return 1;
}
-#endif
diff --git a/usr.bin/telnet/externs.h b/usr.bin/telnet/externs.h
index a8c3f24..10e89ac 100644
--- a/usr.bin/telnet/externs.h
+++ b/usr.bin/telnet/externs.h
@@ -31,6 +31,7 @@
* SUCH DAMAGE.
*
* @(#)externs.h 8.2 (Berkeley) 12/15/93
+ * $FreeBSD$
*/
#ifndef BSD
@@ -86,6 +87,14 @@ typedef unsigned char cc_t;
#endif
#include <strings.h>
+#if defined(IPSEC)
+#include <netinet6/ipsec.h>
+#if defined(IPSEC_POLICY_IPSEC)
+extern char *ipsec_policy_in;
+extern char *ipsec_policy_out;
+#endif
+#endif
+
#ifndef _POSIX_VDISABLE
# ifdef sun
# include <sys/param.h> /* pick up VDISABLE definition, mayby */
@@ -115,6 +124,7 @@ extern int
autologin, /* Autologin enabled */
skiprc, /* Don't process the ~/.telnetrc file */
eight, /* use eight bit mode (binary in and/or out */
+ family, /* address family of peer */
flushout, /* flush output */
connected, /* Are we connected to the other side? */
globalmode, /* Mode tty should be in */
diff --git a/usr.bin/telnet/main.c b/usr.bin/telnet/main.c
index 298389c..9126738 100644
--- a/usr.bin/telnet/main.c
+++ b/usr.bin/telnet/main.c
@@ -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$
*/
#ifndef lint
@@ -42,6 +44,7 @@ static char sccsid[] = "@(#)main.c 8.2 (Berkeley) 12/15/93";
#endif /* not lint */
#include <sys/types.h>
+#include <sys/socket.h>
#include "ring.h"
#include "externs.h"
@@ -56,6 +59,13 @@ static char sccsid[] = "@(#)main.c 8.2 (Berkeley) 12/15/93";
#define FORWARD
#endif
+#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
+char *ipsec_policy_in = NULL;
+char *ipsec_policy_out = NULL;
+#endif
+
+int family = AF_UNSPEC;
+
/*
* Initialize variables.
*/
@@ -81,10 +91,10 @@ usage()
fprintf(stderr, "Usage: %s %s%s%s%s\n",
prompt,
#ifdef AUTHENTICATION
- "[-8] [-E] [-K] [-L] [-N] [-S tos] [-X atype] [-a] [-c] [-d]",
+ "[-4] [-6] [-8] [-E] [-K] [-L] [-N] [-S tos] [-X atype] [-a] [-c] [-d]",
"\n\t[-e char] [-k realm] [-l user] [-f/-F] [-n tracefile] ",
#else
- "[-8] [-E] [-L] [-N] [-S tos] [-a] [-c] [-d] [-e char] [-l user]",
+ "[-4] [-6] [-8] [-E] [-L] [-N] [-S tos] [-a] [-c] [-d] [-e char] [-l user]",
"\n\t[-n tracefile] ",
#endif
#if defined(TN3270) && defined(unix)
@@ -98,6 +108,9 @@ usage()
#else
"[-r] [-s src_addr] ",
#endif
+#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
+ "[-P policy]"
+#endif
"[host-name [port]]"
);
exit(1);
@@ -138,8 +151,25 @@ main(argc, argv)
rlogin = (strncmp(prompt, "rlog", 4) == 0) ? '~' : _POSIX_VDISABLE;
autologin = -1;
- while ((ch = getopt(argc, argv, "8EKLNS:X:acde:fFk:l:n:rs:t:x")) != -1) {
+#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
+#define IPSECOPT "P:"
+#else
+#define IPSECOPT
+#endif
+ while ((ch = getopt(argc, argv,
+ "468EKLNS:X:acde:fFk:l:n:rs:t:x" IPSECOPT)) != -1)
+#undef IPSECOPT
+ {
+
switch(ch) {
+ case '4':
+ family = AF_INET;
+ break;
+#ifdef INET6
+ case '6':
+ family = AF_INET6;
+ break;
+#endif
case '8':
eight = 3; /* binary output and input */
break;
@@ -276,6 +306,16 @@ main(argc, argv)
"%s: Warning: -x ignored, no ENCRYPT support.\n",
prompt);
break;
+#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
+ case 'P':
+ if (!strncmp("in", optarg, 2))
+ ipsec_policy_in = strdup(optarg);
+ else if (!strncmp("out", optarg, 3))
+ ipsec_policy_out = strdup(optarg);
+ else
+ usage();
+ break;
+#endif
case '?':
default:
usage();
diff --git a/usr.bin/telnet/telnet.1 b/usr.bin/telnet/telnet.1
index ca2e968..dfa4fcf 100644
--- a/usr.bin/telnet/telnet.1
+++ b/usr.bin/telnet/telnet.1
@@ -32,7 +32,7 @@
.\" @(#)telnet.1 8.5 (Berkeley) 3/1/94
.\" $FreeBSD$
.\"
-.Dd March 1, 1994
+.Dd January 27, 2000
.Dt TELNET 1
.Os BSD 4.2
.Sh NAME
@@ -564,9 +564,10 @@ will attempt to contact a
.Tn TELNET
server at the default port.
The host specification may be either a host name (see
-.Xr hosts 5 )
-or an Internet address specified in the \*(Lqdot notation\*(Rq (see
-.Xr inet 3 ) .
+.Xr hosts 5 ) ,
+an Internet address specified in the \*(Lqdot notation\*(Rq (see
+.Xr inet 3 ) ,
+or IPv6 host name or IPv6 coloned-hexadecimal addreess.
The
.Fl l
option may be used to specify the user name
@@ -1390,6 +1391,8 @@ The
.Nm
command appeared in
.Bx 4.2 .
+.Pp
+IPv6 support was added by WIDE/KAME project.
.Sh NOTES
.Pp
On some remote systems, echo has to be turned off manually when in
OpenPOWER on IntegriCloud