bug-inetutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[bug-inetutils] IPv6 support for inetd, telnet and telnetd


From: Jeroen Dekkers
Subject: [bug-inetutils] IPv6 support for inetd, telnet and telnetd
Date: Mon, 19 Apr 2004 16:36:31 +0200
User-agent: Mutt/1.5.5.1+cvs20040105i

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. :)


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 Apr 2004 13:27:58 -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 Apr 2004 13:27:58 -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 Apr 2004 13:27:59 -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 Apr 2004 13:27:59 -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,320 @@ 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;
-       }
-    } else {
+  telnetport = 0;
+  if (portp && *portp == '-')
+    {
+      portp++;
+      telnetport = 1;
+    }
+  else
+    {
+      telnetport = 1;
+      portp = "telnet";
+    }
+
+  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 +2825,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 Apr 2004 13:27:59 -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 Apr 2004 13:27:59 -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 */
 


-- 
Jeroen Dekkers

Attachment: signature.asc
Description: Digital signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]