mirror of
https://git.savannah.gnu.org/git/inetutils.git
synced 2026-01-12 00:19:39 +08:00
* bootstrap.conf: Add dirfd, filemode, inttostr and progname. * configure.ac: Fix checks for IPv6 header files. * doc/Makefile.am (inetutils_TEXINFOS): Add traceroute.texi. * doc/ftp.texi: Fixes. * ftp/cmds.c: Add missing includes. * ftp/ftp.c: Remove extern program_name. * ftp/ftp_var.h: Include progname.h * ftp/main.c (main): Call set_program_name * ftp/ruserpass.c: Include error.h * ftpd/Makefile.am (LDADD): Link LIBLS before libgnu. * ftpd/extern.h: Include getopt.h * ftpd/ftpd.c, gwhois/whois.c, hostname/hostname.c, logger/logger.c, rcp/rcp.c, rexecd/rexecd.c, rlogin/rlogin.c, rsh/rsh.c, rshd/rshd.c, syslogd/syslogd.c, talk/talk.c, traceroute/traceroute.c: Include progname.h (main): Call set_program_name. * ftpd/popen.c: Remove useless extern. * ifconfig/ifconfig.h: Include progname.h. * ifconfig/options.c (parse_opt): Call set_program_name. * ifconfig/options.h (program_name): Remove extern. * inetd/inetd.c: Include progname.h (main): Call set_program_name. (EAI_ADDRFAMILY): Provide a fallback definition for FreeBSD. * libinetutils/argcv.c: Include ctype.h * libinetutils/libinetutils.h (utmp_logout, logwtmp_keep_open): New protos. * libls/bsdport.h: Remove * libls/bsdport.c: Remove * libls/Makefile.am (libls_a_SOURCES): Remove bsdport.c (noinst_HEADERS): Remove bsdport.h (INCLUDES): New var. * libls/fts.c: Remove bsdport.h * libls/ls.c: Remove bsdisms. * libls/print.c: Likewise. * libtelnet/auth.h (auth_debug_mode): Fix extern. * ping/libping.c (ping_recv): Fix call to ping_event.handler. * ping/ping.c, ping/ping6.c (main): Call set_program_name. * ping/ping_common.c (ping_set_data): Remove useless if. * ping/ping_common.h: Include error.h and progname.h * rcp/util.c: Include error.h * rlogind/rlogind.c: Include utmp.h * talk/ctl.c (print_addr): Remove unused function. * talk/ctl_transact.c: Include talk.h * talk/display.c: Fix order of function definitions. * talk/get_addrs.c: Include unistd.h * talk/get_names.c: Include unistd.h and netinet/in.h * talk/init_disp.c: Include unistd.h * talk/invite.c: Fix order of function definitions. * talk/io.c: Include unistd.h * talk/look_up.c: Include unistd.h. Fix order of function definitions. * talk/talk.h: Include progname.h. Add missing prototypes. * talk/talk_ctl.h (ctl_transact): New proto. * telnet/commands.c: Include sys/wait.h. Reorder function definitions. * telnet/externs.h, telnet/ring.h: Add missing prototypes. * telnet/telnet.c: Reorder function definitions. * telnet/utilities.c: Include sys/socket.h * telnetd/telnetd.h: Include sys/stat.h and ctype.h. Add missing prototypes. * traceroute/Makefile.am (INCLUDES): Add ../lib. (LDADD): Add ../libgnu.a * uucpd/uucpd.c: Reorder function definitions.
283 lines
6.4 KiB
C
283 lines
6.4 KiB
C
/* Copyright (C) 1998, 2001, 2005, 2007, 2008 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 3, 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., 51 Franklin Street,
|
|
Fifth Floor, Boston, MA 02110-1301 USA. */
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# include <config.h>
|
|
#endif
|
|
|
|
#include <sys/param.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/file.h>
|
|
#include <sys/time.h>
|
|
#include <signal.h>
|
|
|
|
/*#include <netinet/ip_icmp.h> -- deliberately not including this */
|
|
#include <arpa/inet.h>
|
|
#include <netdb.h>
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
|
|
#include "ping.h"
|
|
|
|
static size_t _ping_packetsize (PING * p);
|
|
|
|
size_t
|
|
_ping_packetsize (PING * p)
|
|
{
|
|
if (p->ping_type == ICMP_TIMESTAMP || p->ping_type == ICMP_TIMESTAMPREPLY)
|
|
return 20;
|
|
return 8 + p->ping_datalen;
|
|
}
|
|
|
|
PING *
|
|
ping_init (int type, int ident)
|
|
{
|
|
int fd;
|
|
struct protoent *proto;
|
|
PING *p;
|
|
|
|
/* Initialize raw ICMP socket */
|
|
proto = getprotobyname ("icmp");
|
|
if (!proto)
|
|
{
|
|
fprintf (stderr, "ping: unknown protocol icmp.\n");
|
|
return NULL;
|
|
}
|
|
|
|
fd = socket (AF_INET, SOCK_RAW, proto->p_proto);
|
|
if (fd < 0)
|
|
{
|
|
if (errno == EPERM)
|
|
fprintf (stderr, "ping: ping must run as root\n");
|
|
return NULL;
|
|
}
|
|
|
|
/* Allocate PING structure and initialize it to default values */
|
|
p = malloc (sizeof (*p));
|
|
if (!p)
|
|
{
|
|
close (fd);
|
|
return p;
|
|
}
|
|
|
|
memset (p, 0, sizeof (*p));
|
|
|
|
p->ping_fd = fd;
|
|
p->ping_type = type;
|
|
p->ping_count = 0;
|
|
p->ping_interval = PING_DEFAULT_INTERVAL;
|
|
p->ping_datalen = sizeof (icmphdr_t);
|
|
/* 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;
|
|
}
|
|
|
|
void
|
|
ping_reset (PING * p)
|
|
{
|
|
p->ping_num_xmit = 0;
|
|
p->ping_num_recv = 0;
|
|
p->ping_num_rept = 0;
|
|
}
|
|
|
|
void
|
|
ping_set_type (PING * p, int type)
|
|
{
|
|
p->ping_type = type;
|
|
}
|
|
|
|
int
|
|
ping_xmit (PING * p)
|
|
{
|
|
int i, buflen;
|
|
|
|
if (_ping_setbuf (p, USE_IPV6))
|
|
return -1;
|
|
|
|
buflen = _ping_packetsize (p);
|
|
|
|
/* Mark sequence number as sent */
|
|
_PING_CLR (p, p->ping_num_xmit % p->ping_cktab_size);
|
|
|
|
/* Encode ICMP header */
|
|
switch (p->ping_type)
|
|
{
|
|
case ICMP_ECHO:
|
|
icmp_echo_encode (p->ping_buffer, buflen, p->ping_ident,
|
|
p->ping_num_xmit);
|
|
break;
|
|
|
|
case ICMP_TIMESTAMP:
|
|
icmp_timestamp_encode (p->ping_buffer, buflen, p->ping_ident,
|
|
p->ping_num_xmit);
|
|
break;
|
|
|
|
case ICMP_ADDRESS:
|
|
icmp_address_encode (p->ping_buffer, buflen, p->ping_ident,
|
|
p->ping_num_xmit);
|
|
break;
|
|
|
|
default:
|
|
icmp_generic_encode (p->ping_buffer, buflen, p->ping_type,
|
|
p->ping_ident, p->ping_num_xmit);
|
|
break;
|
|
}
|
|
|
|
i = sendto (p->ping_fd, (char *) p->ping_buffer, buflen, 0,
|
|
(struct sockaddr *) &p->ping_dest.ping_sockaddr, sizeof (struct sockaddr_in));
|
|
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, icmphdr_t * icmp)
|
|
{
|
|
struct ip *orig_ip = &icmp->icmp_ip;
|
|
icmphdr_t *orig_icmp = (icmphdr_t *) (orig_ip + 1);
|
|
|
|
return (orig_ip->ip_dst.s_addr == p->ping_dest.ping_sockaddr.sin_addr.s_addr
|
|
&& orig_ip->ip_p == IPPROTO_ICMP
|
|
&& orig_icmp->icmp_type == ICMP_ECHO
|
|
&& orig_icmp->icmp_id == p->ping_ident);
|
|
}
|
|
|
|
int
|
|
ping_recv (PING * p)
|
|
{
|
|
int fromlen = sizeof (p->ping_from.ping_sockaddr);
|
|
int n, rc;
|
|
icmphdr_t *icmp;
|
|
struct ip *ip;
|
|
int dupflag;
|
|
|
|
n = recvfrom (p->ping_fd,
|
|
(char *) p->ping_buffer, _PING_BUFLEN (p, USE_IPV6), 0,
|
|
(struct sockaddr *) &p->ping_from.ping_sockaddr, &fromlen);
|
|
if (n < 0)
|
|
return -1;
|
|
|
|
rc = icmp_generic_decode (p->ping_buffer, n, &ip, &icmp);
|
|
if (rc < 0)
|
|
{
|
|
/*FIXME: conditional */
|
|
fprintf (stderr, "packet too short (%d bytes) from %s\n", n,
|
|
inet_ntoa (p->ping_from.ping_sockaddr.sin_addr));
|
|
return -1;
|
|
}
|
|
|
|
switch (icmp->icmp_type)
|
|
{
|
|
case ICMP_ECHOREPLY:
|
|
case ICMP_TIMESTAMPREPLY:
|
|
case ICMP_ADDRESSREPLY:
|
|
/* case ICMP_ROUTERADV: */
|
|
|
|
if (icmp->icmp_id != p->ping_ident)
|
|
return -1;
|
|
|
|
if (rc)
|
|
fprintf (stderr, "checksum mismatch from %s\n",
|
|
inet_ntoa (p->ping_from.ping_sockaddr.sin_addr));
|
|
|
|
p->ping_num_recv++;
|
|
if (_PING_TST (p, icmp->icmp_seq % p->ping_cktab_size))
|
|
{
|
|
p->ping_num_rept++;
|
|
p->ping_num_recv--;
|
|
dupflag = 1;
|
|
}
|
|
else
|
|
{
|
|
_PING_SET (p, icmp->icmp_seq % p->ping_cktab_size);
|
|
dupflag = 0;
|
|
}
|
|
|
|
if (p->ping_event.handler)
|
|
(*p->ping_event.handler) (dupflag ? PEV_DUPLICATE : PEV_RESPONSE,
|
|
p->ping_closure,
|
|
&p->ping_dest.ping_sockaddr,
|
|
&p->ping_from.ping_sockaddr, ip, icmp, n);
|
|
break;
|
|
|
|
case ICMP_ECHO:
|
|
case ICMP_TIMESTAMP:
|
|
case ICMP_ADDRESS:
|
|
return -1;
|
|
|
|
default:
|
|
if (!my_echo_reply (p, icmp))
|
|
return -1;
|
|
|
|
if (p->ping_event.handler)
|
|
(*p->ping_event.handler) (PEV_NOECHO,
|
|
p->ping_closure,
|
|
&p->ping_dest.ping_sockaddr,
|
|
&p->ping_from.ping_sockaddr, ip, icmp, n);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
ping_set_event_handler (PING * ping, ping_efp pf, void *closure)
|
|
{
|
|
ping->ping_event.handler = pf;
|
|
ping->ping_closure = closure;
|
|
}
|
|
|
|
void
|
|
ping_set_packetsize (PING * ping, size_t size)
|
|
{
|
|
ping->ping_datalen = size;
|
|
}
|
|
|
|
int
|
|
ping_set_dest (PING * ping, char *host)
|
|
{
|
|
struct sockaddr_in *s_in = &ping->ping_dest.ping_sockaddr;
|
|
s_in->sin_family = AF_INET;
|
|
if (inet_aton (host, &s_in->sin_addr))
|
|
ping->ping_hostname = strdup (host);
|
|
else
|
|
{
|
|
struct hostent *hp = gethostbyname (host);
|
|
if (!hp)
|
|
return 1;
|
|
|
|
s_in->sin_family = hp->h_addrtype;
|
|
if (hp->h_length > (int) sizeof (s_in->sin_addr))
|
|
hp->h_length = sizeof (s_in->sin_addr);
|
|
|
|
memcpy (&s_in->sin_addr, hp->h_addr, hp->h_length);
|
|
ping->ping_hostname = strdup (hp->h_name);
|
|
}
|
|
return 0;
|
|
}
|