summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Habets <thomas@habets.se>2011-10-31 23:57:00 +0000
committerThomas Habets <thomas@habets.se>2011-11-01 00:02:25 +0000
commit1e01eb02c67122c5113afc164c97772a6054456c (patch)
treeadb69b62798a0b0966d6adfd28496082eb5ad2d9
parent8e4a0717bcaa7c8d45e2065220736ac4053d3c99 (diff)
parent91e1da907d9024dd2be06151fc23f3542d896f05 (diff)
downloadarping-1e01eb02c67122c5113afc164c97772a6054456c.tar.gz
Merge from mainline
-rw-r--r--README13
-rw-r--r--config.h.in6
-rwxr-xr-xconfigure191
-rw-r--r--configure.ac27
-rw-r--r--doc/Makefile.am6
-rw-r--r--doc/Makefile.in7
-rw-r--r--doc/arping.8111
-rw-r--r--doc/arping.yodl22
-rw-r--r--src/arping.c109
9 files changed, 387 insertions, 105 deletions
diff --git a/README b/README
index 7b90a34..86d5ee9 100644
--- a/README
+++ b/README
@@ -191,13 +191,18 @@ A: Be my guest, but if care about security *at all* you will have to restrict
a network debugging tool, which generates low-level network packets that
ordinary users have absolutely no business generating.
- For example, I don't protect against an ALRM signal flood, which will result
- in a packet flood. (arping 2.x doesn't have this issue)
-
If you are honestly debugging the network then I don't see why you aren't
root already.
- If you think I'm wrong, tell me why.
+ That being said, on Linux you can add the CAP_NET_RAW capability to arping
+ limiting the damage if arping were to be compromised:
+ sudo setcap cap_net_raw+ep /usr/local/sbin/arping
+ This requires a libnet which does not explicitly check for uid 0. The
+ current version of libnet does check this, so unless you patch it it will
+ not help.
+
+ Patch:
+ http://github.com/ThomasHabets/libnet/commit/aaa383b5c816107082508b7646929a9479b81645
---
Q: What's this -A switch all about, I don't understand it.
diff --git a/config.h.in b/config.h.in
index d78f33f..dfa8ed7 100644
--- a/config.h.in
+++ b/config.h.in
@@ -3,6 +3,9 @@
/* Define to 1 if you have the <arpa/inet.h> header file. */
#undef HAVE_ARPA_INET_H
+/* Monotonic clock */
+#undef HAVE_CLOCK_MONOTONIC
+
/* Define to 1 if you have the `gettimeofday' function. */
#undef HAVE_GETTIMEOFDAY
@@ -81,6 +84,9 @@
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
+/* Define to 1 if you have the <time.h> header file. */
+#undef HAVE_TIME_H
+
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
diff --git a/configure b/configure
index 2dd4cbf..3436cfd 100755
--- a/configure
+++ b/configure
@@ -709,6 +709,8 @@ CPP
GREP
EGREP
LIBOBJS
+HAVE_CLOCK_MONOTONIC_TRUE
+HAVE_CLOCK_MONOTONIC_FALSE
LTLIBOBJS'
ac_subst_files=''
ac_precious_vars='build_alias
@@ -4015,6 +4017,89 @@ echo "$as_me: error: libpcap not found" >&2;}
{ (exit 1); exit 1; }; }
fi
+{ echo "$as_me:$LINENO: checking for library containing clock_gettime" >&5
+echo $ECHO_N "checking for library containing clock_gettime... $ECHO_C" >&6; }
+if test "${ac_cv_search_clock_gettime+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char clock_gettime ();
+int
+main ()
+{
+return clock_gettime ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' rt; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_search_clock_gettime=$ac_res
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext
+ if test "${ac_cv_search_clock_gettime+set}" = set; then
+ break
+fi
+done
+if test "${ac_cv_search_clock_gettime+set}" = set; then
+ :
+else
+ ac_cv_search_clock_gettime=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_search_clock_gettime" >&5
+echo "${ECHO_T}$ac_cv_search_clock_gettime" >&6; }
+ac_res=$ac_cv_search_clock_gettime
+if test "$ac_res" != no; then
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
# Checks for header files.
ac_ext=c
@@ -4664,11 +4749,13 @@ done
+
for ac_header in \
arpa/inet.h \
netinet/in.h \
stdlib.h \
sys/socket.h \
+time.h \
sys/time.h \
sys/types.h \
stdint.h \
@@ -5995,7 +6082,7 @@ case "$target_os" in
esac
;;
- *freebsd*|*openbsd*|*solaris*)
+ *freebsd*|*openbsd*|*solaris*|*darwin*)
case " $LIBOBJS " in
*" findif_bsd.$ac_objext "* ) ;;
*) LIBOBJS="$LIBOBJS findif_bsd.$ac_objext"
@@ -6012,6 +6099,91 @@ esac
;;
esac
+
+
+
+# check for CLOCK_MONOTONIC
+{ echo "$as_me:$LINENO: checking for CLOCK_MONOTONIC" >&5
+echo $ECHO_N "checking for CLOCK_MONOTONIC... $ECHO_C" >&6; }
+if test "${ac_cv_have_clock_monotonic+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ if test "$cross_compiling" = yes; then
+ { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#include <time.h>
+int main() {
+struct timespec ts;
+exit(!!clock_gettime(CLOCK_MONOTONIC, &ts));
+}
+
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_have_clock_monotonic="yes"
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ ac_cv_have_clock_monotonic="no"
+
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_have_clock_monotonic" >&5
+echo "${ECHO_T}$ac_cv_have_clock_monotonic" >&6; }
+ if test x$ac_cv_have_clock_monotonic = xyes; then
+ HAVE_CLOCK_MONOTONIC_TRUE=
+ HAVE_CLOCK_MONOTONIC_FALSE='#'
+else
+ HAVE_CLOCK_MONOTONIC_TRUE='#'
+ HAVE_CLOCK_MONOTONIC_FALSE=
+fi
+
+if test x$ac_cv_have_clock_monotonic = xyes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_CLOCK_MONOTONIC 1
+_ACEOF
+
+fi
+
ac_config_files="$ac_config_files Makefile"
ac_config_files="$ac_config_files src/Makefile"
@@ -6135,6 +6307,13 @@ echo "$as_me: error: conditional \"am__fastdepCC\" was never defined.
Usually this means the macro was only invoked conditionally." >&2;}
{ (exit 1); exit 1; }; }
fi
+if test -z "${HAVE_CLOCK_MONOTONIC_TRUE}" && test -z "${HAVE_CLOCK_MONOTONIC_FALSE}"; then
+ { { echo "$as_me:$LINENO: error: conditional \"HAVE_CLOCK_MONOTONIC\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"HAVE_CLOCK_MONOTONIC\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+ { (exit 1); exit 1; }; }
+fi
: ${CONFIG_STATUS=./config.status}
ac_clean_files_save=$ac_clean_files
@@ -6763,10 +6942,12 @@ CPP!$CPP$ac_delim
GREP!$GREP$ac_delim
EGREP!$EGREP$ac_delim
LIBOBJS!$LIBOBJS$ac_delim
+HAVE_CLOCK_MONOTONIC_TRUE!$HAVE_CLOCK_MONOTONIC_TRUE$ac_delim
+HAVE_CLOCK_MONOTONIC_FALSE!$HAVE_CLOCK_MONOTONIC_FALSE$ac_delim
LTLIBOBJS!$LTLIBOBJS$ac_delim
_ACEOF
- if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 95; then
+ if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then
break
elif $ac_last_try; then
{ { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
@@ -6785,7 +6966,7 @@ fi
cat >>$CONFIG_STATUS <<_ACEOF
cat >"\$tmp/subs-1.sed" <<\CEOF$ac_eof
-/@[a-zA-Z_][a-zA-Z_0-9]*@/!b end
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
_ACEOF
sed '
s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g
@@ -6798,8 +6979,6 @@ N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n
' >>$CONFIG_STATUS <conf$$subs.sed
rm -f conf$$subs.sed
cat >>$CONFIG_STATUS <<_ACEOF
-:end
-s/|#_!!_#|//g
CEOF$ac_eof
_ACEOF
@@ -7053,7 +7232,7 @@ s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
s&@INSTALL@&$ac_INSTALL&;t t
s&@MKDIR_P@&$ac_MKDIR_P&;t t
$ac_datarootdir_hack
-" $ac_file_inputs | sed -f "$tmp/subs-1.sed" >$tmp/out
+" $ac_file_inputs | sed -f "$tmp/subs-1.sed" | sed 's/|#_!!_#|//g' >$tmp/out
test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
{ ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } &&
diff --git a/configure.ac b/configure.ac
index 0f43c28..843c9fb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -23,6 +23,7 @@ AC_CHECK_LIB([net], [libnet_name_resolve],
[AC_MSG_ERROR([libnet 1.0.x found. Arping 2.x requires libnet 1.1.x])])
AC_CHECK_LIB([net], [libnet_init], ,[AC_MSG_ERROR([libnet 1.1.x not found])])
AC_CHECK_LIB([pcap], [pcap_open_live], ,[AC_MSG_ERROR([libpcap not found])])
+AC_SEARCH_LIBS([clock_gettime], [rt])
# Checks for header files.
AC_HEADER_STDC
@@ -31,6 +32,7 @@ arpa/inet.h \
netinet/in.h \
stdlib.h \
sys/socket.h \
+time.h \
sys/time.h \
sys/types.h \
stdint.h \
@@ -64,13 +66,36 @@ case "$target_os" in
*linux*)
AC_LIBOBJ([findif_linux])
;;
- *freebsd*|*openbsd*|*solaris*)
+ *freebsd*|*openbsd*|*solaris*|*darwin*)
AC_LIBOBJ([findif_bsd])
;;
*)
AC_LIBOBJ([findif_other])
;;
esac
+
+
+
+# check for CLOCK_MONOTONIC
+AC_CACHE_CHECK([for CLOCK_MONOTONIC],
+ ac_cv_have_clock_monotonic, [
+ AC_TRY_RUN(
+ [
+#include <time.h>
+int main() {
+struct timespec ts;
+exit(!!clock_gettime(CLOCK_MONOTONIC, &ts));
+}
+ ],
+ [ ac_cv_have_clock_monotonic="yes" ],
+ [ ac_cv_have_clock_monotonic="no" ]
+ )
+])
+AM_CONDITIONAL(HAVE_CLOCK_MONOTONIC, test x$ac_cv_have_clock_monotonic = xyes)
+if test x$ac_cv_have_clock_monotonic = xyes; then
+ AC_DEFINE([HAVE_CLOCK_MONOTONIC], [1], [Monotonic clock])
+fi
+
AC_CONFIG_FILES([Makefile])
AC_CONFIG_FILES([src/Makefile])
AC_CONFIG_FILES([doc/Makefile])
diff --git a/doc/Makefile.am b/doc/Makefile.am
index 725ba02..4b12519 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -2,6 +2,10 @@
#
include $(top_srcdir)/Makefile.am.common
+# Manpage is only run by maintainer, not by end user. That's why there
+# is no dependency on arping.yodl.
man_MANS = arping.8
arping.8:
- yodl2man -o arping.8 arping.yodl
+ yodl2man -o arping.8.tmp arping.yodl
+ perl -ne 's/(^|(?<=[^\\\w]))-/\\-/g;print' < arping.8.tmp > arping.8
+ rm -f arping.8.tmp
diff --git a/doc/Makefile.in b/doc/Makefile.in
index a1b6515..af444ce 100644
--- a/doc/Makefile.in
+++ b/doc/Makefile.in
@@ -153,6 +153,9 @@ DISTCLEANFILES = *~
# arping/doc/Makefile.am
#
+
+# Manpage is only run by maintainer, not by end user. That's why there
+# is no dependency on arping.yodl.
man_MANS = arping.8
all: all-am
@@ -366,7 +369,9 @@ uninstall-man: uninstall-man8
uninstall-am uninstall-man uninstall-man8
arping.8:
- yodl2man -o arping.8 arping.yodl
+ yodl2man -o arping.8.tmp arping.yodl
+ perl -ne 's/(^|(?<=[^\\\w]))-/\\-/g;print' < arping.8.tmp > arping.8
+ rm -f arping.8.tmp
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
diff --git a/doc/arping.8 b/doc/arping.8
index f73e6d0..c42ce38 100644
--- a/doc/arping.8
+++ b/doc/arping.8
@@ -5,9 +5,9 @@
arping \- sends arp and/or ip pings to a given host
.PP
.SH "SYNOPSIS"
-\fBarping\fP [-abdDeFhpqrRd0uv] [-S \fIhost/ip\fP] [-T \fIhost/ip\fP] [-s \fIMAC\fP] [-t \fIMAC\fP] [-c \fIcount\fP] [-i \fIinterface\fP] [ -w \fIus\fP ] <\fIhost\fP | -B>
+\fBarping\fP [\-abdDeFhpqrRd0uv] [\-S \fIhost/ip\fP] [\-T \fIhost/ip\fP] [\-s \fIMAC\fP] [\-t \fIMAC\fP] [\-c \fIcount\fP] [\-i \fIinterface\fP] [ \-w \fIus\fP ] <\fIhost\fP | \-B>
.PP
-\fBarping\fP --help
+\fBarping\fP \-\-help
.PP
.SH "DESCRIPTION"
The \fIarping\fP utility sends \fBARP\fP and/or \fBICMP\fP requests to the specified \fIhost\fP and displays the replies\&. The \fIhost\fP may be specified by its \fBhostname\fP, its \fBIP\fP address, or its \fBMAC\fP address\&.
@@ -25,9 +25,9 @@ scheduler can\&'t keep up to get exact enough timing\&.
On an idle system the roundtrip times will be pretty much accurate, but
with more load the timing gets less exact\&.
.PP
-To get more exact timing on a non-idle system, re-nice arping to -15 or so\&.
+To get more exact timing on a non-idle system, re-nice arping to \-15 or so\&.
.PP
-# nice -n -15 arping foobar
+# nice \-n \-15 arping foobar
.PP
This is not just an issue with arping, it is with normal ping also
(at least it is on my system)\&. But it doesn\&'t show up as much with ping
@@ -37,98 +37,101 @@ received and are therefore replied to faster\&.
.SH "OPTIONS"
.PP
-.IP "--help"
+.IP "\-\-help"
Show extended help\&. Not quite as extensive as this manpage,
-but more than -h\&.
-.IP "-0"
+but more than \-h\&.
+.IP "\-0"
Use this option to ping with source IP address 0\&.0\&.0\&.0\&. Use this
when you haven\&'t configured your interface yet\&.
Note that this may get the MAC-ping unanswered\&.
-This is an alias for -S 0\&.0\&.0\&.0\&.
-.IP "-a"
+This is an alias for \-S 0\&.0\&.0\&.0\&.
+.IP "\-a"
Audible ping\&.
-.IP "-A"
+.IP "\-A"
Only count addresses matching requested address (This *WILL*
break most things you do\&. Only useful if you are arpinging many
hosts at once\&. See arping-scan-net\&.sh for an example)\&.
-.IP "-b"
-Like -0 but source broadcast source address (255\&.255\&.255\&.255)\&.
+.IP "\-b"
+Like \-0 but source broadcast source address (255\&.255\&.255\&.255)\&.
Note that this may get the arping unanswered since it\&'s not normal behavior
for a host\&.
-.IP "-B"
+.IP "\-B"
Use instead of host if you want to address 255\&.255\&.255\&.255\&.
-.IP "-c \fIcount\fP"
+.IP "\-c \fIcount\fP"
Only send \fIcount\fP requests\&.
-.IP "-d"
+.IP "\-d"
Find duplicate replies\&. Exit with 1 if there are answers from
two different MAC addresses\&.
-.IP "-D"
+.IP "\-D"
Display answers as dots and missing packets as exclamation points\&.
Like flood ping on a Cisco\&.
-.IP "-e"
-Like -a but beep when there is no reply\&.
-.IP "-F"
+.IP "\-e"
+Like \-a but beep when there is no reply\&.
+.IP "\-F"
Don\&'t try to be smart about the interface name\&. Even if this
-switch is not given, -i disables this smartness\&.
-.IP "-h"
+switch is not given, \-i disables this smartness\&.
+.IP "\-h"
Displays a help message and exits\&.
-.IP "-i \fIinterface\fP"
+.IP "\-i \fIinterface\fP"
Don\&'t guess, use the specified interface\&.
-.IP "-p"
+.IP "\-p"
Turn on promiscious mode on interface, use this if you don\&'t
"own" the MAC address you are using\&.
-.IP "-q"
+.IP "\-q"
Does not display messages, except error messages\&.
-.IP "-r"
+.IP "\-r"
Raw output: only the MAC/IP address is displayed for each reply\&.
-.IP "-R"
-Raw output: Like -r but shows "the other one", can be combined with
--r\&.
-.IP "-s \fIMAC\fP"
-Set source MAC address\&. You may need to use -p with this\&.
-.IP "-S \fIIP\fP"
-Like -b and -0 but with set source address\&.
+.IP "\-R"
+Raw output: Like \-r but shows "the other one", can be combined with
+\-r\&.
+.IP "\-s \fIMAC\fP"
+Set source MAC address\&. You may need to use \-p with this\&.
+.IP "\-S \fIIP\fP"
+Like \-b and \-0 but with set source address\&.
Note that this may get the arping unanswered if the target does not have
routing to the IP\&. If you don\&'t own the IP you are using, you may need to turn
-on promiscious mode on the interface (with -p)\&. With this switch you can find
+on promiscious mode on the interface (with \-p)\&. With this switch you can find
out what IP-address a host has without taking an IP-address yourself\&.
-.IP "-t \fIMAC\fP"
+.IP "\-t \fIMAC\fP"
Set target MAC address to use when pinging IP address\&.
-.IP "-T \fIIP\fP"
-Use -T as target address when pinging MACs that won\&'t
+.IP "\-T \fIIP\fP"
+Use \-T as target address when pinging MACs that won\&'t
respond to a broadcast ping but perhaps to a directed broadcast\&.
.IP
-\fIExample\fP: To check the address of MAC-A, use knowledge of MAC-B and IP-B\&.
+\fIExample\fP:
+.nf
+.sp
+To check the address of MAC-A, use knowledge of MAC-B and IP-B\&.
.IP
-$ arping -S <IP-B> -s <MAC-B> -p <MAC-A>
-.IP "-u"
+$ arping \-S <IP-B> \-s <MAC-B> \-p <MAC-A>
+.IP "\-u"
Show index=received/sent instead of just index=received when
pinging MACs\&.
-.IP "-v"
+.IP "\-v"
Verbose output\&. Use twice for more messages\&.
-.IP "-w"
+.IP "\-w"
Time to wait between pings, in microseconds\&.
.PP
.SH "EXAMPLES"
.nf
.sp
-# \fBarping -c 3 88\&.123\&.180\&.225\fP
-ARPING 88\&.123\&.180\&.225
-60 bytes from 00:11:85:4c:01:01 (88\&.123\&.180\&.225): index=0 time=13\&.910 msec
-60 bytes from 00:11:85:4c:01:01 (88\&.123\&.180\&.225): index=1 time=13\&.935 msec
-60 bytes from 00:11:85:4c:01:01 (88\&.123\&.180\&.225): index=2 time=13\&.944 msec
+# \fBarping \-c 3 88\&.1\&.180\&.225\fP
+ARPING 88\&.1\&.180\&.225
+60 bytes from 00:11:85:4c:01:01 (88\&.1\&.180\&.225): index=0 time=13\&.910 msec
+60 bytes from 00:11:85:4c:01:01 (88\&.1\&.180\&.225): index=1 time=13\&.935 msec
+60 bytes from 00:11:85:4c:01:01 (88\&.1\&.180\&.225): index=2 time=13\&.944 msec
.PP
---- 88\&.123\&.180\&.225 statistics ---
+\-\-\- 88\&.1\&.180\&.225 statistics \-\-\-
3 packets transmitted, 3 packets received, 0% unanswered
.PP
-# \fBarping -c 3 00:11:85:4c:01:01\fP
+# \fBarping \-c 3 00:11:85:4c:01:01\fP
ARPING 00:11:85:4c:01:01
-60 bytes from 88\&.123\&.180\&.225 (00:11:85:4c:01:01): icmp_seq=0 time=13\&.367 msec
-60 bytes from 88\&.123\&.180\&.225 (00:11:85:4c:01:01): icmp_seq=1 time=13\&.929 msec
-60 bytes from 88\&.123\&.180\&.225 (00:11:85:4c:01:01): icmp_seq=2 time=13\&.929 msec
+60 bytes from 88\&.1\&.180\&.225 (00:11:85:4c:01:01): icmp_seq=0 time=13\&.367 msec
+60 bytes from 88\&.1\&.180\&.225 (00:11:85:4c:01:01): icmp_seq=1 time=13\&.929 msec
+60 bytes from 88\&.1\&.180\&.225 (00:11:85:4c:01:01): icmp_seq=2 time=13\&.929 msec
.PP
---- 00:11:85:4c:01:01 statistics ---
+\-\-\- 00:11:85:4c:01:01 statistics \-\-\-
3 packets transmitted, 3 packets received, 0% unanswered
.PP
.fi
@@ -137,8 +140,8 @@ ARPING 00:11:85:4c:01:01
.SH "BUGS"
.PP
-You have to use -B instead of arpinging 255\&.255\&.255\&.255, and -b
-instead of -S 255\&.255\&.255\&.255\&. This is libnets fault\&.
+You have to use \-B instead of arpinging 255\&.255\&.255\&.255, and \-b
+instead of \-S 255\&.255\&.255\&.255\&. This is libnets fault\&.
.PP
.SH "SEE ALSO"
diff --git a/doc/arping.yodl b/doc/arping.yodl
index 1f655bc..76df777 100644
--- a/doc/arping.yodl
+++ b/doc/arping.yodl
@@ -76,7 +76,9 @@ out what IP-address a host has without taking an IP-address yourself.
dit(-T em(IP)) Use -T as target address when pinging MACs that won't
respond to a broadcast ping but perhaps to a directed broadcast.
-em(Example): \
+em(Example):
+mancommand(.nf)
+mancommand(.sp)
To check the address of MAC-A, use knowledge of MAC-B and IP-B.
$ arping -S <IP-B> -s <MAC-B> -p <MAC-A>
@@ -90,20 +92,20 @@ enddit()
manpagesection(EXAMPLES)
mancommand(.nf)
mancommand(.sp)
- # bf(arping -c 3 88.123.180.225)
- ARPING 88.123.180.225
- 60 bytes from 00:11:85:4c:01:01 (88.123.180.225): index=0 time=13.910 msec
- 60 bytes from 00:11:85:4c:01:01 (88.123.180.225): index=1 time=13.935 msec
- 60 bytes from 00:11:85:4c:01:01 (88.123.180.225): index=2 time=13.944 msec
+ # bf(arping -c 3 88.1.180.225)
+ ARPING 88.1.180.225
+ 60 bytes from 00:11:85:4c:01:01 (88.1.180.225): index=0 time=13.910 msec
+ 60 bytes from 00:11:85:4c:01:01 (88.1.180.225): index=1 time=13.935 msec
+ 60 bytes from 00:11:85:4c:01:01 (88.1.180.225): index=2 time=13.944 msec
- --- 88.123.180.225 statistics ---
+ --- 88.1.180.225 statistics ---
3 packets transmitted, 3 packets received, 0% unanswered
# bf(arping -c 3 00:11:85:4c:01:01)
ARPING 00:11:85:4c:01:01
- 60 bytes from 88.123.180.225 (00:11:85:4c:01:01): icmp_seq=0 time=13.367 msec
- 60 bytes from 88.123.180.225 (00:11:85:4c:01:01): icmp_seq=1 time=13.929 msec
- 60 bytes from 88.123.180.225 (00:11:85:4c:01:01): icmp_seq=2 time=13.929 msec
+ 60 bytes from 88.1.180.225 (00:11:85:4c:01:01): icmp_seq=0 time=13.367 msec
+ 60 bytes from 88.1.180.225 (00:11:85:4c:01:01): icmp_seq=1 time=13.929 msec
+ 60 bytes from 88.1.180.225 (00:11:85:4c:01:01): icmp_seq=2 time=13.929 msec
--- 00:11:85:4c:01:01 statistics ---
3 packets transmitted, 3 packets received, 0% unanswered
diff --git a/src/arping.c b/src/arping.c
index f5ce5ce..e8bb14c 100644
--- a/src/arping.c
+++ b/src/arping.c
@@ -52,6 +52,10 @@
#include <inttypes.h>
#endif
+#if HAVE_TIME_H
+#include <time.h>
+#endif
+
#if HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
@@ -79,11 +83,11 @@
#if HAVE_WIN32_LIBNET_H
#include <win32/libnet.h>
#endif
-#include <pcap.h>
#if HAVE_NET_BPF_H
#include <net/bpf.h>
#endif
+#include <pcap.h>
#ifndef ETH_ALEN
#define ETH_ALEN 6
@@ -139,7 +143,7 @@ static char dstmac[ETH_ALEN];
static char lastreplymac[ETH_ALEN];
/* doesn't need to be volatile */
-volatile int time_to_die = 0;
+volatile sig_atomic_t time_to_die = 0;
/**
*
@@ -168,15 +172,17 @@ do_libnet_init(const char *ifname)
libnet_destroy(libnet);
libnet = 0;
}
- if (getuid() && geteuid()) {
- fprintf(stderr, "arping: must run as root\n");
- exit(1);
- }
+ /* try libnet_init() even though we aren't root. We may have
+ * a capability or something */
if (!(libnet = libnet_init(LIBNET_LINK,
(char*)ifname,
ebuf))) {
- fprintf(stderr, "arping: libnet_init(): %s\n", ebuf);
+ fprintf(stderr, "arping: %s\n", ebuf);
+ if (getuid() && geteuid()) {
+ fprintf(stderr,
+ "arping: you may need to run as root\n");
+ }
exit(1);
}
}
@@ -233,20 +239,40 @@ static void sigint(int i)
}
/**
+ * idiot-proof gettimeofday() wrapper.
+ */
+static void
+gettv(struct timespec *ts)
+{
+ struct timeval tv;
+ if (-1 == gettimeofday(&tv, NULL)) {
+ fprintf(stderr, "arping: "
+ "gettimeofday(): %s\n",
+ strerror(errno));
+ sigint(0);
+ }
+ ts->tv_sec = tv.tv_sec;
+ ts->tv_nsec = tv.tv_usec * 1000;
+}
+
+/**
* idiot-proof clock_gettime() wrapper
*/
static void
getclock(struct timespec *ts)
{
+#if HAVE_CLOCK_MONOTONIC
if (-1 == clock_gettime(CLOCK_MONOTONIC, ts)) {
fprintf(stderr,
"arping: clock_gettime(): %s\n",
strerror(errno));
sigint(0);
}
+#else
+ gettv(ts);
+#endif
}
-
/**
*
*/
@@ -511,7 +537,7 @@ pingmac_send(uint8_t *srcmac, uint8_t *dstmac,
libnet_geterror(libnet));
sigint(0);
}
- if(verbose>1) {
+ if (verbose > 1) {
getclock(&lastpacketsent);
printf("arping: sending packet at time %d.%09d\n",
lastpacketsent.tv_sec,
@@ -567,7 +593,7 @@ pingip_send(uint8_t *srcmac, uint8_t *dstmac,
libnet_geterror(libnet));
sigint(0);
}
- if(verbose>1) {
+ if (verbose > 1) {
getclock(&lastpacketsent);
printf("arping: sending packet at time %d.%09d\n",
lastpacketsent.tv_sec,
@@ -823,14 +849,14 @@ fixup_timespec(struct timespec *tv)
static void
ping_recv_unix(pcap_t *pcap, uint32_t packetwait, pcap_handler func)
{
- struct timespec tv;
+ struct timespec ts;
struct timespec endtime;
char done = 0;
int fd;
- getclock(&tv);
- endtime.tv_sec = tv.tv_sec + (packetwait / 1000000);
- endtime.tv_nsec = tv.tv_nsec + 1000 * (packetwait % 1000000);
+ getclock(&ts);
+ endtime.tv_sec = ts.tv_sec + (packetwait / 1000000);
+ endtime.tv_nsec = ts.tv_nsec + 1000 * (packetwait % 1000000);
fixup_timespec(&endtime);
fd = pcap_get_selectable_fd(pcap);
@@ -838,33 +864,54 @@ ping_recv_unix(pcap_t *pcap, uint32_t packetwait, pcap_handler func)
for (;!done;) {
int trydispatch = 0;
- getclock(&tv);
- tv.tv_sec = endtime.tv_sec - tv.tv_sec;
- tv.tv_nsec = endtime.tv_nsec - tv.tv_nsec;
- fixup_timespec(&tv);
+ getclock(&ts);
+ ts.tv_sec = endtime.tv_sec - ts.tv_sec;
+ ts.tv_nsec = endtime.tv_nsec - ts.tv_nsec;
+ fixup_timespec(&ts);
if (verbose > 2) {
printf("listen for replies for %d.%09d sec\n",
- tv.tv_sec, tv.tv_nsec);
+ ts.tv_sec, ts.tv_nsec);
}
- if (tv.tv_sec < 0) {
- tv.tv_sec = 0;
- tv.tv_nsec = 1;
+
+ /* if time has passed, do one last check and then we're done.
+ * this also triggers if not using monotonic clock and time
+ * is set forwards */
+ if (ts.tv_sec < 0) {
+ ts.tv_sec = 0;
+ ts.tv_nsec = 1;
done = 1;
}
+
+ /* if wait-for-packet time is longer than full period,
+ * we're obviously not using a monotonic clock and the system
+ * time has been changed.
+ * we don't know how far we're into the waiting, so just end
+ * it here */
+ if ((ts.tv_sec > packetwait / 1000000)
+ || ((ts.tv_sec == packetwait / 1000000)
+ && (ts.tv_nsec > packetwait % 1000000))) {
+ ts.tv_sec = 0;
+ ts.tv_nsec = 1;
+ done = 1;
+ }
+
+ /* check for sigint */
if (time_to_die) {
return;
}
/* try to wait for data */
{
- struct pollfd p;
+ fd_set fds;
int r;
- p.fd = fd;
- p.events = POLLIN | POLLPRI;
+ struct timeval tv;
+ tv.tv_sec = ts.tv_sec;
+ tv.tv_usec = ts.tv_nsec / 1000;
+
+ FD_ZERO(&fds);
+ FD_SET(fd, &fds);
- /* poll has ms resolution, but has less false
- positives than select() */
- r = poll(&p, 1,tv.tv_sec * 1000 + tv.tv_nsec / 1000000);
+ r = select(fd + 1, &fds, NULL, NULL, &tv);
switch (r) {
case 0: /* timeout */
done = 1;
@@ -1378,3 +1425,9 @@ int main(int argc, char **argv)
return !numrecvd;
}
}
+/* ---- Emacs Variables ----
+ * Local Variables:
+ * c-basic-offset: 8
+ * indent-tabs-mode: nil
+ * End:
+ */