[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [bug-inetutils] IPv6 support for inetd, telnet and telnetd
From: |
Jeroen Dekkers |
Subject: |
Re: [bug-inetutils] IPv6 support for inetd, telnet and telnetd |
Date: |
Wed, 19 May 2004 21:19:00 +0200 |
User-agent: |
Wanderlust/2.10.1 (Watching The Wheels) SEMI/1.14.6 (Maruoka) FLIM/1.14.6 (Marutamachi) APEL/10.6 Emacs/21.3.50 (i686-pc-linux-gnu) MULE/5.0 (SAKAKI) |
At Wed, 19 May 2004 19:59:16 +0200,
Göran Weinholt wrote:
>
> On Mon, Apr 19, 2004 at 04:36:31PM +0200, Jeroen Dekkers wrote:
> > Hi,
> >
> > the patch below implements IPv6 support for inetd, telnet and
> > telnetd. I also cleaned up telnet some bit, removing source routing
> > (I don't think anyone allows you to do that nowadays) and code for
> > some obsolete TOS interface. If you've any questions about the
> > patch, just ask. :)
>
> I had a small problem with the patch against telnet (I haven't tested
> the rest.) It always connects to port 23, no matter what port you give
> it.
>
> > + telnetport = 0;
> > + if (portp && *portp == '-')
> > + {
> > + portp++;
> > + telnetport = 1;
> > + }
> > + else
> > + {
> > + telnetport = 1;
> > + portp = "telnet";
> > + }
>
> The problem would appear to be here. Changing the else to "else if
> (!portp)" seems to fix it.
You're right, I've recoded the logic which should fix it. Here is a
new version of the patch:
2004-04-19 Jeroen Dekkers <address@hidden>
* configure.ac: Add checks for IPv6.
doc/
2004-04-19 Jeroen Dekkers <address@hidden>
* inetd.texi (inetd): Document IPv6 configuration options.
inetd/
2004-04-19 Jeroen Dekkers <address@hidden>
* inetd.c: Move global variable sp to...
(nextconfig): Here. Only use the getservbyname code when
[!IPV6]. Remove unused variable i.
(struct servtab): Change type of to pid_t. Add se_family.
[IPV6] Add se_v4mapped. Change se_ctrladdr to struct
sockaddr_storage.
(setup): Add support for IPv6.
(INETD_FIELDS_MIN): Define to 6.
(getconfigent): Add support for IPv6. Remove unused variable arg.
(set_proc_title): Add support for IPv6.
(echo_dg): Likewise.
(chargen_dg): Likewise.
(machtime_dg): Likewise.
(daytime_dg): Likewise.
telnet/
2004-04-19 Jeroen Dekkers <address@hidden>
* commands.c: Include <arpa/telnet.h>. Remove variable tos and
_hostname.
(tn): Rewritten. Removed support for source routing and added
support for IPv6.
(sourceroute): Function removed.
* main.c (help): Add "-4" and "-6", remove "-S".
(long_options): Add "ipv4" and "ipv6", remove "tos".
(main): New variable family. Implement "-4" and "-6" options and
remove "-S" option.
telnetd/
2004-04-19 Jeroen Dekkers <address@hidden>
* telnetd.c (telnetd_setup): Add support for IPv6.
Index: configure.ac
===================================================================
RCS file: /cvsroot/inetutils/inetutils/configure.ac,v
retrieving revision 1.19
diff -u -p -r1.19 configure.ac
--- configure.ac 30 Jan 2004 13:15:24 -0000 1.19
+++ configure.ac 19 May 2004 18:58:04 -0000
@@ -1,6 +1,6 @@
# Configuration for inetutils
#
-# Copyright (C) 1995, 1996, 1997, 1998, 2000, 2001, 2002 Free Software
Foundation, Inc.
+# Copyright (C) 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2004 Free Software
Foundation, Inc.
#
# Written by Miles Bader <address@hidden>
#
@@ -280,6 +280,65 @@ if test ".$LIBAUTH" != .; then
[Define to one if you want authentication.])
test "$enable_encryption" = yes && AC_DEFINE(ENCRYPTION, 1,
[Define to one if you want encryption.])
+fi
+
+dnl Checks for IPv6
+
+AC_ARG_ENABLE(ipv6,
+ AS_HELP_STRING([--disable-ipv6], [disable IPv6 support]),
+ [case "${enable_ipv6}" in
+ no)
+ AC_MSG_NOTICE([Disabling IPv6 at user request])
+ ipv6=no
+ ;;
+ *)
+ ipv6=yes
+ ;;
+ esac],
+ [ipv6=auto]
+)
+
+if test ! "X$ipv6" = "Xno"; then
+ working_ipv6=yes
+
+ AC_MSG_CHECKING([for AF_INET6])
+ AC_COMPILE_IFELSE([AC_INCLUDES_DEFAULT
+#include <sys/socket.h>
+
+#ifndef AF_INET6
+#error Missing AF_INET6
+#endif
+ ], [AC_MSG_RESULT(yes)], [
+ AC_MSG_RESULT(no)
+ working_ipv6=no])
+
+ AC_MSG_CHECKING([for IPV6_V6ONLY])
+ AC_COMPILE_IFELSE([AC_INCLUDES_DEFAULT
+#include <netinet/in.h>
+
+#ifndef IPV6_V6ONLY
+#error Missing IPV6_V6ONLY
+#endif
+ ], [AC_MSG_RESULT(yes)], [
+ AC_MSG_RESULT(no)
+ working_ipv6=no])
+
+ AC_CHECK_TYPE(struct sockaddr_storage, , working_ipv6=no, [#include
<sys/socket.h>])
+ AC_CHECK_TYPE(struct addrinfo, , working_ipv6=no, [#include <netdb.h>])
+
+ AC_CHECK_FUNC(getaddrinfo, ,working_ipv6=no, [#include <netdb.h>])
+ AC_CHECK_FUNC(getnameinfo, ,working_ipv6=no, [#include <netdb.h>])
+
+ if test "X$working_ipv6" = "Xyes"; then
+ AC_MSG_NOTICE([Enabling IPv6])
+ AC_DEFINE(IPV6, 1, [Define to one if you want IPv6.])
+ else
+ if test "X$ipv6" = "Xyes"; then
+ AC_MSG_FAILURE([IPv6 support not available])
+ else
+ AC_MSG_WARN([Disabling IPv6 support])
+ fi
+ fi
fi
dnl Check if they want support for Wrap. Certain daemons like
Index: doc/inetd.texi
===================================================================
RCS file: /cvsroot/inetutils/inetutils/doc/inetd.texi,v
retrieving revision 1.1
diff -u -p -r1.1 inetd.texi
--- doc/inetd.texi 11 Nov 2001 03:07:23 -0000 1.1
+++ doc/inetd.texi 19 May 2004 18:58:04 -0000
@@ -78,8 +78,13 @@ or ``seqpacket'', depending on whether t
raw, reliably delivered message, or sequenced packet socket. TCPMUX services
must use ``stream''.
-The protocol must be a valid protocol as given in /etc/protocols. Examples
-might be ``tcp'' or ``udp''. TCPMUX services must use ``tcp''.
+The protocol must be a valid protocol as given in /etc/protocols.
+Examples might be ``tcp'' or ``udp''. TCPMUX services must use
+``tcp''. If IPv6 support is enabled the sockets will accept both IPv4
+and IPv6 connections if that is supported by the OS. If inetd should only
+accept IPv4 or IPv6 connections, add ``4'' or ``6'' to the protocol.
+For example ``tcp4'' will only accept IPv4 tcp connections and
+``udp6'' will only accept IPv6 udp connections.
The wait/nowait entry specifies whether the server that is invoked by inetd
will take over the socket associated with the service access point,
Index: inetd/inetd.c
===================================================================
RCS file: /cvsroot/inetutils/inetutils/inetd/inetd.c,v
retrieving revision 1.27
diff -u -p -r1.27 inetd.c
--- inetd/inetd.c 11 Nov 2003 15:16:32 -0000 1.27
+++ inetd/inetd.c 19 May 2004 18:58:05 -0000
@@ -1,5 +1,24 @@
+/* Copyright (C) 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+
+ This file is part of GNU Inetutils.
+
+ GNU Inetutils is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU Inetutils is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Inetutils; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
/*
- * Copyright (c) 1983, 1991, 1993, 1994, 2002
+ * Copyright (c) 1983, 1991, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -144,13 +163,12 @@ fd_set allsock;
int options;
int timingout;
int toomany = TOOMANY;
-struct servent *sp;
struct servtab {
char *se_service; /* name of service */
int se_socktype; /* type of socket to use */
char *se_proto; /* protocol used */
- short se_wait; /* single threaded server */
+ pid_t se_wait; /* single threaded server */
short se_checked; /* looked at during merge */
char *se_user; /* user name to run as */
struct biltin *se_bi; /* if built-in, description */
@@ -159,7 +177,13 @@ struct servtab {
size_t se_argc; /* number of arguments */
int se_fd; /* open descriptor */
int se_type; /* type */
+ sa_family_t se_family; /* address family of the socket */
+ char se_v4mapped; /* 1 = accept v4mapped connection, 0 = don't */
+#ifdef IPV6
+ struct sockaddr_storage se_ctrladdr;/* bound address */
+#else
struct sockaddr_in se_ctrladdr;/* bound address */
+#endif
int se_count; /* number started since se_time */
struct timeval se_time; /* start of se_count */
struct servtab *se_next;
@@ -218,7 +242,7 @@ struct biltin {
{ "discard", SOCK_STREAM, 1, 0, discard_stream },
{ "discard", SOCK_DGRAM, 0, 0, discard_dg },
- /* Return 32 bit time since 1970 */
+ /* Return 32 bit time since 1900 */
{ "time", SOCK_STREAM, 0, 0, machtime_stream },
{ "time", SOCK_DGRAM, 0, 0, machtime_dg },
@@ -708,6 +732,9 @@ config (int signo)
void
nextconfig (const char *file)
{
+#ifndef IPV6
+ struct servent *sp;
+#endif
struct servtab *sep, *cp, **sepp;
struct passwd *pwd;
FILE * fconfig;
@@ -737,8 +764,6 @@ nextconfig (const char *file)
break;
if (sep != 0)
{
- int i;
-
signal_block (&sigstatus);
/*
* sep->se_wait may be holding the pid of a daemon
@@ -776,6 +801,7 @@ nextconfig (const char *file)
sep->se_fd = -1;
continue;
}
+#ifndef IPV6 /* This code is moved to setup() for IPV6. */
sp = getservbyname (sep->se_service, sep->se_proto);
if (sp == 0)
{
@@ -791,6 +817,7 @@ nextconfig (const char *file)
if (sep->se_fd >= 0)
close_sep (sep);
}
+#endif
if (sep->se_fd == -1)
setup (sep);
}
@@ -833,27 +860,132 @@ retry (int signo)
void
setup (struct servtab *sep)
{
- int on = 1;
+ int err;
+ const int on = 1;
+#ifdef IPV6
+ const int off = 0;
+ struct addrinfo *result, hints;
+ struct protoent *proto;
- if ((sep->se_fd = socket (AF_INET, sep->se_socktype, 0)) < 0)
+ tryagain:
+#endif
+ sep->se_fd = socket (sep->se_family, sep->se_socktype, 0);
+ if (sep->se_fd < 0)
{
+#ifdef IPV6
+ /* If we don't support creating AF_INET6 sockets, create AF_INET
+ sockets. */
+ if (errno == EAFNOSUPPORT && sep->se_family == AF_INET6 &&
sep->se_v4mapped)
+ {
+ /* Fall back to IPv6 silently. */
+ sep->se_family = AF_INET;
+ goto tryagain;
+ }
+#endif
+
if (debug)
fprintf (stderr, "socket failed on %s/%s: %s\n",
sep->se_service, sep->se_proto, strerror (errno));
syslog(LOG_ERR, "%s/%s: socket: %m", sep->se_service, sep->se_proto);
return;
}
-#define turnon(fd, opt) \
-setsockopt(fd, SOL_SOCKET, opt, (char *)&on, sizeof (on))
- if (strcmp (sep->se_proto, "tcp") == 0 && (options & SO_DEBUG)
- && turnon(sep->se_fd, SO_DEBUG) < 0)
- syslog (LOG_ERR, "setsockopt (SO_DEBUG): %m");
- if (turnon (sep->se_fd, SO_REUSEADDR) < 0)
- syslog (LOG_ERR, "setsockopt (SO_REUSEADDR): %m");
-#undef turnon
- if (bind (sep->se_fd, (struct sockaddr *)&sep->se_ctrladdr,
- sizeof (sep->se_ctrladdr)) < 0)
+
+#ifdef IPV6
+ /* Make sure that tcp6 etc also work. */
+ if (strncmp (sep->se_proto, "tcp", 3) == 0)
+ proto = getprotobyname ("tcp");
+ else if (strncmp (sep->se_proto, "udp", 3) == 0)
+ proto = getprotobyname ("udp");
+ else
+ proto = getprotobyname (sep->se_proto);
+
+ if (!proto)
+ {
+ syslog (LOG_ERR, "%s: Unknown protocol", sep->se_proto);
+ close (sep->se_fd);
+ sep->se_fd = -1;
+ return;
+ }
+
+ memset (&hints, 0, sizeof (hints));
+
+ hints.ai_flags = AI_PASSIVE;
+ hints.ai_family = sep->se_family;
+ hints.ai_socktype = sep->se_socktype;
+ hints.ai_protocol = proto->p_proto;
+
+ err = getaddrinfo (NULL, sep->se_service, &hints, &result);
+ if (err)
+ {
+ const char *errmsg;
+
+ if (err == EAI_FAMILY && sep->se_family == AF_INET6 && sep->se_v4mapped)
+ {
+ /* Fall back to IPv6 silently. */
+ sep->se_family = AF_INET;
+ close (sep->se_fd);
+ goto tryagain;
+ }
+
+ if (err == EAI_SYSTEM)
+ errmsg = strerror (errno);
+ else
+ errmsg = gai_strerror (err);
+
+ syslog (LOG_ERR, "%s/%s: getaddrinfo: %s",
+ sep->se_service, sep->se_proto, errmsg);
+
+ close (sep->se_fd);
+ sep->se_fd = -1;
+ return;
+ }
+
+ memcpy (&sep->se_ctrladdr, result->ai_addr, result->ai_addrlen);
+
+ freeaddrinfo (result);
+
+ if (sep->se_family == AF_INET6)
+ {
+ if (sep->se_v4mapped)
+ err = setsockopt (sep->se_fd, IPPROTO_IPV6, IPV6_V6ONLY,
+ (char *)&off, sizeof(off));
+ else
+ err = setsockopt (sep->se_fd, IPPROTO_IPV6, IPV6_V6ONLY,
+ (char *)&on, sizeof(on));
+
+ if (err < 0)
+ syslog (LOG_ERR, "setsockopt (IPV6_V6ONLY): %m");
+ }
+#endif
+
+ if (strncmp (sep->se_proto, "tcp", 3) == 0 && (options & SO_DEBUG))
{
+ err = setsockopt(sep->se_fd, SOL_SOCKET, SO_DEBUG,
+ (char *)&on, sizeof (on));
+ if (err < 0)
+ syslog (LOG_ERR, "setsockopt (SO_DEBUG): %m");
+ }
+
+ err = setsockopt(sep->se_fd, SOL_SOCKET, SO_REUSEADDR,
+ (char *)&on, sizeof (on));
+ if (err < 0)
+ syslog (LOG_ERR, "setsockopt (SO_REUSEADDR): %m");
+
+ err = bind (sep->se_fd, (struct sockaddr *)&sep->se_ctrladdr,
+ sizeof (sep->se_ctrladdr));
+ if (err < 0)
+ {
+#ifdef IPV6
+ /* If we can't bind with AF_INET6 try again with AF_INET. */
+ if ((errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT)
+ && sep->se_family == AF_INET6 && sep->se_v4mapped)
+ {
+ /* Fall back to IPv6 silently. */
+ sep->se_family = AF_INET;
+ close (sep->se_fd);
+ goto tryagain;
+ }
+#endif
if (debug)
fprintf (stderr, "bind failed on %s/%s: %s\n",
sep->se_service, sep->se_proto, strerror (errno));
@@ -952,7 +1084,7 @@ endconfig (FILE *fconfig)
#define INETD_SERVER_PATH 5 /* server program path */
#define INETD_SERVER_ARGS 6 /* server program arguments */
-#define INETD_FIELDS_MIN 7 /* Minimum number of fields in entry */
+#define INETD_FIELDS_MIN 6 /* Minimum number of fields in entry */
struct servtab *
getconfigent (FILE *fconfig, const char *file, size_t *line)
@@ -960,7 +1092,7 @@ getconfigent (FILE *fconfig, const char
struct servtab *sep = &serv;
size_t argc = 0, i;
char **argv = NULL;
- char *cp, *arg;
+ char *cp;
static char TCPMUX_TOKEN[] = "tcpmux/";
#define MUX_LEN (sizeof(TCPMUX_TOKEN)-1)
@@ -1025,6 +1157,37 @@ getconfigent (FILE *fconfig, const char
sep->se_proto = newstr (argv[INETD_PROTOCOL]);
+#ifdef IPV6
+ /* We default to IPv6, in setup() we'll fall back to IPv4 if
+ it doesn't work. */
+ sep->se_family = AF_INET6;
+ sep->se_v4mapped = 1;
+
+ if ((strncmp (sep->se_proto, "tcp", 3) == 0)
+ || (strncmp (sep->se_proto, "udp", 3) == 0))
+ {
+ if (sep->se_proto[3] == '6')
+ {
+ sep->se_family = AF_INET6;
+ sep->se_v4mapped = 0;
+ }
+ else if (sep->se_proto[3] == '4')
+ {
+ sep->se_family = AF_INET;
+ }
+ }
+#else
+ if ((strncmp (sep->se_proto, "tcp6", 4) == 0)
+ || (strncmp (sep->se_proto, "udp6", 4) == 0))
+ {
+ syslog (LOG_ERR, "%s:%lu: %s: IPv6 support isn't eneabled",
+ file, (unsigned long) *line, sep->se_proto);
+ continue;
+ }
+
+ sep->se_family = AF_INET;
+#endif
+
if (strcmp (argv[INETD_WAIT], "wait") == 0)
sep->se_wait = 1;
else if (strcmp (argv[INETD_WAIT], "nowait") == 0)
@@ -1043,7 +1206,7 @@ getconfigent (FILE *fconfig, const char
*/
sep->se_wait = 0;
- if (strcmp (sep->se_proto, "tcp"))
+ if (strncmp (sep->se_proto, "tcp", 3))
{
syslog (LOG_ERR, "%s:%lu: bad protocol for tcpmux service %s",
file, (unsigned long) *line, sep->se_service);
@@ -1103,8 +1266,6 @@ getconfigent (FILE *fconfig, const char
void
freeconfig (struct servtab *cp)
{
- int i;
-
if (cp->se_service)
free (cp->se_service);
if (cp->se_proto)
@@ -1144,13 +1305,31 @@ set_proc_title (char *a, int s)
{
int size;
char *cp;
- struct sockaddr_in lsin;
+#ifdef IPV6
+ struct sockaddr_storage saddr;
+#else
+ struct sockaddr_in saddr;
+#endif
char buf[80];
cp = Argv[0];
- size = sizeof lsin;
- if (getpeername (s, (struct sockaddr *)&lsin, &size) == 0)
- snprintf (buf, sizeof buf, "-%s [%s]", a, inet_ntoa (lsin.sin_addr));
+ size = sizeof saddr;
+ if (getpeername (s, (struct sockaddr *)&saddr, &size) == 0)
+ {
+#ifdef IPV6
+ int err;
+ char buf2[80];
+
+ err = getnameinfo ((struct sockaddr *) &saddr, sizeof (saddr), buf2,
+ sizeof (buf2), NULL, 0, NI_NUMERICHOST);
+ if (!err)
+ snprintf (buf, sizeof buf, "-%s [%s]", a, buf2);
+ else
+ snprintf (buf, sizeof buf, "-%s", a);
+#else
+ snprintf (buf, sizeof buf, "-%s [%s]", a, inet_ntoa (saddr.sin_addr));
+#endif
+ }
else
snprintf (buf, sizeof buf, "-%s", a);
strncpy (cp, buf, LastArg - cp);
@@ -1186,13 +1365,18 @@ echo_dg (int s, struct servtab *sep)
{
char buffer[BUFSIZE];
int i, size;
+#ifdef IPV6
+ struct sockaddr_storage sa;
+#else
struct sockaddr sa;
+#endif
(void)sep;
size = sizeof sa;
- if ((i = recvfrom (s, buffer, sizeof buffer, 0, &sa, &size)) < 0)
+ i = recvfrom (s, buffer, sizeof buffer, 0, (struct sockaddr *)&sa, &size);
+ if (i < 0)
return;
- sendto (s, buffer, i, 0, &sa, sizeof sa);
+ sendto (s, buffer, i, 0, (struct sockaddr *) &sa, sizeof sa);
}
/* ARGSUSED */
@@ -1281,7 +1465,11 @@ chargen_stream (int s, struct servtab *s
void
chargen_dg (int s, struct servtab *sep)
{
+#ifdef IPV6
+ struct sockaddr_storage sa;
+#else
struct sockaddr sa;
+#endif
static char *rs;
int len, size;
char text[LINESIZ+2];
@@ -1294,7 +1482,7 @@ chargen_dg (int s, struct servtab *sep)
}
size = sizeof sa;
- if (recvfrom (s, text, sizeof text, 0, &sa, &size) < 0)
+ if (recvfrom (s, text, sizeof text, 0, (struct sockaddr *)&sa, &size) < 0)
return;
if ((len = endring - rs) >= LINESIZ)
@@ -1308,7 +1496,7 @@ chargen_dg (int s, struct servtab *sep)
rs = ring;
text[LINESIZ] = '\r';
text[LINESIZ + 1] = '\n';
- sendto (s, text, sizeof text, 0, &sa, sizeof sa);
+ sendto (s, text, sizeof text, 0, (struct sockaddr *)&sa, sizeof sa);
}
/*
@@ -1351,15 +1539,21 @@ void
machtime_dg (int s, struct servtab *sep)
{
long result;
+#ifdef IPV6
+ struct sockaddr_storage sa;
+#else
struct sockaddr sa;
+#endif
int size;
(void)sep; /* shutup gcc */
size = sizeof sa;
- if (recvfrom (s, (char *)&result, sizeof result, 0, &sa, &size) < 0)
+ if (recvfrom (s, (char *)&result, sizeof result, 0,
+ (struct sockaddr *)&sa, &size) < 0)
return;
result = machtime ();
- sendto (s, (char *) &result, sizeof result, 0, &sa, sizeof sa);
+ sendto (s, (char *) &result, sizeof result, 0,
+ (struct sockaddr *)&sa, sizeof sa);
}
/* ARGSUSED */
@@ -1384,17 +1578,21 @@ daytime_dg(int s, struct servtab *sep)
{
char buffer[256];
time_t lclock;
+#ifdef IPV6
+ struct sockaddr_storage sa;
+#else
struct sockaddr sa;
+#endif
int size;
(void)sep; /* shutup gcc */
lclock = time ((time_t *) 0);
size = sizeof sa;
- if (recvfrom (s, buffer, sizeof buffer, 0, &sa, &size) < 0)
+ if (recvfrom (s, buffer, sizeof buffer, 0, (struct sockaddr *)&sa, &size) <
0)
return;
sprintf (buffer, "%.24s\r\n", ctime (&lclock));
- sendto (s, buffer, strlen(buffer), 0, &sa, sizeof sa);
+ sendto (s, buffer, strlen(buffer), 0, (struct sockaddr *)&sa, sizeof sa);
}
/*
Index: telnet/commands.c
===================================================================
RCS file: /cvsroot/inetutils/inetutils/telnet/commands.c,v
retrieving revision 1.17
diff -u -p -r1.17 commands.c
--- telnet/commands.c 31 Aug 2003 22:31:59 -0000 1.17
+++ telnet/commands.c 19 May 2004 18:58:05 -0000
@@ -27,9 +27,9 @@
* SUCH DAMAGE.
*/
-#ifndef lint
+#if 0
static char sccsid[] = "@(#)commands.c 8.4 (Berkeley) 5/30/95";
-#endif /* not lint */
+#endif
#ifdef HAVE_CONFIG_H
#include <config.h>
@@ -72,6 +72,7 @@ static char sccsid[] = "@(#)commands.c 8
#include <malloc.h>
#endif
+#include <arpa/inet.h>
#include <arpa/telnet.h>
#include "general.h"
@@ -95,12 +96,7 @@ static char sccsid[] = "@(#)commands.c 8
#include <netinet/ip.h>
#endif
-#if defined(IPPROTO_IP) && defined(IP_TOS)
-int tos = -1;
-#endif /* defined(IPPROTO_IP) && defined(IP_TOS) */
-
-char *hostname;
-static char *_hostname = 0;
+char *hostname = 0;
extern char *getenv __P((const char *));
@@ -2199,246 +2195,324 @@ ayt_status()
}
#endif
-unsigned long inet_addr();
-
int
tn(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;
-#ifndef strrchr
- char *strrchr();
-#endif
- unsigned long sourceroute(), srlen;
-#endif
- char *cmd, *hostp = 0, *portp = 0, *user = 0;
-
- /* clear the socket address prior to use */
- memset((char *)&sin, 0, sizeof(sin));
+#ifdef IPV6
+ struct addrinfo *result, *aip, hints;
+#else
+ struct hostent *host = 0;
+ struct sockaddr_in sin;
+ struct servent *sp = 0;
+ in_addr_t temp;
+#endif
+ const int on = 1;
+ int err;
+ char *cmd, *hostp = 0, *portp = 0, *user = 0;
- if (connected) {
- printf("?Already connected to %s\n", hostname);
- setuid(getuid());
- return 0;
- }
- if (argc < 2) {
- (void) strcpy(line, "open ");
- printf("(to) ");
- (void) fgets(&line[strlen(line)], sizeof(line) - strlen(line), stdin);
- makeargv();
- argc = margc;
- argv = margv;
+#ifdef IPV6
+ memset (&hints, 0, sizeof (hints));
+#else
+ /* clear the socket address prior to use */
+ memset ((char *)&sin, 0, sizeof(sin));
+#endif
+
+ if (connected)
+ {
+ printf("?Already connected to %s\n", hostname);
+ return 0;
}
- cmd = *argv;
- --argc; ++argv;
- while (argc) {
- if (strcmp(*argv, "help") == 0 || isprefix(*argv, "?"))
+ if (argc < 2)
+ {
+ (void) strcpy(line, "open ");
+ printf("(to) ");
+ (void) fgets(&line[strlen(line)], sizeof(line) - strlen(line), stdin);
+ makeargv();
+ argc = margc;
+ argv = margv;
+ }
+ cmd = *argv;
+ --argc; ++argv;
+ while (argc)
+ {
+ if (strcmp(*argv, "help") == 0 || isprefix(*argv, "?"))
+ goto usage;
+ if (strcmp(*argv, "-l") == 0)
+ {
+ --argc; ++argv;
+ if (argc == 0)
goto usage;
- if (strcmp(*argv, "-l") == 0) {
- --argc; ++argv;
- if (argc == 0)
- goto usage;
- user = *argv++;
- --argc;
- continue;
+ user = *argv++;
+ --argc;
+ continue;
}
- if (strcmp(*argv, "-a") == 0) {
- --argc; ++argv;
- autologin = 1;
- continue;
+ if (strcmp(*argv, "-a") == 0)
+ {
+ --argc; ++argv;
+ autologin = 1;
+ continue;
}
- if (hostp == 0) {
- hostp = *argv++;
- --argc;
- continue;
+ if (strcmp(*argv, "-6") == 0)
+ {
+ --argc; ++argv;
+#ifdef IPV6
+ hints.ai_family = AF_INET6;
+#else
+ puts ("IPv6 isn't supported");
+#endif
+ continue;
}
- if (portp == 0) {
- portp = *argv++;
- --argc;
- continue;
+ if (strcmp(*argv, "-4") == 0)
+ {
+ --argc; ++argv;
+#ifdef IPV6
+ hints.ai_family = AF_INET;
+#endif
+ continue;
+ }
+ if (hostp == 0)
+ {
+ hostp = *argv++;
+ --argc;
+ continue;
+ }
+ if (portp == 0)
+ {
+ portp = *argv++;
+ --argc;
+ continue;
}
usage:
- printf("usage: %s [-l user] [-a] host-name [port]\n", cmd);
- setuid(getuid());
- return 0;
+ printf("usage: %s [-4] [-6] [-l user] [-a] host-name [port]\n", cmd);
+ return 0;
}
- if (hostp == 0)
- goto usage;
+ if (hostp == 0)
+ goto usage;
-#if defined(IP_OPTIONS) && defined(IPPROTO_IP)
- if (hostp[0] == '@' || hostp[0] == '!') {
- if ((hostname = strrchr(hostp, ':')) == NULL)
- hostname = strrchr(hostp, '@');
- hostname++;
- srp = 0;
- temp = sourceroute(hostp, &srp, &srlen);
- if (temp == 0) {
- herror(srp);
- setuid(getuid());
- return 0;
- } else if (temp == -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;
+ if (!portp)
+ {
+ portp = "telnet";
+ telnetport = 1;
+ }
+ else
+ {
+ if (*portp == '-')
+ {
+ portp++;
+ telnetport = 1;
}
- } else {
+ else
+ telnetport = 0;
+ }
+
+ if (hostname)
+ free (hostname);
+ hostname = malloc (strlen (hostp) + 1);
+ if (hostname)
+ strcpy (hostname, hostp);
+ else
+ {
+ printf ("Can't allocate memory to copy hostname\n");
+ return 0;
+ }
+
+#ifdef IPV6
+#ifdef AI_ADDRCONFIG
+ hints.ai_flags = AI_ADDRCONFIG;
#endif
- temp = inet_addr(hostp);
- if (temp != (unsigned long) -1) {
- sin.sin_addr.s_addr = temp;
- sin.sin_family = AF_INET;
+ hints.ai_socktype = SOCK_STREAM;
- } 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) */
+ err = getaddrinfo (hostp, portp, &hints, &result);
+ if (err)
+ {
+ const char *errmsg;
+
+ if (err == EAI_SYSTEM)
+ errmsg = strerror (errno);
+ else
+ errmsg = gai_strerror (err);
+
+ printf ("%s/%s: lookup failure: %s\n", hostp, portp, errmsg);
+ return 0;
+ }
+
+ aip = result;
+
+ do
+ {
+ char buf[256];
+
+ err = getnameinfo (aip->ai_addr, aip->ai_addrlen, buf, sizeof (buf),
+ NULL, 0, NI_NUMERICHOST);
+ if (err)
+ {
+ /* I don't know how thing can happen, but we just handle it. */
+ const char *errmsg;
+
+ if (err == EAI_SYSTEM)
+ errmsg = strerror (errno);
+ else
+ errmsg = gai_strerror (err);
+
+ printf ("getnameinfo error: %s\n", errmsg);
+ return 0;
+ }
+
+ printf ("Trying %s...\n", buf);
+ net = socket (aip->ai_family, SOCK_STREAM, 0);
+ if (net < 0)
+ {
+ perror("telnet: socket");
+ return 0;
+ }
+
+ if (debug)
+ {
+ err = setsockopt (net, SOL_SOCKET, SO_DEBUG, &on, sizeof(on));
+ if (err < 0)
+ perror("setsockopt (SO_DEBUG)");
+ }
+
+ err = connect (net, (struct sockaddr *)aip->ai_addr, aip->ai_addrlen);
+ if (err < 0)
+ {
+ if (aip->ai_next)
+ {
+ perror ("Connection failed");
+ aip = aip->ai_next;
+ close (net);
+ continue;
}
+
+ perror("telnet: Unable to connect to remote host");
+ return 0;
}
- if (_hostname)
- free (_hostname);
- _hostname = malloc (strlen (hostp) + 1);
- if (_hostname) {
- strcpy (_hostname, hostp);
- hostname = _hostname;
- } else {
- printf ("Can't allocate memory to copy hostname\n");
- setuid(getuid());
- return 0;
- }
-#if defined(IP_OPTIONS) && defined(IPPROTO_IP)
+
+ connected++;
+#if defined(AUTHENTICATION) || defined(ENCRYPTION)
+ auth_encrypt_connect(connected);
+#endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */
+ } while (!connected);
+
+ freeaddrinfo (result);
+#else /* !IPV6 */
+ temp = inet_addr (hostp);
+ if (temp != (in_addr_t) -1)
+ {
+ sin.sin_addr.s_addr = temp;
+ sin.sin_family = AF_INET;
}
-#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 !HAVE_DECL_HTONS
-#ifndef htons
- u_short htons __P((unsigned short));
-#endif
-#endif
- sin.sin_port = htons (sin.sin_port);
+ else
+ {
+ host = gethostbyname (hostp);
+ if (host)
+ {
+ sin.sin_family = host->h_addrtype;
+ memmove (&sin.sin_addr, host->h_addr_list[0], host->h_length);
}
- } 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;
+ else
+ {
+ printf ("Can't lookup hostname %s\n", hostp);
+ return 0;
}
- telnetport = 1;
}
- printf("Trying %s...\n", inet_ntoa(sin.sin_addr));
- do {
- net = socket(AF_INET, SOCK_STREAM, 0);
- setuid(getuid());
- if (net < 0) {
- perror("telnet: socket");
- return 0;
+
+ sin.sin_port = atoi (portp);
+ if (sin.sin_port == 0)
+ {
+ sp = getservbyname (portp, "tcp");
+ if (sp == 0)
+ {
+ printf ("tcp/%s: unknown service\n", portp);
+ 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 defined(IPPROTO_IP) && defined(IP_TOS)
+ sin.sin_port = sp->s_port;
+ }
+ else
+ sin.sin_port = htons (sin.sin_port);
+
+ printf("Trying %s...\n", inet_ntoa(sin.sin_addr));
+ do
+ {
+ net = socket(AF_INET, SOCK_STREAM, 0);
+ if (net < 0)
{
-# if defined(HAS_GETTOS)
- struct tosent *tp;
- if (tos < 0 && (tp = gettosbyname("telnet", "tcp")))
- tos = tp->t_tos;
-# endif
- if (tos < 0)
- tos = 020; /* Low Delay bit */
- if (tos
- && (setsockopt(net, IPPROTO_IP, IP_TOS,
- (char *)&tos, sizeof(int)) < 0)
- && (errno != ENOPROTOOPT))
- perror("telnet: setsockopt (IP_TOS) (ignored)");
+ perror("telnet: socket");
+ return 0;
}
+#if defined(IPPROTO_IP) && defined(IP_TOS)
+ {
+#ifdef IPTOS_LOWDELAY
+ const int tos = IPTOS_LOWDELAY;
+#else
+ const int tos = 0x10;
+#endif
+
+ err = setsockopt (net, IPPROTO_IP, IP_TOS,
+ (char *)&tos, sizeof(tos));
+ if (err < 0 && errno != ENOPROTOOPT)
+ perror("telnet: setsockopt (IP_TOS) (ignored)");
+ }
#endif /* defined(IPPROTO_IP) && defined(IP_TOS) */
- if (debug && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 1) < 0) {
- perror("setsockopt (SO_DEBUG)");
- }
+ if (debug && setsockopt(net, SOL_SOCKET, SO_DEBUG, &on, sizeof(on)) < 0)
+ 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++;
- memmove((caddr_t)&sin.sin_addr,
- host->h_addr_list[0], host->h_length);
- (void) NetClose(net);
- continue;
+ if (connect(net, (struct sockaddr *)&sin, sizeof (sin)) < 0)
+ {
+ 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++;
+ memmove((caddr_t)&sin.sin_addr,
+ host->h_addr_list[0], host->h_length);
+ close (net);
+ continue;
}
-#endif /* defined(h_addr) */
- perror("telnet: Unable to connect to remote host");
- return 0;
+ perror("telnet: Unable to connect to remote host");
+ return 0;
}
- connected++;
+ connected++;
#if defined(AUTHENTICATION) || defined(ENCRYPTION)
- auth_encrypt_connect(connected);
+ auth_encrypt_connect(connected);
#endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */
} while (connected == 0);
- cmdrc(hostp, hostname);
- if (autologin && user == NULL) {
- struct passwd *pw;
-
- user = getenv("USER");
- if (user == NULL ||
- (pw = getpwnam(user)) && pw->pw_uid != getuid()) {
- if (pw = getpwuid(getuid()))
- user = pw->pw_name;
- else
- user = NULL;
+#endif /* !IPV6 */
+ cmdrc(hostp, hostname);
+ if (autologin && user == NULL)
+ {
+ struct passwd *pw;
+
+ user = getenv("USER");
+ if (user == NULL ||
+ (pw = getpwnam(user)) && pw->pw_uid != getuid())
+ {
+ if (pw = getpwuid(getuid()))
+ user = pw->pw_name;
+ else
+ user = NULL;
}
}
- if (user) {
- env_define((unsigned char *)"USER", (unsigned char *)user);
- env_export((unsigned char *)"USER");
+ if (user)
+ {
+ env_define((unsigned char *)"USER", (unsigned char *)user);
+ env_export((unsigned char *)"USER");
}
- (void) call(status, "status", "notmuch", 0);
- if (setjmp(peerdied) == 0)
- telnet(user);
- (void) NetClose(net);
- ExitString("Connection closed by foreign host.\n",1);
- /*NOTREACHED*/
+ (void) call(status, "status", "notmuch", 0);
+ if (setjmp(peerdied) == 0)
+ telnet(user);
+
+ close (net);
+ ExitString("Connection closed by foreign host.\n",1);
+ /*NOTREACHED*/
+
+ return 0;
}
#define HELPINDENT (sizeof ("connect"))
@@ -2755,176 +2829,3 @@ cmdrc(char *m1, char *m2)
}
fclose(rcfile);
}
-
-#if defined(IP_OPTIONS) && defined(IPPROTO_IP)
-
-/*
- * Source route is handed in as
- * address@hidden@hop2...[@|:]dst
- * If the leading ! is present, it is a
- * strict source route, otherwise it is
- * assmed to be a loose source route.
- *
- * We fill in the source route option as
- * hop1,hop2,hop3...dest
- * and return a pointer to hop1, which will
- * be the address to connect() to.
- *
- * Arguments:
- * arg: pointer to route list to decipher
- *
- * cpp: If *cpp is not equal to NULL, this is a
- * pointer to a pointer to a character array
- * that should be filled in with the option.
- *
- * lenp: pointer to an integer that contains the
- * length of *cpp if *cpp != NULL.
- *
- * Return values:
- *
- * Returns the address of the host to connect to. 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
- * path is unknown, and *cpp is set to point to the bad
- * hostname.
- *
- * *cpp: If *cpp was equal to NULL, it will be filled
- * in with a pointer to our static area that has
- * the option filled in. This will be 32bit aligned.
- *
- * *lenp: This will be filled in with how long the option
- * pointed to by *cpp is.
- *
- */
-unsigned long
-sourceroute(char *arg, char **cpp, int *lenp)
-{
- static char lsr[44];
-#ifdef sysV88
- static IOPTN ipopt;
-#endif
- char *cp, *cp2, *lsrp, *lsrep;
- register int tmp;
- struct in_addr sin_addr;
- register struct hostent *host = 0;
- register char c;
-
- /*
- * Verify the arguments, and make sure we have
- * 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);
- /*
- * 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;
- } else {
- *cpp = lsrp = lsr;
- lsrep = lsrp + 44;
- }
-
- cp = arg;
-
- /*
- * Next, decide whether we have a loose source
- * route or a strict source route, and fill in
- * the begining of the option.
- */
-#ifndef sysV88
- if (*cp == '!') {
- cp++;
- *lsrp++ = IPOPT_SSRR;
- } else
- *lsrp++ = IPOPT_LSRR;
-#else
- if (*cp == '!') {
- cp++;
- ipopt.io_type = IPOPT_SSRR;
- } else
- ipopt.io_type = IPOPT_LSRR;
-#endif
-
- if (*cp != '@')
- return((unsigned long)-1);
-
-#ifndef sysV88
- lsrp++; /* skip over length, we'll fill it in later */
- *lsrp++ = 4;
-#endif
-
- cp++;
-
- sin_addr.s_addr = 0;
-
- for (c = 0;;) {
- if (c == ':')
- cp2 = 0;
- else for (cp2 = cp; c = *cp2; cp2++) {
- if (c == ',') {
- *cp2++ = '\0';
- if (*cp2 == '@')
- cp2++;
- } else if (c == '@') {
- *cp2++ = '\0';
- } else if (c == ':') {
- *cp2++ = '\0';
- } else
- continue;
- break;
- }
- if (!c)
- cp2 = 0;
-
- if ((tmp = inet_addr(cp)) != -1) {
- sin_addr.s_addr = tmp;
- } else if (host = gethostbyname(cp)) {
-#if defined(h_addr)
- memmove((caddr_t)&sin_addr,
- host->h_addr_list[0], host->h_length);
-#else
- memmove((caddr_t)&sin_addr, host->h_addr,
host->h_length);
-#endif
- } else {
- *cpp = cp;
- return(0);
- }
- memmove(lsrp, (char *)&sin_addr, 4);
- lsrp += 4;
- if (cp2)
- cp = cp2;
- else
- break;
- /*
- * Check to make sure there is space for next address
- */
- if (lsrp + 4 > lsrep)
- return((unsigned long)-1);
- }
-#ifndef sysV88
- if ((*(*cpp+IPOPT_OLEN) = lsrp - *cpp) <= 7) {
- *cpp = 0;
- *lenp = 0;
- return((unsigned long)-1);
- }
- *lsrp++ = IPOPT_NOP; /* 32 bit word align it */
- *lenp = lsrp - *cpp;
-#else
- ipopt.io_len = lsrp - *cpp;
- if (ipopt.io_len <= 5) { /* Is 3 better ? */
- *cpp = 0;
- *lenp = 0;
- return((unsigned long)-1);
- }
- *lenp = sizeof(ipopt);
- *cpp = (char *) &ipopt;
-#endif
- return(sin_addr.s_addr);
-}
-#endif
Index: telnet/main.c
===================================================================
RCS file: /cvsroot/inetutils/inetutils/telnet/main.c,v
retrieving revision 1.13
diff -u -p -r1.13 main.c
--- telnet/main.c 29 Apr 2002 21:22:31 -0000 1.13
+++ telnet/main.c 19 May 2004 18:58:05 -0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1988, 1990, 1993, 2002
+ * Copyright (c) 1988, 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,15 +27,9 @@
* SUCH DAMAGE.
*/
-#ifndef lint
-static char copyright[] =
-"@(#) Copyright (c) 1988, 1990, 1993\n\
- The Regents of the University of California. All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
+#if 0
static char sccsid[] = "@(#)main.c 8.3 (Berkeley) 5/30/95";
-#endif /* not lint */
+#endif
#ifdef HAVE_CONFIG_H
#include <config.h>
@@ -87,6 +81,8 @@ help ()
fprintf (stdout, USAGE, prompt);
puts ("Login to remote system HOST (optionally, on service port PORT)\n\n\
+ -4, --ipv4 Use only IPv4\n\
+ -6, --ipv6 Use only IPv6\n\
-8, --binary Use an 8-bit data path\n\
-a, --login Attempt automatic login\n\
-c, --no-rc Don't read the user's .telnetrc file\n\
@@ -98,7 +94,6 @@ help ()
-L, --binary-output Use an 8-bit data path for output only\n\
-n FILE, --trace=FILE Record trace information into FILE\n\
-r, --rlogin Use a user-interface similar to rlogin\n\
- -S TOS, --tos=TOS Use the IP type-of-service TOS\n\
-X ATYPE, --disable-auth=ATYPE Disable type ATYPE authentication");
#ifdef ENCRYPTION
@@ -155,6 +150,8 @@ usage ()
static struct option long_options[] =
{
+ { "ipv4", no_argument, 0, '4'},
+ { "ipv6", no_argument, 0, '6'},
{ "binary", no_argument, 0, '8' },
{ "login", no_argument, 0, 'a' },
{ "no-rc", no_argument, 0, 'c' },
@@ -166,7 +163,6 @@ static struct option long_options[] =
{ "binary-output", no_argument, 0, 'L' },
{ "trace", required_argument, 0, 'n' },
{ "rlogin", no_argument, 0, 'r' },
- { "tos", required_argument, 0, 'S' },
{ "disable-auth", required_argument, 0, 'X' },
{ "encrypt", no_argument, 0, 'x' },
{ "fwd-credentials", no_argument, 0, 'f' },
@@ -186,6 +182,7 @@ main(int argc, char *argv[])
extern char *optarg;
extern int optind;
int ch;
+ int family = 0;
char *user;
#ifndef strrchr
char *strrchr();
@@ -211,11 +208,19 @@ main(int argc, char *argv[])
rlogin = (strncmp(prompt, "rlog", 4) == 0) ? '~' : _POSIX_VDISABLE;
autologin = -1;
- while ((ch = getopt_long (argc, argv, "8EKLS:X:acde:fFk:l:n:rt:x",
+ while ((ch = getopt_long (argc, argv, "468EKLS:X:acde:fFk:l:n:rt:x",
long_options, 0))
!= EOF)
{
switch(ch) {
+ case '4':
+ family = 4;
+ break;
+
+ case '6':
+ family = 6;
+ break;
+
case '8':
eight = 3; /* binary output and input */
break;
@@ -230,23 +235,6 @@ main(int argc, char *argv[])
case 'L':
eight |= 2; /* binary output only */
break;
- case 'S':
- {
-#ifdef HAS_GETTOS
- extern int tos;
-
- if ((tos = parsetos(optarg, "tcp")) < 0)
- fprintf(stderr, "%s%s%s%s\n",
- prompt, ": Bad TOS argument '",
- optarg,
- "; will try to use default TOS");
-#else
- fprintf(stderr,
- "%s: Warning: -S ignored, no parsetos() support.\n",
- prompt);
-#endif
- }
- break;
case 'X':
#ifdef AUTHENTICATION
auth_disable_name(optarg);
@@ -374,7 +362,7 @@ main(int argc, char *argv[])
argv += optind;
if (argc) {
- char *args[7], **argp = args;
+ char *args[8], **argp = args;
if (argc > 2)
usage ();
@@ -383,6 +371,11 @@ main(int argc, char *argv[])
*argp++ = "-l";
*argp++ = user;
}
+ if (family == 4)
+ *argp++ = "-4";
+ else if (family == 6)
+ *argp++ = "-6";
+
*argp++ = argv[0]; /* host */
if (argc > 1)
*argp++ = argv[1]; /* port */
Index: telnetd/telnetd.c
===================================================================
RCS file: /cvsroot/inetutils/inetutils/telnetd/telnetd.c,v
retrieving revision 1.31
diff -u -p -r1.31 telnetd.c
--- telnetd/telnetd.c 5 Apr 2003 16:45:08 -0000 1.31
+++ telnetd/telnetd.c 19 May 2004 18:58:15 -0000
@@ -1,4 +1,4 @@
-/* Copyright (C) 1998,2001, 2002 Free Software Foundation, Inc.
+/* Copyright (C) 1998, 2001, 2002, 2004 Free Software Foundation, Inc.
This file is part of GNU Inetutils.
@@ -275,10 +275,16 @@ extern char *localhost __P ((void));
void
telnetd_setup (int fd)
{
+#ifdef IPV6
+ struct sockaddr_storage saddr;
+ char buf[256], buf2[256]; /* FIXME: We should use dynamic allocation. */
+ int err;
+#else
struct sockaddr_in saddr;
+ struct hostent *hp;
+#endif
int true = 1;
socklen_t len;
- struct hostent *hp;
char uname[256]; /*FIXME*/
int level;
@@ -289,8 +295,84 @@ telnetd_setup (int fd)
exit (1);
}
- syslog (LOG_INFO, "Connect from %s", inet_ntoa (saddr.sin_addr));
-
+#ifdef IPV6
+ err = getnameinfo ((struct sockaddr *) &saddr, sizeof (saddr), buf,
+ sizeof (buf), NULL, 0, NI_NUMERICHOST);
+ if (err)
+ {
+ const char *errmsg;
+
+ if (err == EAI_SYSTEM)
+ errmsg = strerror (errno);
+ else
+ errmsg = gai_strerror (err);
+
+ syslog (LOG_AUTH|LOG_NOTICE, "Cannot get address: %s", errmsg);
+ fatal (fd, "Cannot get address.");
+ }
+
+ /* We use a second buffer so we don't have to call getnameinfo again
+ if we need the numeric host below. */
+ err = getnameinfo ((struct sockaddr *) &saddr, sizeof (saddr), buf2,
+ sizeof (buf2), NULL, 0, NI_NAMEREQD);
+
+ if (reverse_lookup)
+ {
+ struct addrinfo *result, *aip;
+
+ if (err)
+ {
+ const char *errmsg;
+
+ if (err == EAI_SYSTEM)
+ errmsg = strerror (errno);
+ else
+ errmsg = gai_strerror (err);
+
+ syslog (LOG_AUTH|LOG_NOTICE, "Can't resolve %s: %s", buf, errmsg);
+ fatal (fd, "Cannot resolve address.");
+ }
+
+ remote_hostname = xstrdup (buf2);
+
+ err = getaddrinfo (remote_hostname, NULL, NULL, &result);
+ if (err)
+ {
+ const char *errmsg;
+
+ if (err == EAI_SYSTEM)
+ errmsg = strerror (errno);
+ else
+ errmsg = gai_strerror (err);
+
+ syslog (LOG_AUTH|LOG_NOTICE, "Forward resolve of %s failed: %s",
+ remote_hostname, errmsg);
+ fatal (fd, "Cannot resolve address.");
+ }
+
+ for (aip = result; aip; aip = aip->ai_next)
+ if (!memcmp (aip->ai_addr, &saddr, aip->ai_addrlen))
+ break;
+
+ if (aip == NULL)
+ {
+ syslog (LOG_AUTH|LOG_NOTICE,
+ "None of addresses of %s matched %s",
+ remote_hostname,
+ buf);
+ exit (0);
+ }
+
+ freeaddrinfo (result);
+ }
+ else
+ {
+ if (!err)
+ remote_hostname = xstrdup (buf2);
+ else
+ remote_hostname = xstrdup (buf);
+ }
+#else
hp = gethostbyaddr ((char*)&saddr.sin_addr.s_addr,
sizeof (saddr.sin_addr.s_addr), AF_INET);
if (reverse_lookup)
@@ -337,6 +419,7 @@ telnetd_setup (int fd)
else
remote_hostname = xstrdup (inet_ntoa (saddr.sin_addr));
}
+#endif
/* Set socket options */