[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[bug-inetutils] New IPv6 patch for inetutils
From: |
Jeroen Dekkers |
Subject: |
[bug-inetutils] New IPv6 patch for inetutils |
Date: |
Wed, 07 Jul 2004 00:20:55 +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) |
Hey,
Here is a new IPv6 patch for inetutils. It's actually the same except
that this patch also adds ping6. Comments/suggestions/bugfixes/etc are
welcome.
2004-07-06 Jeroen Dekkers <address@hidden>
* acinclude.m4 (IU_ENABLE_FOO): Use AS_HELP_STRING.
(IU_CHECK_KRB5): Quote correctly.
* configure.ac: Add checks for IPv6.
doc/
2004-07-06 Jeroen Dekkers <address@hidden>
* inetd.texi (inetd): Document IPv6 configuration options.
inetd/
2004-07-06 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.
ping/
2004-07-06 Jeroen Dekkers <address@hidden>
* Makefile.am: Add ping6.
(ping_SOURCES): Add ping_common.c and ping_common.h.
* ping6.c: New file.
* ping6.h: Likewise.
* ping_common.c: Likewise.
* ping_common.h: Likewise.
* ping.c: Include "ping_common.h". Remove __P macro in
prototypes.
(ping_cvt_number, init_data_buffer,
decode_pattern, show_license): Move to ...
* ping_common.c: ... here.
* ping_echo.c: Include "ping_common.h".
(tvsub, nabs, nsqrt): Move to ...
* ping_common.c: ... here.
telnet/
2004-07-06 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-07-06 Jeroen Dekkers <address@hidden>
* telnetd.c (telnetd_setup): Add support for IPv6.
Index: acinclude.m4
===================================================================
RCS file: /cvsroot/inetutils/inetutils/acinclude.m4,v
retrieving revision 1.11
diff -u -p -r1.11 acinclude.m4
--- acinclude.m4 30 Jan 2004 13:14:54 -0000 1.11
+++ acinclude.m4 6 Jul 2004 22:06:43 -0000
@@ -1,6 +1,6 @@
dnl Autoconf macros used by inetutils
dnl
-dnl Copyright (C) 1996, 1997, 1998, 2002 Free Software Foundation, Inc.
+dnl Copyright (C) 1996, 1997, 1998, 2002, 2004 Free Software Foundation, Inc.
dnl
dnl Mostly written by Miles Bader <address@hidden>
dnl
@@ -457,7 +457,7 @@ EOF
AC_SUBST_FILE([$3])])
AC_DEFUN([IU_ENABLE_FOO],
- [AC_ARG_ENABLE($1, [ --disable-$1 don't compile $1], ,
+ [AC_ARG_ENABLE($1, AS_HELP_STRING([--disable-$1], [don't compile $1]), ,
[enable_]$1[=$enable_]$2)
[if test "$enable_$1" = yes; then
$1_BUILD=$1
@@ -558,7 +558,7 @@ dnl if it is set and not "yes".
dnl VERSION should be either 4 or 5
dnl Defines KRB_CFLAGS and KRB_LIBS if found.
dnl Defines KRB_IMPL to "Heimdal", "MIT", or "OldMIT", or "none" if not found
-AC_DEFUN(IU_CHECK_KRB5,
+AC_DEFUN([IU_CHECK_KRB5],
[
if test "x$iu_cv_lib_krb5_libs" = x; then
cache=""
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 6 Jul 2004 22:06:43 -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>
#
@@ -74,6 +74,7 @@ IU_ENABLE_SERVER(uucpd)
IU_ENABLE_CLIENT(ftp)
IU_ENABLE_CLIENT(ping)
+IU_ENABLE_CLIENT(ping6)
IU_ENABLE_CLIENT(rcp)
IU_ENABLE_CLIENT(rlogin)
IU_ENABLE_CLIENT(rsh)
@@ -282,6 +283,111 @@ if test ".$LIBAUTH" != .; then
[Define to one if you want encryption.])
fi
+dnl Checks for IPv6 support.
+
+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]
+)
+
+working_ipv6=yes
+if test ! "X$ipv6" = "Xno" -a "X$working_ipv6" = "Xyes"; then
+ IU_CHECK_MACRO(AF_INET6, [#include <sys/socket.h>], , , working_ipv6=no)
+fi
+
+if test ! "X$ipv6" = "Xno" -a "X$working_ipv6" = "Xyes"; then
+ IU_CHECK_MACRO(IPV6_V6ONLY, [#include <netinet/in.h>], , , working_ipv6=no)
+fi
+
+if test ! "X$ipv6" = "Xno" -a "X$working_ipv6" = "Xyes"; then
+ AC_CHECK_TYPE(struct sockaddr_storage, , working_ipv6=no, [#include
<sys/socket.h>])
+fi
+
+if test ! "X$ipv6" = "Xno" -a "X$working_ipv6" = "Xyes"; then
+ AC_CHECK_TYPE(struct sockaddr_in6, , working_ipv6=no, [#include
<netinet/in.h>])
+fi
+
+if test ! "X$ipv6" = "Xno" -a "X$working_ipv6" = "Xyes"; then
+ AC_CHECK_TYPE(struct addrinfo, , working_ipv6=no, [#include <netdb.h>])
+fi
+
+if test ! "X$ipv6" = "Xno" -a "X$working_ipv6" = "Xyes"; then
+ AC_CHECK_FUNC(getaddrinfo, ,working_ipv6=no, [#include <netdb.h>])
+fi
+
+if test ! "X$ipv6" = "Xno" -a "X$working_ipv6" = "Xyes"; then
+ AC_CHECK_FUNC(getnameinfo, ,working_ipv6=no, [#include <netdb.h>])
+fi
+
+if test ! "X$ipv6" = "Xno" -a "X$working_ipv6" = "Xyes"; then
+ 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
+ if test "X$ipv6" = "Xauto"; then
+ AC_MSG_WARN([IPv6 support not available, disabling IPv6])
+ fi
+ fi
+fi
+
+if test "X$ipv6" = "Xno" -o "X$working_ipv6" = "Xno";then
+ ping6_BUILD=''
+else
+ working_icmp6=yes
+
+ AC_CHECK_HEADER(netinet/icmp6.h, , working_icmp6=no)
+
+ if test "X$working_icmp6" = "Xyes"; then
+ AC_CHECK_HEADER(netinet/ip6.h, , working_icmp6=no)
+ fi
+
+ if test "X$working_icmp6" = "Xyes"; then
+ AC_CHECK_TYPE(struct icmp6_filter, , working_icmp6=no, [#include
<netinet/icmp6.h>])
+ fi
+
+ if test "X$working_icmp6" = "Xyes"; then
+ AC_CHECK_TYPE(struct icmp6_hdr, , working_icmp6=no, [#include
<netinet/icmp6.h>])
+ fi
+
+ if test "X$working_icmp6" = "Xyes"; then
+ IU_CHECK_MACRO(IPV6_RECVHOPLIMIT, [#include <netinet/in.h>], ,
+ [have_recvhoplimt=yes], [have_recvhoplimt=no])
+ if test "X$have_recvhoplimt" = "Xno"; then
+ IU_CHECK_MACRO(IPV6_HOPLIMIT, [#include <netinet/in.h>], , [
+ AC_DEFINE(IPV6_RECVHOPLIMIT, IPV6_HOPLIMIT,
+ [Define to IPV6_HOPLIMIT if not available])
+ ], [working_icmp6=no])
+ fi
+ fi
+
+ if test "X$working_icmp6" = "Xyes"; then
+ IU_CHECK_MACRO(ICMP6_DST_UNREACH_BEYONDSCOPE, [#include
<netinet/icmp6.h>], ,
+ [have_beyondscope=yes], [have_beyondscope=no])
+ if test "X$have_beyondscope" = "Xno"; then
+ IU_CHECK_MACRO(ICMP6_DST_UNREACH_NOTNEIGHBOR, [#include
<netinet/icmp6.h>], , [
+ AC_DEFINE(ICMP6_DST_UNREACH_BEYONDSCOPE, ICMP6_DST_UNREACH_NOTNEIGHBOR,
+ [Define to ICMP6_DST_UNREACH_NOTNEIGHBOR if not available])
+ ], [working_icmp6=no])
+ fi
+ fi
+
+ if test "X$working_icmp6" = "Xno"; then
+ AC_MSG_WARN([ICMPv6 support not available, disabling ping6])
+ ping6_BUILD=''
+ fi
+fi
+
+
dnl Check if they want support for Wrap. Certain daemons like
dnl ftpd have support for it.
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 6 Jul 2004 22:06:43 -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 6 Jul 2004 22:06:43 -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 },
@@ -267,7 +291,7 @@ signal_set_handler (int signo, RETSIGTYP
struct sigvec sv;
memset (&sv, 0, sizeof(sv));
sv.sv_mask = SIGBLOCK;
- sv.sv_handler = retry;
+ sv.sv_handler = handler;
sigvec (signo, &sv, NULL);
#else /* !HAVE_SIGVEC */
signal (signo, handler);
@@ -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: ping/Makefile.am
===================================================================
RCS file: /cvsroot/inetutils/inetutils/ping/Makefile.am,v
retrieving revision 1.13
diff -u -p -r1.13 Makefile.am
--- ping/Makefile.am 15 Jan 2003 08:32:40 -0000 1.13
+++ ping/Makefile.am 6 Jul 2004 22:06:43 -0000
@@ -1,29 +1,30 @@
AUTOMAKE_OPTIONS = ../ansi2knr
-bin_PROGRAMS = @ping_BUILD@
+bin_PROGRAMS = @ping_BUILD@ @ping6_BUILD@
-EXTRA_PROGRAMS = ping
+EXTRA_PROGRAMS = ping ping6
man_MANS = ping.8
EXTRA_DIST = $(man_MANS)
-LDADD = -L../libinetutils -linetutils -L../libicmp -licmp
-INCLUDES = -I$(top_srcdir)/libicmp -I$(top_builddir)/include
+ping_LDADD = -L../libinetutils -linetutils -L../libicmp -licmp
+ping6_LDADD = -L../libinetutils -linetutils
+INCLUDES = -I$(top_srcdir)/libinetutils -I$(top_srcdir)/libicmp
-I$(top_builddir)/include
-ping_SOURCES = ping.c \
- ping_echo.c \
- ping_address.c \
- ping_router.c \
- ping_timestamp.c \
- ping_impl.h
+ping_SOURCES = ping.c ping_common.c ping_echo.c ping_address.c \
+ ping_router.c ping_timestamp.c ping_common.h ping_impl.h
+
+ping6_SOURCES = ping6.c ping_common.c ping_common.h ping6.h
SUIDMODE = -o root -m 4775
install-exec-hook:
- address@hidden(INSTALL_PROGRAM) $(bin_PROGRAMS) $(SUIDMODE)
$(AM_INSTALL_PROGRAM_FLAGS) $(DESTDIR)$(bindir)/`echo $(bin_PROGRAMS)|sed
'$(transform)'` ; \
+ address@hidden program in $(bin_PROGRAMS); do \
+ $(INSTALL_PROGRAM) $$program $(SUIDMODE) $(AM_INSTALL_PROGRAM_FLAGS)
$(DESTDIR)$(bindir)/`echo $$program|sed '$(transform)'` ; \
if test $$? -ne 0; then \
echo 'INSTALL-ERROR:'; \
- echo 'INSTALL-ERROR: THIS PROGRAM($(bin_PROGRAMS)) MUST BE
INSTALLED SETUID ROOT'; \
- echo 'INSTALL-ERROR: $(INSTALL_PROGRAM) $(bin_PROGRAMS)
$(SUIDMODE) $(DESTDIR)$(bindir)/$(bin_PROGRAMS)'; \
+ echo 'INSTALL-ERROR: THIS PROGRAM($$program) MUST BE INSTALLED
SETUID ROOT'; \
+ echo 'INSTALL-ERROR: $(INSTALL_PROGRAM) $(bin_PROGRAMS)
$(SUIDMODE) $(DESTDIR)$(bindir)/$$program'; \
echo 'INSTALL-ERROR:'; \
- fi
+ fi; \
+ done
Index: ping/ping.c
===================================================================
RCS file: /cvsroot/inetutils/inetutils/ping/ping.c,v
retrieving revision 1.19
diff -u -p -r1.19 ping.c
--- ping/ping.c 3 Mar 2004 10:21:03 -0000 1.19
+++ ping/ping.c 6 Jul 2004 22:06:43 -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.
@@ -45,10 +45,11 @@
#include <errno.h>
#include <limits.h>
-#include "getopt.h"
+#include <getopt.h>
#include <icmp.h>
#include <ping.h>
-#include <ping_impl.h>
+#include "ping_common.h"
+#include "ping_impl.h"
static char short_options[] = "VLhc:dfi:l:np:qRrs:t:v";
static struct option long_options[] =
@@ -80,52 +81,23 @@ static struct option long_options[] =
{NULL, no_argument, NULL, 0}
};
-extern int ping_echo __P ((int argc, char **argv));
-extern int ping_timestamp __P ((int argc, char **argv));
-extern int ping_address __P ((int argc, char **argv));
-extern int ping_router __P ((int argc, char **argv));
+extern int ping_echo (int argc, char **argv);
+extern int ping_timestamp (int argc, char **argv);
+extern int ping_address (int argc, char **argv);
+extern int ping_router (int argc, char **argv);
PING *ping;
u_char *data_buffer;
size_t data_length = PING_DATALEN;
unsigned options;
unsigned long preload = 0;
-int (*ping_type) __P ((int argc, char **argv)) = ping_echo;
+int (*ping_type) (int argc, char **argv) = ping_echo;
static void show_usage (void);
-static void show_license (void);
-static void decode_pattern (const char *text, int *pattern_len,
- u_char *pattern_data);
static void decode_type (const char *optarg);
-static void init_data_buffer (u_char *pat, int len);
static int send_echo (PING *ping);
-static size_t
-ping_cvt_number (const char *optarg, size_t maxval, int allow_zero)
-{
- char *p;
- size_t n;
-
- n = strtoul (optarg, &p, 0);
- if (*p)
- {
- fprintf (stderr, "Invalid value (`%s' near `%s')\n", optarg, p);
- exit (1);
- }
- if (n == 0 && !allow_zero)
- {
- fprintf (stderr, "Option value too small: %s\n", optarg);
- exit (1);
- }
- if (maxval && n > maxval)
- {
- fprintf (stderr, "Option value too big: %s\n", optarg);
- exit (1);
- }
- return n;
-}
-
int
main (int argc, char **argv)
{
@@ -155,7 +127,7 @@ main (int argc, char **argv)
{
case 'V':
printf ("ping - %s %s\n", PACKAGE_NAME, PACKAGE_VERSION);
- printf ("Copyright (C) 1998,2001 Free Software Foundation, Inc.\n");
+ printf ("Copyright (C) 2004 Free Software Foundation, Inc.\n");
printf ("%s comes with ABSOLUTELY NO WARRANTY.\n", PACKAGE_NAME);
printf ("You may redistribute copies of %s\n", PACKAGE_NAME);
printf ("under the terms of the GNU General Public License.\n");
@@ -252,10 +224,20 @@ main (int argc, char **argv)
break;
case ICMP_ADDRESS:
+ if (!is_root)
+ {
+ fprintf (stderr, "ping: option not allowed: --address\n");
+ exit (1);
+ }
decode_type ("address");
break;
case ICMP_ROUTERDISCOVERY:
+ if (!is_root)
+ {
+ fprintf (stderr, "ping: option not allowed: --router\n");
+ exit (1);
+ }
decode_type ("router");
break;
@@ -279,37 +261,6 @@ main (int argc, char **argv)
}
void
-init_data_buffer (u_char *pat, int len)
-{
- int i = 0;
- u_char *p;
-
- if (data_length == 0)
- return;
- data_buffer = malloc (data_length);
- if (!data_buffer)
- {
- fprintf (stderr, "ping: out of memory\n");
- exit (1);
- }
- if (pat)
- {
- for (p = data_buffer; p < data_buffer + data_length; p++)
- {
- *p = pat[i];
- if (i++ >= len)
- i = 0;
- }
- }
- else
- {
- for (i = 0; i < data_length; i++)
- data_buffer[i] = i;
- }
-}
-
-
-void
decode_type (const char *optarg)
{
if (strcasecmp (optarg, "echo") == 0)
@@ -329,23 +280,6 @@ decode_type (const char *optarg)
}
}
-void
-decode_pattern (const char *text, int *pattern_len, u_char *pattern_data)
-{
- int i, c, off;
-
- for (i = 0; *text && i < *pattern_len; i++)
- {
- if (sscanf (text, "%2x%n", &c, &off) != 1)
- {
- fprintf (stderr, "ping: error in pattern near %s\n", text);
- exit (1);
- }
- text += off;
- }
- *pattern_len = i;
-}
-
int volatile stop = 0;
RETSIGTYPE
@@ -388,7 +322,7 @@ ping_run (PING *ping, int (*finish)())
while (!stop)
{
- int n, len;
+ int n;
FD_ZERO (&fdset);
FD_SET (ping->ping_fd, &fdset);
@@ -508,9 +442,9 @@ Informational options:\n\
-V, --version output version information and exit\n\
Options controlling ICMP request types:\n\
--echo Send ICMP_ECHO requests (default)\n\
- --address Send ICMP_ADDRESS packets\n\
+* --address Send ICMP_ADDRESS packets\n\
--timestamp Send ICMP_TIMESTAMP packets\n\
- --router Send ICMP_ROUTERDISCOVERY packets\n\
+* --router Send ICMP_ROUTERDISCOVERY packets\n\
Options valid for all request types:\n\
-c, --count N stop after sending N packets\n\
-d, --debug set the SO_DEBUG option\n\
@@ -532,24 +466,3 @@ Options marked with an * are available o
report bugs to " PACKAGE_BUGREPORT ".\n\
");
}
-
-void
-show_license (void)
-{
- static char license_text[] =
-" This program is free software; you can redistribute it and/or modify\n"
-" it under the terms of the GNU General Public License as published by\n"
-" the Free Software Foundation; either version 2, or (at your option)\n"
-" any later version.\n"
-"\n"
-" This program is distributed in the hope that it will be useful,\n"
-" but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
-" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
-" GNU General Public License for more details.\n"
-"\n"
-" You should have received a copy of the GNU General Public License\n"
-" along with this program; if not, write to the Free Software\n"
-" Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n";
- printf ("%s", license_text);
-}
-
Index: ping/ping6.c
===================================================================
RCS file: ping/ping6.c
diff -N ping/ping6.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ping/ping6.c 6 Jul 2004 22:06:43 -0000
@@ -0,0 +1,932 @@
+/* Copyright (C) 1998, 2001, 2002, 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. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <signal.h>
+
+#include <netinet/in.h>
+#include <netinet/ip6.h>
+#include <netinet/icmp6.h>
+
+#include <netdb.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+
+#include <getopt.h>
+#include <xalloc.h>
+#include "ping_common.h"
+#include "ping6.h"
+
+static char short_options[] = "VLhc:dfi:l:np:qRrs:t:v";
+static struct option long_options[] =
+{
+ /* Help options */
+ {"version", no_argument, NULL, 'V'},
+ {"license", no_argument, NULL, 'L'},
+ {"help", no_argument, NULL, 'h'},
+ /* Common options */
+ {"count", required_argument, NULL, 'c'},
+ {"debug", no_argument, NULL, 'd'},
+ {"ignore-routing", no_argument, NULL, 'r'},
+ {"size", required_argument, NULL, 's'},
+ {"interval",required_argument, NULL, 'i'},
+ {"numeric", no_argument, NULL, 'n'},
+ /* echo-specific options */
+ {"flood", no_argument, NULL, 'f'},
+ {"preload", required_argument, NULL, 'l'},
+ {"pattern", required_argument, NULL, 'p'},
+ {"quiet", no_argument, NULL, 'q'},
+ {NULL, no_argument, NULL, 0}
+};
+
+static PING *ping;
+unsigned char *data_buffer;
+size_t data_length = PING_DATALEN;
+static unsigned int options;
+static unsigned long preload = 0;
+
+static int ping_echo (int argc, char **argv);
+
+static void show_usage (void);
+static int send_echo (PING *ping);
+
+int
+main (int argc, char **argv)
+{
+ int c;
+ char *p;
+ int one = 1;
+ u_char pattern[16];
+ int pattern_len = 16;
+ u_char *patptr = NULL;
+ int is_root = getuid () == 0;
+
+ if ((ping = ping_init (0, getpid ())) == NULL)
+ {
+ fprintf (stderr, "can't init ping: %s\n", strerror (errno));
+ exit (1);
+ }
+ setsockopt (ping->ping_fd, SOL_SOCKET, SO_BROADCAST, (char *)&one, sizeof
(one));
+
+ /* Reset root privileges */
+ setuid (getuid ());
+
+ /* Parse command line */
+ while ((c = getopt_long (argc, argv, short_options, long_options, NULL))
+ != EOF)
+ {
+ switch (c)
+ {
+ case 'V':
+ printf ("ping - %s %s\n", PACKAGE_NAME, PACKAGE_VERSION);
+ printf ("Copyright (C) 2004 Free Software Foundation, Inc.\n");
+ printf ("%s comes with ABSOLUTELY NO WARRANTY.\n", PACKAGE_NAME);
+ printf ("You may redistribute copies of %s\n", PACKAGE_NAME);
+ printf ("under the terms of the GNU General Public License.\n");
+ printf ("For more information about these matters, ");
+ printf ("see the files named COPYING.\n");
+ exit (0);
+ break;
+
+ case 'L':
+ show_license ();
+ exit (0);
+
+ case 'h':
+ show_usage ();
+ exit (0);
+ break;
+
+ case 'c':
+ ping->ping_count = ping_cvt_number (optarg, 0, 0);
+ break;
+
+ case 'd':
+ setsockopt (ping->ping_fd, SOL_SOCKET, SO_DEBUG, &one, sizeof (one));
+ break;
+
+ case 'r':
+ setsockopt (ping->ping_fd, SOL_SOCKET, SO_DONTROUTE, &one, sizeof
(one));
+ break;
+
+ case 'i':
+ options |= OPT_INTERVAL;
+ ping->ping_interval = ping_cvt_number (optarg, 0, 0);
+ break;
+
+ case 'p':
+ decode_pattern (optarg, &pattern_len, pattern);
+ patptr = pattern;
+ break;
+
+ case 's':
+ data_length = ping_cvt_number (optarg, PING_MAX_DATALEN, 1);
+ break;
+
+ case 'n':
+ options |= OPT_NUMERIC;
+ break;
+
+ case 'q':
+ options |= OPT_QUIET;
+ break;
+
+ case 'l':
+ if (!is_root)
+ {
+ fprintf (stderr, "ping: option not allowed: --preload\n");
+ exit (1);
+ }
+ preload = strtoul (optarg, &p, 0);
+ if (*p || preload > INT_MAX)
+ {
+ fprintf (stderr, "ping: invalid preload value (%s)\n", optarg);
+ exit (1);
+ }
+ break;
+
+ case 'f':
+ if (!is_root)
+ {
+ fprintf (stderr, "ping: option not allowed: --flood\n");
+ exit (1);
+ }
+ options |= OPT_FLOOD;
+ setbuf (stdout, (char *)NULL);
+ break;
+
+ default:
+ fprintf (stderr, "%c: not implemented\n", c);
+ exit (1);
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+ if (argc == 0)
+ {
+ show_usage ();
+ exit (0);
+ }
+
+ init_data_buffer (patptr, pattern_len);
+
+ return ping_echo (argc, argv);
+}
+
+static char *
+ipaddr2str (struct sockaddr_in6 *from)
+{
+ int err;
+ size_t len;
+ char *buf, ipstr[256], hoststr[256];
+
+ err = getnameinfo ((struct sockaddr *) from, sizeof (*from), ipstr,
+ sizeof (ipstr), NULL, 0, NI_NUMERICHOST);
+ if (err)
+ {
+ const char *errmsg;
+
+ if (err == EAI_SYSTEM)
+ errmsg = strerror (errno);
+ else
+ errmsg = gai_strerror (err);
+
+ fprintf (stderr, "ping: getnameinfo: %s\n", errmsg);
+ return xstrdup ("unknown");
+ }
+
+ if (options & OPT_NUMERIC)
+ return xstrdup (ipstr);
+
+ err = getnameinfo ((struct sockaddr *) from, sizeof (*from), hoststr,
+ sizeof (hoststr), NULL, 0, NI_NAMEREQD);
+ if (err)
+ return xstrdup (ipstr);
+
+ len = strlen (ipstr) + strlen (hoststr) + 4; /* Pair of parentheses, a space
+ and a NUL. */
+ buf = xmalloc (len);
+ sprintf (buf, "%s (%s)", hoststr, ipstr);
+
+ return buf;
+}
+
+static volatile int stop = 0;
+
+static RETSIGTYPE
+sig_int (int signal)
+{
+ stop = 1;
+}
+
+static int
+ping_run (PING *ping, int (*finish)())
+{
+ fd_set fdset;
+ int fdmax;
+ struct timeval timeout;
+ struct timeval last, intvl, now;
+ struct timeval *t = NULL;
+ int finishing = 0;
+ int nresp = 0;
+
+ signal (SIGINT, sig_int);
+
+ fdmax = ping->ping_fd+1;
+
+ while (preload--)
+ send_echo (ping);
+
+ if (options & OPT_FLOOD)
+ {
+ intvl.tv_sec = 0;
+ intvl.tv_usec = 10000;
+ }
+ else
+ {
+ intvl.tv_sec = ping->ping_interval;
+ intvl.tv_usec = 0;
+ }
+
+ gettimeofday (&last, NULL);
+ send_echo (ping);
+
+ while (!stop)
+ {
+ int n;
+
+ FD_ZERO (&fdset);
+ FD_SET (ping->ping_fd, &fdset);
+ gettimeofday (&now, NULL);
+ timeout.tv_sec = last.tv_sec + intvl.tv_sec - now.tv_sec;
+ timeout.tv_usec = last.tv_usec + intvl.tv_usec - now.tv_usec;
+
+ while (timeout.tv_usec < 0)
+ {
+ timeout.tv_usec += 1000000;
+ timeout.tv_sec--;
+ }
+ while (timeout.tv_usec >= 1000000)
+ {
+ timeout.tv_usec -= 1000000;
+ timeout.tv_sec++;
+ }
+
+ if (timeout.tv_sec < 0)
+ timeout.tv_sec = timeout.tv_usec = 0;
+
+ n = select (fdmax, &fdset, NULL, NULL, &timeout);
+ if (n < 0)
+ {
+ if (errno != EINTR)
+ perror ("select");
+ continue;
+ }
+ else if (n == 1)
+ {
+ if (ping_recv (ping) == 0)
+ nresp++;
+ if (t == 0)
+ {
+ gettimeofday (&now, NULL);
+ t = &now;
+ }
+ if (ping->ping_count && nresp >= ping->ping_count)
+ break;
+ }
+ else
+ {
+ if (!ping->ping_count || ping->ping_num_xmit < ping->ping_count)
+ {
+ send_echo (ping);
+ if (!(options & OPT_QUIET) && options & OPT_FLOOD)
+ {
+ putchar ('.');
+ }
+ }
+ else if (finishing)
+ break;
+ else
+ {
+ finishing = 1;
+
+ intvl.tv_sec = MAXWAIT;
+ }
+ gettimeofday (&last, NULL);
+ }
+ }
+ if (finish)
+ return (*finish)();
+ return 0;
+}
+
+static int
+send_echo (PING *ping)
+{
+ int off = 0;
+
+ if (PING_TIMING (data_length))
+ {
+ struct timeval tv;
+ gettimeofday (&tv, NULL);
+ ping_set_data (ping, &tv, 0, sizeof (tv));
+ off += sizeof (tv);
+ }
+ if (data_buffer)
+ ping_set_data (ping, data_buffer, off,
+ data_length > PING_HEADER_LEN ?
+ data_length - PING_HEADER_LEN : data_length);
+ return ping_xmit (ping);
+}
+
+static int
+ping_finish ()
+{
+ fflush (stdout);
+ printf ("--- %s ping statistics ---\n", ping->ping_hostname);
+ printf ("%ld packets transmitted, ", ping->ping_num_xmit);
+ printf ("%ld packets received, ", ping->ping_num_recv);
+ if (ping->ping_num_rept)
+ printf ("+%ld duplicates, ", ping->ping_num_rept);
+ if (ping->ping_num_xmit)
+ {
+ if (ping->ping_num_recv > ping->ping_num_xmit)
+ printf ("-- somebody's printing up packets!");
+ else
+ printf ("%d%% packet loss",
+ (int) (((ping->ping_num_xmit - ping->ping_num_recv) * 100) /
+ ping->ping_num_xmit));
+
+ }
+ printf ("\n");
+ return 0;
+}
+
+static int print_echo (int dup, int hops, struct ping_stat *stat,
+ struct sockaddr_in6 *dest, struct sockaddr_in6 *from,
+ struct icmp6_hdr *icmp6, int datalen);
+static void print_icmp_error (struct sockaddr_in6 *from,
+ struct icmp6_hdr *icmp6, int len);
+
+static int echo_finish (void);
+
+static int
+ping_echo (int argc, char **argv)
+{
+ int err;
+ char buffer[256];
+ struct ping_stat ping_stat;
+
+ if (options & OPT_FLOOD && options & OPT_INTERVAL)
+ {
+ fprintf (stderr,
+ "ping: -f and -i incompatible options.\n");
+ return 2;
+ }
+
+ memset (&ping_stat, 0, sizeof (ping_stat));
+ ping_stat.tmin = 999999999.0;
+
+ ping->ping_datalen = data_length;
+ ping->ping_closure = &ping_stat;
+
+ if (ping_set_dest (ping, *argv))
+ {
+ fprintf (stderr, "ping: unknown host\n");
+ exit (1);
+ }
+
+ err = getnameinfo ((struct sockaddr *) &ping->ping_dest,
+ sizeof (ping->ping_dest), buffer,
+ sizeof (buffer), NULL, 0, NI_NUMERICHOST);
+ if (err)
+ {
+ const char *errmsg;
+
+ if (err == EAI_SYSTEM)
+ errmsg = strerror (errno);
+ else
+ errmsg = gai_strerror (err);
+
+ fprintf (stderr, "ping: getnameinfo: %s\n", errmsg);
+
+ exit (1);
+ }
+
+ printf ("PING %s (%s): %d data bytes\n",
+ ping->ping_hostname, buffer, data_length);
+
+ return ping_run (ping, echo_finish);
+}
+
+static int
+print_echo (int dupflag, int hops, struct ping_stat *ping_stat,
+ struct sockaddr_in6 *dest, struct sockaddr_in6 *from,
+ struct icmp6_hdr *icmp6, int datalen)
+{
+ int err;
+ char buf[256];
+ struct timeval tv;
+ int timing = 0;
+ double triptime = 0.0;
+
+ gettimeofday (&tv, NULL);
+
+ /* Do timing */
+ if (PING_TIMING (datalen - sizeof (struct icmp6_hdr)))
+ {
+ struct timeval tv1, *tp;
+
+ timing++;
+ tp = (struct timeval *) icmp6 + 1;
+
+ /* Avoid unaligned data: */
+ memcpy (&tv1, tp, sizeof (tv1));
+ tvsub (&tv, &tv1);
+
+ triptime = ((double)tv.tv_sec) * 1000.0 +
+ ((double)tv.tv_usec) / 1000.0;
+ ping_stat->tsum += triptime;
+ ping_stat->tsumsq += triptime*triptime;
+ if (triptime < ping_stat->tmin)
+ ping_stat->tmin = triptime;
+ if (triptime > ping_stat->tmax)
+ ping_stat->tmax = triptime;
+ }
+
+ if (options & OPT_QUIET)
+ return 0;
+ if (options & OPT_FLOOD)
+ {
+ putchar ('\b');
+ return 0;
+ }
+
+ err = getnameinfo ((struct sockaddr *) from, sizeof (*from), buf,
+ sizeof (buf), NULL, 0, 0);
+ if (err)
+ {
+ const char *errmsg;
+
+ if (err == EAI_SYSTEM)
+ errmsg = strerror (errno);
+ else
+ errmsg = gai_strerror (err);
+
+ fprintf (stderr, "ping: getnameinfo: %s\n", errmsg);
+
+ strcpy (buf, "unknown");
+ }
+
+ printf ("%d bytes from %s: icmp_seq=%u", datalen, buf, htons
(icmp6->icmp6_seq));
+ if (hops >= 0)
+ printf (" ttl=%d", hops);
+ if (timing)
+ printf (" time=%.3f ms", triptime);
+ if (dupflag)
+ printf (" (DUP!)");
+
+ putchar ('\n');
+
+ return 0;
+}
+
+#define NITEMS(a) sizeof(a)/sizeof((a)[0])
+
+struct icmp_code_descr {
+ int code;
+ char *diag;
+};
+
+static struct icmp_code_descr icmp_dest_unreach_desc[] = {
+ { ICMP6_DST_UNREACH_NOROUTE, "No route to destination" },
+ { ICMP6_DST_UNREACH_ADMIN, "Destination administratively prohibited" },
+ { ICMP6_DST_UNREACH_BEYONDSCOPE, "Beyond scope of source address" },
+ { ICMP6_DST_UNREACH_ADDR, "Address unreachable" },
+ { ICMP6_DST_UNREACH_NOPORT, "Port unreachable" },
+};
+
+static void
+print_dst_unreach (struct icmp6_hdr *icmp6)
+{
+ struct icmp_code_descr *p;
+
+ printf ("Destination unreachable: ");
+ for (p = icmp_dest_unreach_desc;
+ p < icmp_dest_unreach_desc + NITEMS(icmp_dest_unreach_desc);
+ p++)
+ {
+ if (p->code == icmp6->icmp6_code)
+ {
+ puts (p->diag);
+ return;
+ }
+ }
+
+ printf ("Unknown code %d\n", icmp6->icmp6_code);
+}
+
+static void
+print_packet_too_big (struct icmp6_hdr *icmp6)
+{
+ printf ("Packet too big, mtu=%d\n", icmp6->icmp6_mtu);
+}
+
+static struct icmp_code_descr icmp_time_exceeded_desc[] = {
+ { ICMP6_TIME_EXCEED_TRANSIT, "Hop limit exceeded"},
+ { ICMP6_TIME_EXCEED_REASSEMBLY, "Fragment reassembly timeout"},
+};
+
+static void
+print_time_exceeded (struct icmp6_hdr *icmp6)
+{
+ struct icmp_code_descr *p;
+
+ printf ("Time exceeded: ");
+ for (p = icmp_time_exceeded_desc;
+ p < icmp_time_exceeded_desc + NITEMS(icmp_time_exceeded_desc);
+ p++)
+ {
+ if (p->code == icmp6->icmp6_code)
+ {
+ puts (p->diag);
+ return;
+ }
+ }
+
+ printf ("Unknown code %d\n", icmp6->icmp6_code);
+}
+
+static struct icmp_code_descr icmp_param_prob_desc[] = {
+ { ICMP6_PARAMPROB_HEADER, "Erroneous header field"},
+ { ICMP6_PARAMPROB_NEXTHEADER, "Unrecognized Next Header type"},
+ { ICMP6_PARAMPROB_OPTION, "Unrecognized IPv6 option"},
+};
+
+static void
+print_param_prob (struct icmp6_hdr *icmp6)
+{
+ struct icmp_code_descr *p;
+
+ printf ("Parameter problem: ");
+ for (p = icmp_param_prob_desc;
+ p < icmp_param_prob_desc + NITEMS(icmp_param_prob_desc);
+ p++)
+ {
+ if (p->code == icmp6->icmp6_code)
+ {
+ puts (p->diag);
+ return;
+ }
+ }
+
+ printf ("Unknown code %d\n", icmp6->icmp6_code);
+}
+
+static struct icmp_diag {
+ int type;
+ void (*func) (struct icmp6_hdr *);
+} icmp_diag[] = {
+ { ICMP6_DST_UNREACH, print_dst_unreach },
+ { ICMP6_PACKET_TOO_BIG, print_packet_too_big },
+ { ICMP6_TIME_EXCEEDED, print_time_exceeded },
+ { ICMP6_PARAM_PROB, print_param_prob },
+};
+
+static void
+print_icmp_error (struct sockaddr_in6 *from,
+ struct icmp6_hdr *icmp6, int len)
+{
+ char *s;
+ struct icmp_diag *p;
+
+ s = ipaddr2str (from);
+ printf ("%d bytes from %s: ", len, s);
+ free (s);
+
+ for (p = icmp_diag; p < icmp_diag + NITEMS(icmp_diag); p++)
+ {
+ if (p->type == icmp6->icmp6_type)
+ {
+ p->func (icmp6);
+ return;
+ }
+ }
+
+ /* This should never happen because of the ICMP6_FILTER set in
+ ping_init(). */
+ printf ("Unknown ICMP type: %d\n", icmp6->icmp6_type);
+}
+
+static int
+echo_finish ()
+{
+ ping_finish ();
+ if (ping->ping_num_recv && PING_TIMING (data_length))
+ {
+ struct ping_stat *ping_stat = (struct ping_stat*)ping->ping_closure;
+ double total = ping->ping_num_recv + ping->ping_num_rept;
+ double avg = ping_stat->tsum/total;
+ double vari = ping_stat->tsumsq / total - avg * avg;
+
+ printf ("round-trip min/avg/max/stddev = %.3f/%.3f/%.3f/%.3f ms\n",
+ ping_stat->tmin, avg, ping_stat->tmax, nsqrt (vari, 0.0005));
+ }
+ exit (ping->ping_num_recv == 0);
+}
+
+static void
+show_usage (void)
+{
+ printf ("\
+Usage: ping6 [OPTION]... [ADDRESS]...\n\
+\n\
+Informational options:\n\
+ -h, --help display this help and exit\n\
+ -L, --license display license and exit\n\
+ -V, --version output version information and exit\n\
+Options valid for all request types:\n\
+ -c, --count N stop after sending N packets\n\
+ -d, --debug set the SO_DEBUG option\n\
+ -i, --interval N wait N seconds between sending each packet\n\
+ -n, --numeric do not resolve host addresses\n\
+ -r, --ignore-routing send directly to a host on an attached network\n\
+Options valid for --echo requests:\n\
+* -f, --flood flood ping \n\
+* -l, --preload N send N packets as fast as possible before falling into\n\
+ normal mode of behavior\n\
+ -p, --pattern PAT fill ICMP packet with given pattern (hex)\n\
+ -q, --quiet quiet output\n\
+ -s, --size N set number of data octets to send\n\
+\n\
+Options marked with an * are available only to super-user\n\
+\n\
+report bugs to " PACKAGE_BUGREPORT ".\n\
+");
+}
+
+static PING *
+ping_init (int type, int ident)
+{
+ int fd, err;
+ const int on = 1;
+ PING *p;
+ struct icmp6_filter filter;
+
+ /* Initialize raw ICMPv6 socket */
+ fd = socket (PF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
+ if (fd < 0)
+ {
+ if (errno == EPERM)
+ {
+ fprintf (stderr, "ping: ping must run as root\n");
+ }
+ return NULL;
+ }
+
+ /* Tell which ICMPs we are interested in. */
+ ICMP6_FILTER_SETBLOCKALL (&filter);
+ ICMP6_FILTER_SETPASS (ICMP6_ECHO_REPLY, &filter);
+ ICMP6_FILTER_SETPASS (ICMP6_DST_UNREACH, &filter);
+ ICMP6_FILTER_SETPASS (ICMP6_PACKET_TOO_BIG, &filter);
+ ICMP6_FILTER_SETPASS (ICMP6_TIME_EXCEEDED, &filter);
+ ICMP6_FILTER_SETPASS (ICMP6_PARAM_PROB, &filter);
+
+ err = setsockopt (fd, IPPROTO_ICMPV6, ICMP6_FILTER, &filter, sizeof
(filter));
+ if (err)
+ {
+ close (fd);
+ return NULL;
+ }
+
+ err = setsockopt (fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &on, sizeof (on));
+ if (err)
+ {
+ close (fd);
+ return NULL;
+ }
+
+ /* Allocate PING structure and initialize it to default values */
+ p = malloc (sizeof (*p));
+ if (!p)
+ {
+ close (fd);
+ return NULL;
+ }
+
+ memset (p, 0, sizeof (*p));
+
+ p->ping_fd = fd;
+ p->ping_count = 0;
+ p->ping_interval = PING_INTERVAL;
+ p->ping_datalen = sizeof (struct icmp6_hdr);
+ /* Make sure we use only 16 bits in this field, id for icmp is a u_short. */
+ p->ping_ident = ident & 0xFFFF;
+ p->ping_cktab_size = PING_CKTABSIZE;
+ return p;
+}
+
+static int
+_ping_setbuf (PING *p)
+{
+ if (!p->ping_buffer)
+ {
+ p->ping_buffer = malloc (_PING_BUFLEN (p));
+ if (!p->ping_buffer)
+ return -1;
+ }
+ if (!p->ping_cktab)
+ {
+ p->ping_cktab = malloc (p->ping_cktab_size);
+ if (!p->ping_cktab)
+ return -1;
+ memset (p->ping_cktab, 0, p->ping_cktab_size);
+ }
+ return 0;
+}
+
+static int
+ping_set_data (PING *p, void *data, size_t off, size_t len)
+{
+ if (_ping_setbuf (p))
+ return -1;
+ if (p->ping_datalen < off + len)
+ return -1;
+ memcpy (p->ping_buffer + sizeof (struct icmp6_hdr) + off, data, len);
+
+ return 0;
+}
+
+static int
+ping_xmit (PING *p)
+{
+ int i, buflen;
+ struct icmp6_hdr *icmp6;
+
+ if (_ping_setbuf (p))
+ return -1;
+
+ buflen = p->ping_datalen + sizeof (struct icmp6_hdr);
+
+ /* Mark sequence number as sent */
+ _PING_CLR (p, p->ping_num_xmit % p->ping_cktab_size);
+
+ icmp6 = (struct icmp6_hdr *) p->ping_buffer;
+ icmp6->icmp6_type = ICMP6_ECHO_REQUEST;
+ icmp6->icmp6_code = 0;
+ /* The checksum will be calculated by the TCP/IP stack. */
+ icmp6->icmp6_cksum = 0;
+ icmp6->icmp6_id = htons (p->ping_ident);
+ icmp6->icmp6_seq = htons (p->ping_num_xmit);
+
+ i = sendto (p->ping_fd, (char *)p->ping_buffer, buflen, 0,
+ (struct sockaddr*) &p->ping_dest,
+ sizeof (p->ping_dest));
+ if (i < 0)
+ perror ("ping: sendto");
+ else
+ {
+ p->ping_num_xmit++;
+ if (i != buflen)
+ printf ("ping: wrote %s %d chars, ret=%d\n",
+ p->ping_hostname, buflen, i);
+ }
+
+ return 0;
+}
+
+static int
+my_echo_reply (PING *p, struct icmp6_hdr *icmp6)
+{
+ struct ip6_hdr *orig_ip =
+ (struct ip6_hdr *) (icmp6 + 1);
+ struct icmp6_hdr *orig_icmp =
+ (struct icmp6_hdr *)(orig_ip + 1);
+
+ return IN6_ARE_ADDR_EQUAL (&orig_ip->ip6_dst, &ping->ping_dest.sin6_addr)
+ && orig_ip->ip6_nxt == IPPROTO_ICMPV6
+ && orig_icmp->icmp6_type == ICMP6_ECHO_REQUEST
+ && orig_icmp->icmp6_id == htons (p->ping_ident);
+}
+
+static int
+ping_recv (PING *p)
+{
+ int dupflag, n;
+ int hops = -1;
+ struct msghdr msg;
+ struct iovec iov;
+ struct icmp6_hdr *icmp6;
+ struct cmsghdr *cmsg;
+ char cmsg_data[1024];
+
+ iov.iov_base = p->ping_buffer;
+ iov.iov_len = _PING_BUFLEN (p);
+ msg.msg_name = &p->ping_from;
+ msg.msg_namelen = sizeof (p->ping_from);
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = cmsg_data;
+ msg.msg_controllen = sizeof (cmsg_data);
+ msg.msg_flags = 0;
+
+ n = recvmsg (p->ping_fd, &msg, 0);
+ if (n < 0)
+ return -1;
+
+ for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR (&msg, cmsg))
+ {
+ if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_HOPLIMIT)
+ {
+ hops = *(int *)CMSG_DATA(cmsg);
+ break;
+ }
+ }
+
+ icmp6 = (struct icmp6_hdr *) p->ping_buffer;
+ if (icmp6->icmp6_type == ICMP6_ECHO_REPLY)
+ {
+ /* We got an echo reply. */
+ if (ntohs (icmp6->icmp6_id) != p->ping_ident)
+ return -1; /* It's not a response to us. */
+
+ if (_PING_TST (p, ntohs (icmp6->icmp6_seq) % p->ping_cktab_size))
+ {
+ /* We already got the reply for this echo request. */
+ p->ping_num_rept++;
+ dupflag = 1;
+ }
+ else
+ {
+ _PING_SET (p, ntohs (icmp6->icmp6_seq) % p->ping_cktab_size);
+ p->ping_num_recv++;
+ dupflag = 0;
+ }
+
+ print_echo (dupflag, hops, p->ping_closure, &p->ping_dest,
+ &p->ping_from, icmp6, n);
+
+ }
+ else
+ {
+ /* We got an error reply. */
+ if (!my_echo_reply (p, icmp6))
+ return -1; /* It's not for us. */
+
+ print_icmp_error (&p->ping_from, icmp6, n);
+ }
+
+ return 0;
+}
+
+static int
+ping_set_dest (PING *ping, char *host)
+{
+ int err;
+ struct addrinfo *result, hints;
+
+ memset (&hints, 0, sizeof (hints));
+
+ hints.ai_family = AF_INET6;
+
+ err = getaddrinfo (host, NULL, &hints, &result);
+ if (err)
+ return 1;
+
+ memcpy (&ping->ping_dest, result->ai_addr, result->ai_addrlen);
+
+ freeaddrinfo (result);
+
+ ping->ping_hostname = strdup (host);
+ if (!ping->ping_hostname)
+ return 1;
+
+ return 0;
+}
Index: ping/ping6.h
===================================================================
RCS file: ping/ping6.h
diff -N ping/ping6.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ping/ping6.h 6 Jul 2004 22:06:43 -0000
@@ -0,0 +1,99 @@
+/* Copyright (C) 1998, 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. */
+
+#include <netinet/in.h>
+#include <netinet/icmp6.h>
+
+typedef struct ping_data PING;
+typedef int (*ping_efp) (int code, void *closure, struct sockaddr_in6 *dest,
+ struct sockaddr_in6 *from, struct icmp6_hdr *icmp,
+ int datalen);
+
+
+struct ping_data
+{
+ int ping_fd; /* Raw socket descriptor */
+ int ping_type; /* Type of packets to send */
+ int ping_count; /* Number of packets to send */
+ int ping_interval; /* Number of seconds to wait between sending pkts */
+ struct sockaddr_in6 ping_dest; /* whom to ping */
+ char *ping_hostname; /* Printable hostname */
+ size_t ping_datalen; /* Length of data */
+ int ping_ident; /* Our identifier */
+
+ ping_efp ping_event; /* User-defined handler */
+ void *ping_closure; /* User-defined data */
+
+ /* Runtime info */
+ int ping_cktab_size;
+ char *ping_cktab;
+
+ u_char *ping_buffer; /* I/O buffer */
+ struct sockaddr_in6 ping_from;
+ long ping_num_xmit; /* Number of packets transmitted */
+ long ping_num_recv; /* Number of packets received */
+ long ping_num_rept; /* Number of duplicates received */
+};
+
+struct ping_stat
+{
+ double tmin; /* minimum round trip time */
+ double tmax; /* maximum round trip time */
+ double tsum; /* sum of all times, for doing average */
+ double tsumsq; /* sum of all times squared, for std. dev. */
+};
+
+#define PEV_RESPONSE 0
+#define PEV_DUPLICATE 1
+#define PEV_NOECHO 2
+
+#define PING_INTERVAL 1
+#define PING_CKTABSIZE 128
+
+#define MAXWAIT 10 /* max seconds to wait for
response */
+
+#define OPT_FLOOD 0x001
+#define OPT_INTERVAL 0x002
+#define OPT_NUMERIC 0x004
+#define OPT_QUIET 0x008
+#define OPT_RROUTE 0x010
+#define OPT_VERBOSE 0x020
+
+#define PING_TIMING(s) (s >= PING_HEADER_LEN)
+#define PING_HEADER_LEN sizeof (struct timeval)
+#define PING_DATALEN (64 - PING_HEADER_LEN) /* default data length
*/
+#define PING_MAX_DATALEN (65535 - sizeof (struct icmp6_hdr))
+
+#define _PING_BUFLEN(p) ((p)->ping_datalen + sizeof (struct icmp6_hdr))
+
+#define _C_BIT(p,bit) (p)->ping_cktab[(bit)>>3] /* byte in ck array */
+#define _C_MASK(bit) (1 << ((bit) & 0x07))
+
+#define _PING_SET(p,bit) (_C_BIT (p,bit) |= _C_MASK (bit))
+#define _PING_CLR(p,bit) (_C_BIT (p,bit) &= (~_C_MASK (bit)))
+#define _PING_TST(p,bit) (_C_BIT (p,bit) & _C_MASK (bit))
+
+static PING *ping_init (int type, int ident);
+static int ping_set_dest (PING *ping, char *host);
+static int ping_set_data (PING *p, void *data, size_t off, size_t len);
+static int ping_recv (PING *p);
+static int ping_xmit (PING *p);
+
+static int ping_run (PING *ping, int (*finish)());
+static int ping_finish (void);
Index: ping/ping_common.c
===================================================================
RCS file: ping/ping_common.c
diff -N ping/ping_common.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ping/ping_common.c 6 Jul 2004 22:06:43 -0000
@@ -0,0 +1,164 @@
+/* Copyright (C) 1998, 2001, 2002, 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. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+
+extern unsigned char *data_buffer;
+extern size_t data_length;
+
+unsigned long int
+ping_cvt_number (const char *optarg, unsigned long int maxval, int allow_zero)
+{
+ char *p;
+ unsigned long int n;
+
+ n = strtoul (optarg, &p, 0);
+ if (*p)
+ {
+ fprintf (stderr, "Invalid value (`%s' near `%s')\n", optarg, p);
+ exit (1);
+ }
+ if (n == 0 && !allow_zero)
+ {
+ fprintf (stderr, "Option value too small: %s\n", optarg);
+ exit (1);
+ }
+ if (maxval && n > maxval)
+ {
+ fprintf (stderr, "Option value too big: %s\n", optarg);
+ exit (1);
+ }
+ return n;
+}
+
+void
+init_data_buffer (unsigned char *pat, int len)
+{
+ int i = 0;
+ u_char *p;
+
+ if (data_length == 0)
+ return;
+ data_buffer = malloc (data_length);
+ if (!data_buffer)
+ {
+ fprintf (stderr, "ping: out of memory\n");
+ exit (1);
+ }
+ if (pat)
+ {
+ for (p = data_buffer; p < data_buffer + data_length; p++)
+ {
+ *p = pat[i];
+ if (i++ >= len)
+ i = 0;
+ }
+ }
+ else
+ {
+ for (i = 0; i < data_length; i++)
+ data_buffer[i] = i;
+ }
+}
+
+
+void
+decode_pattern (const char *text, int *pattern_len, unsigned char
*pattern_data)
+{
+ int i, c, off;
+
+ for (i = 0; *text && i < *pattern_len; i++)
+ {
+ if (sscanf (text, "%2x%n", &c, &off) != 1)
+ {
+ fprintf (stderr, "ping: error in pattern near %s\n", text);
+ exit (1);
+ }
+ text += off;
+ }
+ *pattern_len = i;
+}
+
+
+/*
+ * tvsub --
+ * Subtract 2 timeval structs: out = out - in. Out is assumed to
+ * be >= in.
+ */
+void
+tvsub (struct timeval *out, struct timeval *in)
+{
+ if ((out->tv_usec -= in->tv_usec) < 0)
+ {
+ --out->tv_sec;
+ out->tv_usec += 1000000;
+ }
+ out->tv_sec -= in->tv_sec;
+}
+
+double
+nabs (double a)
+{
+ return (a < 0) ? -a : a;
+}
+
+double
+nsqrt (double a, double prec)
+{
+ double x0, x1;
+
+ if (a < 0)
+ return 0;
+ if (a < prec)
+ return 0;
+ x1 = a/2;
+ do
+ {
+ x0 = x1;
+ x1 = (x0 + a/x0) / 2;
+ }
+ while (nabs (x1 - x0) > prec);
+
+ return x1;
+}
+
+void
+show_license (void)
+{
+ static char license_text[] =
+" This program is free software; you can redistribute it and/or modify\n"
+" it under the terms of the GNU General Public License as published by\n"
+" the Free Software Foundation; either version 2, or (at your option)\n"
+" any later version.\n"
+"\n"
+" This program is distributed in the hope that it will be useful,\n"
+" but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
+" GNU General Public License for more details.\n"
+"\n"
+" You should have received a copy of the GNU General Public License\n"
+" along with this program; if not, write to the Free Software\n"
+" Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n";
+ printf ("%s", license_text);
+}
Index: ping/ping_common.h
===================================================================
RCS file: ping/ping_common.h
diff -N ping/ping_common.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ping/ping_common.h 6 Jul 2004 22:06:43 -0000
@@ -0,0 +1,34 @@
+/* Copyright (C) 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. */
+
+
+void tvsub (struct timeval *out, struct timeval *in);
+double nabs (double a);
+double nsqrt (double a, double prec);
+
+void show_license (void);
+
+unsigned long int ping_cvt_number (const char *optarg,
+ unsigned long int maxval, int allow_zero);
+
+void init_data_buffer (unsigned char *pat, int len);
+
+void decode_pattern (const char *text, int *pattern_len,
+ unsigned char *pattern_data);
+
Index: ping/ping_echo.c
===================================================================
RCS file: /cvsroot/inetutils/inetutils/ping/ping_echo.c,v
retrieving revision 1.10
diff -u -p -r1.10 ping_echo.c
--- ping/ping_echo.c 10 Nov 2003 14:29:40 -0000 1.10
+++ ping/ping_echo.c 6 Jul 2004 22:06:43 -0000
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+/* Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc.
This file is part of GNU Inetutils.
@@ -45,18 +45,17 @@
#include <errno.h>
#include <limits.h>
-#include "getopt.h"
#include <icmp.h>
#include <ping.h>
-#include <ping_impl.h>
+#include "ping_common.h"
+#include "ping_impl.h"
#define NROUTES 9 /* number of record route slots
*/
#ifndef MAX_IPOPTLEN
# define MAX_IPOPTLEN 40
#endif
-extern char *xstrdup (const char *);
-extern char *xmalloc (size_t);
+#include <xalloc.h>
static int handler (int code, void *closure,
struct sockaddr_in *dest, struct sockaddr_in *from,
@@ -70,8 +69,6 @@ void print_icmp_header (struct sockaddr_
struct ip *ip, icmphdr_t *icmp, int len);
static void print_ip_opt (struct ip *ip, int hlen);
-static void tvsub (struct timeval *out, struct timeval *in);
-
int
ping_echo (int argc, char **argv)
{
@@ -526,48 +523,6 @@ print_ip_opt (struct ip *ip, int hlen)
}
}
-/*
- * tvsub --
- * Subtract 2 timeval structs: out = out - in. Out is assumed to
- * be >= in.
- */
-static void
-tvsub (struct timeval *out, struct timeval *in)
-{
- if ((out->tv_usec -= in->tv_usec) < 0)
- {
- --out->tv_sec;
- out->tv_usec += 1000000;
- }
- out->tv_sec -= in->tv_sec;
-}
-
-double
-nabs (double a)
-{
- return (a < 0) ? -a : a;
-}
-
-double
-nsqrt (double a, double prec)
-{
- double x0, x1;
-
- if (a < 0)
- return 0;
- if (a < prec)
- return 0;
- x1 = a/2;
- do
- {
- x0 = x1;
- x1 = (x0 + a/x0) / 2;
- }
- while (nabs (x1 - x0) > prec);
-
- return x1;
-}
-
int
echo_finish ()
{
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 6 Jul 2004 22:06:43 -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 6 Jul 2004 22:06:43 -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>
@@ -44,6 +38,7 @@ static char sccsid[] = "@(#)main.c 8.3 (
#include <sys/types.h>
#include <getopt.h>
+#include <stdlib.h>
#include "ring.h"
#include "externs.h"
@@ -87,6 +82,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 +95,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 +151,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 +164,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 +183,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 +209,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 +236,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 +363,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 +372,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 6 Jul 2004 22:06:43 -0000
@@ -1,4 +1,4 @@
-/* Copyright (C) 1998,2001, 2002 Free Software Foundation, Inc.
+/* Copyright (C) 1998, 2001, 2002, 2004x 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 */
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [bug-inetutils] New IPv6 patch for inetutils,
Jeroen Dekkers <=