+.*.swp
*.tar.gz
*~
.deps
UNRELEASED
+ * Allow running as non-root on Mac OS X by using non-privileged ICMP (#7)
+
* Fix loop issue after 65536 pings (reported by Peter Folk and GBert, #12)
* Minimum ping data size is now 0
* Removed setsockopt IPV6_CHECKSUM, which shouldn't be set and breaks
sbin_PROGRAMS = ${prog}
-fping_SOURCES = fping.c options.h seqmap.h seqmap.c
+fping_SOURCES = fping.c seqmap.c socket.c socket4.c
fping_DEPENDENCIES = ../config.h
-fping6_SOURCES = fping.c options.h seqmap.h seqmap.c
+fping6_SOURCES = fping.c seqmap.c socket.c socket6.c
fping6_DEPENDENCIES = ../config.h
fping6_CFLAGS = $(AM_CFLAGS) -DIPV6
{
#endif /* __cplusplus */
+#include "fping.h"
+#include "options.h"
+
/* if compiling for Windows, use this separate set
(too difficult to ifdef all the autoconf defines) */
#ifdef WIN32
#include <getopt.h>
#include <stdarg.h>
-#define __APPLE_USE_RFC_3542 1
-#include <netinet/in.h>
-
#include "config.h"
#include "seqmap.h"
#endif /* WIN32 */
-#include "options.h"
-
/*** externals ***/
extern char *optarg;
};
#define ICMP_UNREACH_MAXTYPE 15
-#ifndef IPV6
-#define FPING_SOCKADDR struct sockaddr_in
-#define FPING_ICMPHDR struct icmp
-#else
-#define FPING_SOCKADDR struct sockaddr_in6
-#define FPING_ICMPHDR struct icmp6_hdr
-#endif
/* entry used to keep track of each host we are pinging */
int main( int argc, char **argv )
{
int c, i, n;
-#ifdef IPV6
- int opton = 1;
-#endif
- struct protoent *proto;
char *buf;
uid_t uid;
- int tos = 0;
-
-#ifndef IPV6
- struct sockaddr_in sa;
-#else
- struct sockaddr_in6 sa;
-#endif
+ int tos = 0;
HOST_ENTRY *cursor;
- prog = argv[0];
-
- /* confirm that ICMP is available on this machine */
-#ifndef IPV6
- if( ( proto = getprotobyname( "icmp" ) ) == NULL )
-#else
- if( ( proto = getprotobyname( "ipv6-icmp" ) ) == NULL )
-#endif
- crash_and_burn( "icmp: unknown protocol" );
-
- /* create raw socket for ICMP calls (ping) */
-#ifndef IPV6
- s = socket( AF_INET, SOCK_RAW, proto->p_proto );
-#else
- s = socket( AF_INET6, SOCK_RAW, proto->p_proto );
-#endif
+ s = open_ping_socket();
- if( s < 0 )
- errno_crash_and_burn( "can't create raw socket (must run as root?)" );
-
-#ifdef IPV6
- /*
- * let the kernel pass extension headers of incoming packets,
- * for privileged socket options
- */
-#ifdef IPV6_RECVHOPOPTS
- if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVHOPOPTS, &opton,
- sizeof(opton)))
- err(1, "setsockopt(IPV6_RECVHOPOPTS)");
-#else /* old adv. API */
- if (setsockopt(s, IPPROTO_IPV6, IPV6_HOPOPTS, &opton,
- sizeof(opton)))
- err(1, "setsockopt(IPV6_HOPOPTS)");
-#endif
-#ifdef IPV6_RECVDSTOPTS
- if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVDSTOPTS, &opton,
- sizeof(opton)))
- err(1, "setsockopt(IPV6_RECVDSTOPTS)");
-#else /* old adv. API */
- if (setsockopt(s, IPPROTO_IPV6, IPV6_DSTOPTS, &opton,
- sizeof(opton)))
- err(1, "setsockopt(IPV6_DSTOPTS)");
-#endif
-#ifdef IPV6_RECVRTHDRDSTOPTS
- if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVRTHDRDSTOPTS, &opton,
- sizeof(opton)))
- err(1, "setsockopt(IPV6_RECVRTHDRDSTOPTS)");
-#endif
-#ifdef IPV6_RECVRTHDR
- if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVRTHDR, &opton,
- sizeof(opton)))
- err(1, "setsockopt(IPV6_RECVRTHDR)");
-#else /* old adv. API */
- if (setsockopt(s, IPPROTO_IPV6, IPV6_RTHDR, &opton,
- sizeof(opton)))
- err(1, "setsockopt(IPV6_RTHDR)");
-#endif
-#ifndef USE_SIN6_SCOPE_ID
-#ifdef IPV6_RECVPKTINFO
- if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO, &opton,
- sizeof(opton)))
- err(1, "setsockopt(IPV6_RECVPKTINFO)");
-#else /* old adv. API */
- if (setsockopt(s, IPPROTO_IPV6, IPV6_PKTINFO, &opton,
- sizeof(opton)))
- err(1, "setsockopt(IPV6_PKTINFO)");
-#endif
-#endif /* USE_SIN6_SCOPE_ID */
-#ifdef IPV6_RECVHOPLIMIT
- if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &opton,
- sizeof(opton)))
- err(1, "setsockopt(IPV6_RECVHOPLIMIT)");
-#else /* old adv. API */
- if (setsockopt(s, IPPROTO_IPV6, IPV6_HOPLIMIT, &opton,
- sizeof(opton)))
- err(1, "setsockopt(IPV6_HOPLIMIT)");
-#endif
-#endif
-
- if( ( uid = getuid() ) )
- {
+ if(uid = getuid()) {
seteuid( getuid() );
+ }
- }/* IF */
-
+ prog = argv[0];
ident = getpid() & 0xFFFF;
-
verbose_flag = 1;
backoff_flag = 1;
opterr = 1;
if( !num_hosts )
exit( 2 );
- /* set the source address */
-
- if( src_addr_present )
- {
- memset( &sa, 0, sizeof( sa ) );
-#ifndef IPV6
- sa.sin_family = AF_INET;
- sa.sin_addr = src_addr;
-#else
- sa.sin6_family = AF_INET6;
- sa.sin6_addr = src_addr;
-#endif
- if ( bind( s, (struct sockaddr *)&sa, sizeof( sa ) ) < 0 )
- errno_crash_and_burn( "cannot bind source address" );
+ if(src_addr_present) {
+ socket_set_src_addr(s, src_addr);
}
/* allocate array to hold outstanding ping requests */
--- /dev/null
+#ifndef _FPING_H
+#define _FPING_H
+
+#define __APPLE_USE_RFC_3542 1
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#ifndef IPV6
+#define FPING_SOCKADDR struct sockaddr_in
+#define FPING_INADDR struct in_addr
+#define FPING_ICMPHDR struct icmp
+#else
+#define FPING_SOCKADDR struct sockaddr_in6
+#define FPING_INADDR struct in6_addr
+#define FPING_ICMPHDR struct icmp6_hdr
+#endif
+
+/* fping.c */
+void crash_and_burn( char *message );
+void errno_crash_and_burn( char *message );
+
+/* socket.c */
+int open_ping_socket();
+void socket_set_src_addr(int s, FPING_INADDR src_addr);
+
+#endif
--- /dev/null
+/*
+ * fping: fast-ping, file-ping, favorite-ping, funky-ping
+ *
+ * Ping a list of target hosts in a round robin fashion.
+ * A better ping overall.
+ *
+ * fping website: http://www.fping.org
+ *
+ * Current maintainer of fping: David Schweikert
+ * Please send suggestions and patches to: david@schweikert.ch
+ *
+ *
+ * Original author: Roland Schemers <schemers@stanford.edu>
+ * IPv6 Support: Jeroen Massar <jeroen@unfix.org / jeroen@ipng.nl>
+ * Improved main loop: David Schweikert <david@schweikert.ch>
+ * Debian Merge, TOS settings: Tobi Oetiker <tobi@oetiker.ch>
+ * Bugfixes, byte order & senseful seq.-numbers: Stephan Fuhrmann (stephan.fuhrmann AT 1und1.de)
+ *
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by Stanford University. The name of the University may not be used
+ * to endorse or promote products derived from this software without
+ * specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "fping.h"
+#include "config.h"
+
+int open_ping_socket_ipv4();
+int open_ping_socket_ipv6();
+void socket_set_src_addr_ipv4(int s, FPING_INADDR src_addr);
+void socket_set_src_addr_ipv6(int s, FPING_INADDR src_addr);
+
+int open_ping_socket()
+{
+#ifndef IPV6
+ return open_ping_socket_ipv4();
+#else
+ return open_ping_socket_ipv6();
+#endif
+}
+
+void socket_set_src_addr(int s, FPING_INADDR src_addr)
+{
+#ifndef IPV6
+ socket_set_src_addr_ipv4(s, src_addr);
+#else
+ socket_set_src_addr_ipv6(s, src_addr);
+#endif
+}
--- /dev/null
+/*
+ * fping: fast-ping, file-ping, favorite-ping, funky-ping
+ *
+ * Ping a list of target hosts in a round robin fashion.
+ * A better ping overall.
+ *
+ * fping website: http://www.fping.org
+ *
+ * Current maintainer of fping: David Schweikert
+ * Please send suggestions and patches to: david@schweikert.ch
+ *
+ *
+ * Original author: Roland Schemers <schemers@stanford.edu>
+ * IPv6 Support: Jeroen Massar <jeroen@unfix.org / jeroen@ipng.nl>
+ * Improved main loop: David Schweikert <david@schweikert.ch>
+ * Debian Merge, TOS settings: Tobi Oetiker <tobi@oetiker.ch>
+ * Bugfixes, byte order & senseful seq.-numbers: Stephan Fuhrmann (stephan.fuhrmann AT 1und1.de)
+ *
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by Stanford University. The name of the University may not be used
+ * to endorse or promote products derived from this software without
+ * specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "fping.h"
+#include "config.h"
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <string.h>
+
+int open_ping_socket_ipv4()
+{
+ struct protoent *proto;
+ int s;
+
+ /* confirm that ICMP is available on this machine */
+ if( ( proto = getprotobyname( "icmp" ) ) == NULL )
+ crash_and_burn( "icmp: unknown protocol" );
+
+ /* create raw socket for ICMP calls (ping) */
+ s = socket( AF_INET, SOCK_RAW, proto->p_proto );
+ if( s < 0 ) {
+ /* try non-privileged icmp (works on Mac OSX without privileges, for example) */
+ s = socket( AF_INET, SOCK_DGRAM, proto->p_proto );
+ if( s < 0 ) {
+ errno_crash_and_burn( "can't create socket (must run as root?)" );
+ }
+ }
+
+ return s;
+}
+
+void socket_set_src_addr_ipv4(int s, FPING_INADDR src_addr)
+{
+ struct sockaddr_in sa;
+ memset( &sa, 0, sizeof( sa ) );
+ sa.sin_family = AF_INET;
+ sa.sin_addr = src_addr;
+
+ if ( bind( s, (struct sockaddr *)&sa, sizeof( sa ) ) < 0 )
+ errno_crash_and_burn( "cannot bind source address" );
+}
--- /dev/null
+/*
+ * fping: fast-ping, file-ping, favorite-ping, funky-ping
+ *
+ * Ping a list of target hosts in a round robin fashion.
+ * A better ping overall.
+ *
+ * fping website: http://www.fping.org
+ *
+ * Current maintainer of fping: David Schweikert
+ * Please send suggestions and patches to: david@schweikert.ch
+ *
+ *
+ * Original author: Roland Schemers <schemers@stanford.edu>
+ * IPv6 Support: Jeroen Massar <jeroen@unfix.org / jeroen@ipng.nl>
+ * Improved main loop: David Schweikert <david@schweikert.ch>
+ * Debian Merge, TOS settings: Tobi Oetiker <tobi@oetiker.ch>
+ * Bugfixes, byte order & senseful seq.-numbers: Stephan Fuhrmann (stephan.fuhrmann AT 1und1.de)
+ *
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by Stanford University. The name of the University may not be used
+ * to endorse or promote products derived from this software without
+ * specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "fping.h"
+#include "config.h"
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <netinet/icmp6.h>
+
+int open_ping_socket_ipv6()
+{
+ struct protoent *proto;
+ int opton = 1;
+ int s;
+
+ /* confirm that ICMP is available on this machine */
+ if( ( proto = getprotobyname( "ipv6-icmp" ) ) == NULL )
+ crash_and_burn( "icmp: unknown protocol" );
+
+ /* create raw socket for ICMP calls (ping) */
+ s = socket( AF_INET6, SOCK_RAW, proto->p_proto );
+ if( s < 0 ) {
+ /* try non-privileged icmp (works on Mac OSX without privileges, for example) */
+ s = socket( AF_INET6, SOCK_DGRAM, proto->p_proto );
+ if( s < 0 ) {
+ errno_crash_and_burn( "can't create raw socket (must run as root?)" );
+ }
+ }
+
+ /*
+ * let the kernel pass extension headers of incoming packets,
+ * for privileged socket options
+ */
+#ifdef IPV6_RECVHOPOPTS
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVHOPOPTS, &opton,
+ sizeof(opton)))
+ err(1, "setsockopt(IPV6_RECVHOPOPTS)");
+#else /* old adv. API */
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_HOPOPTS, &opton,
+ sizeof(opton)))
+ err(1, "setsockopt(IPV6_HOPOPTS)");
+#endif
+#ifdef IPV6_RECVDSTOPTS
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVDSTOPTS, &opton,
+ sizeof(opton)))
+ err(1, "setsockopt(IPV6_RECVDSTOPTS)");
+#else /* old adv. API */
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_DSTOPTS, &opton,
+ sizeof(opton)))
+ err(1, "setsockopt(IPV6_DSTOPTS)");
+#endif
+#ifdef IPV6_RECVRTHDRDSTOPTS
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVRTHDRDSTOPTS, &opton,
+ sizeof(opton)))
+ err(1, "setsockopt(IPV6_RECVRTHDRDSTOPTS)");
+#endif
+#ifdef IPV6_RECVRTHDR
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVRTHDR, &opton,
+ sizeof(opton)))
+ err(1, "setsockopt(IPV6_RECVRTHDR)");
+#else /* old adv. API */
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_RTHDR, &opton,
+ sizeof(opton)))
+ err(1, "setsockopt(IPV6_RTHDR)");
+#endif
+#ifndef USE_SIN6_SCOPE_ID
+#ifdef IPV6_RECVPKTINFO
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO, &opton,
+ sizeof(opton)))
+ err(1, "setsockopt(IPV6_RECVPKTINFO)");
+#else /* old adv. API */
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_PKTINFO, &opton,
+ sizeof(opton)))
+ err(1, "setsockopt(IPV6_PKTINFO)");
+#endif
+#endif /* USE_SIN6_SCOPE_ID */
+#ifdef IPV6_RECVHOPLIMIT
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &opton,
+ sizeof(opton)))
+ err(1, "setsockopt(IPV6_RECVHOPLIMIT)");
+#else /* old adv. API */
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_HOPLIMIT, &opton,
+ sizeof(opton)))
+ err(1, "setsockopt(IPV6_HOPLIMIT)");
+#endif
+
+ return s;
+}
+
+void socket_set_src_addr_ipv6(int s, FPING_INADDR src_addr)
+{
+ struct sockaddr_in6 sa;
+ memset( &sa, 0, sizeof( sa ) );
+ sa.sin6_family = AF_INET6;
+ sa.sin6_addr = src_addr;
+
+ if ( bind( s, (struct sockaddr *)&sa, sizeof( sa ) ) < 0 )
+ errno_crash_and_burn( "cannot bind source address" );
+}