diff options
author | Thomas Habets <thomas@habets.se> | 2011-10-31 23:57:00 +0000 |
---|---|---|
committer | Thomas Habets <thomas@habets.se> | 2011-11-01 00:02:25 +0000 |
commit | 1e01eb02c67122c5113afc164c97772a6054456c (patch) | |
tree | adb69b62798a0b0966d6adfd28496082eb5ad2d9 | |
parent | 8e4a0717bcaa7c8d45e2065220736ac4053d3c99 (diff) | |
parent | 91e1da907d9024dd2be06151fc23f3542d896f05 (diff) | |
download | arping-1e01eb02c67122c5113afc164c97772a6054456c.tar.gz |
Merge from mainline
-rw-r--r-- | README | 13 | ||||
-rw-r--r-- | config.h.in | 6 | ||||
-rwxr-xr-x | configure | 191 | ||||
-rw-r--r-- | configure.ac | 27 | ||||
-rw-r--r-- | doc/Makefile.am | 6 | ||||
-rw-r--r-- | doc/Makefile.in | 7 | ||||
-rw-r--r-- | doc/arping.8 | 111 | ||||
-rw-r--r-- | doc/arping.yodl | 22 | ||||
-rw-r--r-- | src/arping.c | 109 |
9 files changed, 387 insertions, 105 deletions
@@ -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 @@ -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: + */ |