Files
inetutils/ping/libping.c
Sergey Poznyakoff 3d9c96104b Bugfixes.
* 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.
2008-12-27 20:36:00 +00:00

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;
}