|
version 1.1.1.2, 2014/06/15 16:26:43
|
version 1.1.1.3, 2016/10/18 13:16:10
|
|
Line 15
|
Line 15
|
| * |
* |
| */ |
*/ |
| /* |
/* |
| * Copyright (C) 2000-2011 Thomas Habets <thomas@habets.se> | * Copyright (C) 2000-2014 Thomas Habets <thomas@habets.se> |
| * |
* |
| * This library is free software; you can redistribute it and/or | * This program is free software; you can redistribute it and/or modify |
| * modify it under the terms of the GNU General Public | * it under the terms of the GNU General Public License as published by |
| * License as published by the Free Software Foundation; either | * the Free Software Foundation; either version 2 of the License, or |
| * version 2 of the License, or (at your option) any later version. | * (at your option) any later version. |
| * |
* |
| * This library is distributed in the hope that it will be useful, | * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * General Public License for more details. | * GNU General Public License for more details. |
| * |
* |
| * You should have received a copy of the GNU General Public License along |
* You should have received a copy of the GNU General Public License along |
| * with this program; if not, write to the Free Software Foundation, Inc., |
* with this program; if not, write to the Free Software Foundation, Inc., |
|
Line 85
|
Line 85
|
| #include <win32/libnet.h> |
#include <win32/libnet.h> |
| #endif |
#endif |
| |
|
| |
#if HAVE_PWD_H |
| |
#include <pwd.h> |
| |
#endif |
| |
|
| |
#if HAVE_SYS_CAPABILITY_H |
| |
#include <sys/capability.h> |
| |
#endif |
| |
|
| #if HAVE_NET_BPF_H |
#if HAVE_NET_BPF_H |
| #include <net/bpf.h> |
#include <net/bpf.h> |
| #endif |
#endif |
|
Line 110
|
Line 118
|
| |
|
| /** |
/** |
| * OS-specific interface finding using routing table. See findif_*.c |
* OS-specific interface finding using routing table. See findif_*.c |
| |
* ebuf must be called with a size of at least |
| |
* max(LIBNET_ERRBUF_SIZE, PCAP_ERRBUF_SIZE). |
| */ |
*/ |
| const char * |
const char * |
| arping_lookupdev(uint32_t srcip, uint32_t dstip, char *ebuf); |
arping_lookupdev(uint32_t srcip, uint32_t dstip, char *ebuf); |
|
Line 121 static const char *version = VERSION; /* from autoconf
|
Line 131 static const char *version = VERSION; /* from autoconf
|
| |
|
| static libnet_t *libnet = 0; |
static libnet_t *libnet = 0; |
| |
|
| |
/* Timestamp of last packet sent. |
| |
* Used for timing, and assumes that reply is due to most recent sent query. |
| |
*/ |
| static struct timespec lastpacketsent; |
static struct timespec lastpacketsent; |
| |
|
| /* target string */ |
/* target string */ |
|
Line 146 static int reverse_beep = 0; /* beep when expe
|
Line 159 static int reverse_beep = 0; /* beep when expe
|
| static int alsototal = 0; /* print sent as well as received. -u */ |
static int alsototal = 0; /* print sent as well as received. -u */ |
| static int addr_must_be_same = 0; /* -A */ |
static int addr_must_be_same = 0; /* -A */ |
| static int unsolicited = 0; /* -U */ |
static int unsolicited = 0; /* -U */ |
| |
static int send_reply = 0; /* Send reply instead of request. -P */ |
| |
|
| static int finddup = 0; /* finddup mode. -d */ |
static int finddup = 0; /* finddup mode. -d */ |
| static int dupfound = 0; /* set to 1 if dup found */ |
static int dupfound = 0; /* set to 1 if dup found */ |
| static char lastreplymac[ETH_ALEN]; /* if last different from this then dup */ |
static char lastreplymac[ETH_ALEN]; /* if last different from this then dup */ |
| |
|
| static unsigned int numsent = 0; /* packets sent */ | static unsigned int numsent = 0; /* packets sent */ |
| static unsigned int numrecvd = 0; /* packets received */ | static unsigned int numrecvd = 0; /* packets received */ |
| static unsigned int numdots = 0; /* dots that should be printed */ | static unsigned int max_replies = UINT_MAX; /* exit after -C replies */ |
| | static unsigned int numdots = 0; /* dots that should be printed */ |
| | static const char* timestamp_type = NULL; /* Incoming packet measurement ts type (-m) */ |
| |
|
| static double stats_min_time = -1; |
static double stats_min_time = -1; |
| static double stats_max_time = -1; |
static double stats_max_time = -1; |
|
Line 178 int verbose = 0; /* Increase with -v */
|
Line 194 int verbose = 0; /* Increase with -v */
|
| static volatile sig_atomic_t time_to_die = 0; |
static volatile sig_atomic_t time_to_die = 0; |
| |
|
| /** |
/** |
| |
* If possible, chroot. |
| |
* |
| |
* The sshd user is used for privilege separation in OpenSSH. |
| |
* Let's assume it's installed and chroot() to there. |
| |
*/ |
| |
static void |
| |
drop_fs_root() |
| |
{ |
| |
const char* chroot_user = "sshd"; |
| |
struct passwd *pw; |
| |
errno = 0; |
| |
if (!(pw = getpwnam(chroot_user))) { |
| |
if (verbose) { |
| |
printf("arping: getpwnam(%s): %s", |
| |
chroot_user, strerror(errno)); |
| |
} |
| |
return; |
| |
} |
| |
if (chdir(pw->pw_dir)) { |
| |
if (verbose) { |
| |
printf("arping: chdir(%s): %s", |
| |
pw->pw_dir, strerror(errno)); |
| |
} |
| |
return; |
| |
} |
| |
if (chroot(pw->pw_dir)) { |
| |
if (verbose) { |
| |
printf("arping: chroot(%s): %s", |
| |
pw->pw_dir, strerror(errno)); |
| |
} |
| |
return; |
| |
} |
| |
if (verbose > 1) { |
| |
printf("arping: Successfully chrooted to %s\n", pw->pw_dir); |
| |
} |
| |
} |
| |
|
| |
/** |
| |
* If possible, drop uid to nobody. |
| |
* |
| |
* This code only successfully sets all [ug]ids if running as |
| |
* root. ARPing is most likely running as root unless using |
| |
* capabilities, and those are dropped elsewhere. |
| |
*/ |
| |
static void |
| |
drop_uid(uid_t uid, gid_t gid) |
| |
{ |
| |
int fail = 0; |
| |
if (setgroups(0, NULL)) { |
| |
if (verbose) { |
| |
printf("arping: setgroups(0, NULL): %s\n", strerror(errno)); |
| |
} |
| |
fail++; |
| |
} |
| |
if (gid && setgid(gid)) { |
| |
if (verbose) { |
| |
printf("arping: setgid(): %s\n", strerror(errno)); |
| |
} |
| |
fail++; |
| |
} |
| |
if (uid && setuid(uid)) { |
| |
if (verbose) { |
| |
printf("arping: setuid(): %s\n", strerror(errno)); |
| |
} |
| |
fail++; |
| |
} |
| |
if (!fail && verbose > 1) { |
| |
printf("arping: Successfully dropped uid/gid to %d/%d.\n", |
| |
uid, gid); |
| |
} |
| |
} |
| |
|
| |
/** |
| |
* Drop any and all capabilities. |
| |
*/ |
| |
static void |
| |
drop_capabilities() |
| |
{ |
| |
#if HAVE_CAP_INIT |
| |
cap_t no_cap; |
| |
if (!(no_cap = cap_init())) { |
| |
if (verbose) { |
| |
printf("arping: cap_init(): %s\n", strerror(errno)); |
| |
} |
| |
return; |
| |
} |
| |
if (cap_set_proc(no_cap)) { |
| |
if (verbose) { |
| |
printf("arping: cap_set_proc(): %s\n", strerror(errno)); |
| |
} |
| |
} |
| |
if (verbose > 1) { |
| |
printf("arping: Successfully dropped all capabilities.\n"); |
| |
} |
| |
cap_free(no_cap); |
| |
#endif |
| |
} |
| |
|
| |
/** |
| |
* drop all privileges. |
| |
*/ |
| |
static void |
| |
drop_privileges() |
| |
{ |
| |
// Need to get uid/gid of 'nobody' before chroot(). |
| |
const char* drop_user = "nobody"; |
| |
struct passwd *pw; |
| |
errno = 0; |
| |
uid_t uid = 0; |
| |
gid_t gid = 0; |
| |
if (!(pw = getpwnam(drop_user))) { |
| |
if (verbose) { |
| |
printf("arping: getpwnam(%s): %s\n", |
| |
drop_user, strerror(errno)); |
| |
} |
| |
return; |
| |
} else { |
| |
uid = pw->pw_uid; |
| |
gid = pw->pw_gid; |
| |
} |
| |
drop_fs_root(); |
| |
drop_uid(uid, gid); |
| |
drop_capabilities(); |
| |
} |
| |
|
| |
|
| |
/** |
| |
* Do pcap_open_live(), except by using the pcap_create() interface |
| |
* introduced in 2008 (libpcap 0.4) where available. |
| |
* |
| |
* FIXME: Use pcap_set_buffer_size()? |
| |
*/ |
| |
static pcap_t* |
| |
try_pcap_open_live(const char *device, int snaplen, |
| |
int promisc, int to_ms, char *errbuf) |
| |
{ |
| |
#ifdef HAVE_PCAP_CREATE |
| |
pcap_t* pcap; |
| |
int rc; |
| |
|
| |
if (!(pcap = pcap_create(device, errbuf))) { |
| |
goto err; |
| |
} |
| |
if ((rc = pcap_set_snaplen(pcap, snaplen))) { |
| |
snprintf(errbuf, PCAP_ERRBUF_SIZE, "pcap_set_snaplen(): %s", pcap_statustostr(rc)); |
| |
goto err; |
| |
} |
| |
if ((rc = pcap_set_promisc(pcap, promisc))) { |
| |
snprintf(errbuf, PCAP_ERRBUF_SIZE, "pcap_set_promisc(): %s", pcap_statustostr(rc)); |
| |
goto err; |
| |
} |
| |
if ((rc = pcap_set_timeout(pcap, to_ms))) { |
| |
snprintf(errbuf, PCAP_ERRBUF_SIZE, "pcap_set_timeout(): %s", pcap_statustostr(rc)); |
| |
goto err; |
| |
} |
| |
|
| |
#ifdef HAVE_PCAP_SET_IMMEDIATE_MODE |
| |
// Without immediate mode some architectures (e.g. Linux with |
| |
// TPACKET_V3) will buffer replies and incorrectly upwards of |
| |
// hundreds of milliseconds of delay. |
| |
if ((rc = pcap_set_immediate_mode(pcap, 1))) { |
| |
if (verbose) { |
| |
fprintf(stderr, "arping: pcap_set_immediate_mode() failed: %s\n", pcap_statustostr(rc)); |
| |
} |
| |
} |
| |
#endif |
| |
#ifdef HAVE_PCAP_LIST_TSTAMP_TYPES |
| |
if (timestamp_type) { |
| |
int err; |
| |
int v = pcap_tstamp_type_name_to_val(timestamp_type); |
| |
if (v == PCAP_ERROR) { |
| |
fprintf(stderr, "arping: Unknown timestamp type \"%s\"\n", timestamp_type); |
| |
exit(1); |
| |
} |
| |
if ((err = pcap_set_tstamp_type(pcap, v))) { |
| |
fprintf(stderr, |
| |
"arping: Failed to set timestamp type \"%s\" (%d): %s\n", |
| |
timestamp_type, v, pcap_statustostr(err)); |
| |
} |
| |
} |
| |
#endif |
| |
if ((rc = pcap_activate(pcap))) { |
| |
if (timestamp_type) { |
| |
snprintf(errbuf, PCAP_ERRBUF_SIZE, "pcap_activate(tstype=\"%s\"): %s. Try without setting timestamp type.", timestamp_type, pcap_statustostr(rc)); |
| |
} else { |
| |
snprintf(errbuf, PCAP_ERRBUF_SIZE, "pcap_activate(): %s", pcap_statustostr(rc)); |
| |
} |
| |
goto err; |
| |
} |
| |
#ifdef HAVE_PCAP_LIST_TSTAMP_TYPES |
| |
// List timestamp types after activating, since we don't want to list |
| |
// them if activating failed. |
| |
if (verbose > 1) { |
| |
int *ts; |
| |
int count; |
| |
count = pcap_list_tstamp_types(pcap, &ts); |
| |
if (count == PCAP_ERROR) { |
| |
fprintf(stderr, "arping: pcap_list_tstamp_types() failed\n"); |
| |
} else { |
| |
int c; |
| |
const char* fmt = " %-18s %s\n"; |
| |
fprintf(stderr, "Timestamp types:\n"); |
| |
fprintf(stderr, fmt, "Name", "Description"); |
| |
for (c = 0; c < count; c++) { |
| |
fprintf(stderr, fmt, pcap_tstamp_type_val_to_name(ts[c]), |
| |
pcap_tstamp_type_val_to_description(ts[c])); |
| |
} |
| |
pcap_free_tstamp_types(ts); |
| |
} |
| |
} |
| |
#endif |
| |
return pcap; |
| |
err: |
| |
if (pcap) { |
| |
pcap_close(pcap); |
| |
} |
| |
return NULL; |
| |
#else |
| |
return pcap_open_live(device, snaplen, promisc, to_ms, errbuf); |
| |
#endif |
| |
} |
| |
|
| |
/** |
| * Some stupid OSs (Solaris) think it's a good idea to put network |
* Some stupid OSs (Solaris) think it's a good idea to put network |
| * devices in /dev and then play musical chairs with them. |
* devices in /dev and then play musical chairs with them. |
| * |
* |
|
Line 194 do_pcap_open_live(const char *device, int snaplen,
|
Line 433 do_pcap_open_live(const char *device, int snaplen,
|
| pcap_t* ret; |
pcap_t* ret; |
| char buf[PATH_MAX]; |
char buf[PATH_MAX]; |
| |
|
| if ((ret = pcap_open_live(device, snaplen, promisc, to_ms, errbuf))) { | if ((ret = try_pcap_open_live(device, snaplen, promisc, to_ms, errbuf))) { |
| return ret; |
return ret; |
| } |
} |
| |
|
| snprintf(buf, sizeof(buf), "/dev/%s", device); |
snprintf(buf, sizeof(buf), "/dev/%s", device); |
| if ((ret = pcap_open_live(buf, snaplen, promisc, to_ms, errbuf))) { | if ((ret = try_pcap_open_live(buf, snaplen, promisc, to_ms, errbuf))) { |
| return ret; |
return ret; |
| } |
} |
| |
|
| snprintf(buf, sizeof(buf), "/dev/net/%s", device); |
snprintf(buf, sizeof(buf), "/dev/net/%s", device); |
| if ((ret = pcap_open_live(buf, snaplen, promisc, to_ms, errbuf))) { | if ((ret = try_pcap_open_live(buf, snaplen, promisc, to_ms, errbuf))) { |
| return ret; |
return ret; |
| } |
} |
| |
|
| /* Call original again to reset the error message. */ |
/* Call original again to reset the error message. */ |
| return pcap_open_live(device, snaplen, promisc, to_ms, errbuf); | return try_pcap_open_live(device, snaplen, promisc, to_ms, errbuf); |
| } |
} |
| |
|
| /** |
/** |
| * | * Some Libnet error messages end with a newline. Strip that in place. |
| */ |
*/ |
| static void | void |
| count_missing_dots() | strip_newline(char* s) { |
| { | if (!*s) { |
| while (numsent > numdots) { | return; |
| putchar('.'); | |
| numdots++; | |
| } |
} |
| |
size_t n; |
| |
for (n = strlen(s); s[n - 1] == '\n'; --n) { |
| |
s[n - 1] = 0; |
| |
} |
| } |
} |
| |
|
| /** |
/** |
| * Init libnet with specified ifname. Destroy if already inited. |
* Init libnet with specified ifname. Destroy if already inited. |
| |
* If this function retries with different parameter it will preserve |
| |
* the original error message and print that. |
| |
* Call with recursive=0. |
| */ |
*/ |
| void |
void |
| do_libnet_init(const char *ifname) | do_libnet_init(const char *ifname, int recursive) |
| { |
{ |
| char ebuf[LIBNET_ERRBUF_SIZE]; |
char ebuf[LIBNET_ERRBUF_SIZE]; |
| |
ebuf[0] = 0; |
| if (verbose > 1) { |
if (verbose > 1) { |
| printf("libnet_init(%s)\n", ifname ? ifname : "<null>"); | printf("arping: libnet_init(%s)\n", ifname ? ifname : "<null>"); |
| } |
} |
| if (libnet) { |
if (libnet) { |
| /* Probably going to switch interface from temp to real. */ |
/* Probably going to switch interface from temp to real. */ |
|
Line 245 do_libnet_init(const char *ifname)
|
Line 490 do_libnet_init(const char *ifname)
|
| if (!(libnet = libnet_init(LIBNET_LINK, |
if (!(libnet = libnet_init(LIBNET_LINK, |
| (char*)ifname, |
(char*)ifname, |
| ebuf))) { |
ebuf))) { |
| fprintf(stderr, "arping: %s\n", ebuf); | strip_newline(ebuf); |
| | if (!ifname) { |
| | /* Sometimes libnet guesses an interface that it then |
| | * can't use. Work around that by attempting to |
| | * use "lo". */ |
| | return do_libnet_init("lo", 1); |
| | } else if (recursive) { |
| | /* Continue original execution. */ |
| | return; |
| | } |
| | fprintf(stderr, "arping: libnet_init(LIBNET_LINK, %s): %s\n", |
| | ifname ? ifname : "<null>", ebuf); |
| if (getuid() && geteuid()) { |
if (getuid() && geteuid()) { |
| fprintf(stderr, |
fprintf(stderr, |
| "arping: you may need to run as root\n"); |
"arping: you may need to run as root\n"); |
|
Line 291 getclock(struct timespec *ts)
|
Line 547 getclock(struct timespec *ts)
|
| /** |
/** |
| * |
* |
| */ |
*/ |
| |
static char* |
| |
format_mac(unsigned char* mac, char* buf, size_t bufsize) { |
| |
snprintf(buf, bufsize, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x", |
| |
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); |
| |
return buf; |
| |
} |
| |
|
| |
/** |
| |
* |
| |
*/ |
| static void |
static void |
| extended_usage() |
extended_usage() |
| { |
{ |
|
Line 310 extended_usage()
|
Line 576 extended_usage()
|
| " -B Use instead of host if you want to address 255.255.255.255.\n" |
" -B Use instead of host if you want to address 255.255.255.255.\n" |
| " -c count\n" |
" -c count\n" |
| " Only send count requests.\n" |
" Only send count requests.\n" |
| |
" -C count\n" |
| |
" Only wait for this many replies, regardless of -c and -w.\n" |
| " -d Find duplicate replies. Exit with 1 if there are " |
" -d Find duplicate replies. Exit with 1 if there are " |
| "answers from\n" |
"answers from\n" |
| " two different MAC addresses.\n" |
" two different MAC addresses.\n" |
|
Line 320 extended_usage()
|
Line 588 extended_usage()
|
| " -h Displays a help message and exits.\n" |
" -h Displays a help message and exits.\n" |
| " -i interface\n" |
" -i interface\n" |
| " Use the specified interface.\n" |
" Use the specified interface.\n" |
| |
" -m type" |
| |
#ifndef HAVE_PCAP_LIST_TSTAMP_TYPES |
| |
" (Disabled on this system. Option ignored)" |
| |
#endif |
| |
"\n Type of timestamp to use for incoming packets. Use -vv when\n" |
| |
" pinging to list available ones.\n" |
| " -q Does not display messages, except error messages.\n" |
" -q Does not display messages, except error messages.\n" |
| " -r Raw output: only the MAC/IP address is displayed for each reply.\n" |
" -r Raw output: only the MAC/IP address is displayed for each reply.\n" |
| " -R Raw output: Like -r but shows \"the other one\", can be combined\n" |
" -R Raw output: Like -r but shows \"the other one\", can be combined\n" |
| " with -r.\n" |
" with -r.\n" |
| " -s MAC Set source MAC address. You may need to use -p with this.\n" |
" -s MAC Set source MAC address. You may need to use -p with this.\n" |
| " -S IP Like -b and -0 but with set source address. Note that this may\n" |
" -S IP Like -b and -0 but with set source address. Note that this may\n" |
| " get the arping unanswered if the target does not have routing to\n" | " get the arping unanswered if the target does not have routing to\n" |
| " the IP. If you don't own the IP you are using, you may need to\n" |
" the IP. If you don't own the IP you are using, you may need to\n" |
| " turn on promiscious mode on the interface (with -p). With this\n" |
" turn on promiscious mode on the interface (with -p). With this\n" |
| " switch you can find out what IP-address a host has without tak-\n" |
" switch you can find out what IP-address a host has without tak-\n" |
|
Line 339 extended_usage()
|
Line 613 extended_usage()
|
| " $ arping -S <IP-B> -s <MAC-B> -p <MAC-A>\n" |
" $ arping -S <IP-B> -s <MAC-B> -p <MAC-A>\n" |
| " -p Turn on promiscious mode on interface, use this if you don't\n" |
" -p Turn on promiscious mode on interface, use this if you don't\n" |
| " \"own\" the MAC address you are using.\n" |
" \"own\" the MAC address you are using.\n" |
| |
" -P Send ARP replies instead of requests. Useful with -U.\n" |
| " -u Show index=received/sent instead of just index=received when\n" |
" -u Show index=received/sent instead of just index=received when\n" |
| " pinging MACs.\n" |
" pinging MACs.\n" |
| " -U Send unsolicited ARP.\n" |
" -U Send unsolicited ARP.\n" |
| " -v Verbose output. Use twice for more messages.\n" |
" -v Verbose output. Use twice for more messages.\n" |
| " -w Time to wait between pings, in microseconds.\n"); | " -w Time to wait between pings, in microseconds.\n" |
| | " -W Same as -w, but in floating point seconds.\n"); |
| printf("Report bugs to: thomas@habets.se\n" |
printf("Report bugs to: thomas@habets.se\n" |
| "Arping home page: <http://www.habets.pp.se/synscan/>\n" |
"Arping home page: <http://www.habets.pp.se/synscan/>\n" |
| "Development repo: http://github.com/ThomasHabets/arping\n"); |
"Development repo: http://github.com/ThomasHabets/arping\n"); |
|
Line 357 standard_usage()
|
Line 633 standard_usage()
|
| { |
{ |
| printf("ARPing %s, by Thomas Habets <thomas@habets.se>\n", |
printf("ARPing %s, by Thomas Habets <thomas@habets.se>\n", |
| version); |
version); |
| printf("usage: arping [ -0aAbdDeFpqrRuUv ] [ -w <us> ] " | printf("usage: arping [ -0aAbdDeFpPqrRuUv ] [ -w <us> ] " |
| | "[ -W <sec> ] " |
| "[ -S <host/ip> ]\n" |
"[ -S <host/ip> ]\n" |
| " " |
" " |
| "[ -T <host/ip ] " |
"[ -T <host/ip ] " |
| "[ -s <MAC> ] [ -t <MAC> ] [ -c <count> ]\n" |
"[ -s <MAC> ] [ -t <MAC> ] [ -c <count> ]\n" |
| " " |
" " |
| "[ -i <interface> ] " | "[ -C <count> ] [ -i <interface> ] [ -m <type> ] " |
| "<host/ip/MAC | -B>\n"); |
"<host/ip/MAC | -B>\n"); |
| } |
} |
| |
|
|
Line 477 timespec2dbl(const struct timespec *tv)
|
Line 754 timespec2dbl(const struct timespec *tv)
|
| * max size of buffer is intsize + 1 + intsize + 4 = 70 bytes or so |
* max size of buffer is intsize + 1 + intsize + 4 = 70 bytes or so |
| * |
* |
| * Still, I'm using at least 128bytes below |
* Still, I'm using at least 128bytes below |
| * |
|
| * (because snprintf() sadly isn't as portable, that's why) |
|
| */ |
*/ |
| static char *ts2str(const struct timespec *tv, const struct timespec *tv2, |
static char *ts2str(const struct timespec *tv, const struct timespec *tv2, |
| char *buf) | char *buf, size_t bufsize) |
| { |
{ |
| double f,f2; |
double f,f2; |
| int exp = 0; |
int exp = 0; |
|
Line 495 static char *ts2str(const struct timespec *tv, const s
|
Line 770 static char *ts2str(const struct timespec *tv, const s
|
| } |
} |
| switch (exp) { |
switch (exp) { |
| case 0: |
case 0: |
| sprintf(buf, "%.3f nsec", f); | snprintf(buf, bufsize, "%.3f nsec", f); |
| break; |
break; |
| case 3: |
case 3: |
| sprintf(buf, "%.3f usec", f); | snprintf(buf, bufsize, "%.3f usec", f); |
| break; |
break; |
| case 6: |
case 6: |
| sprintf(buf, "%.3f msec", f); | snprintf(buf, bufsize, "%.3f msec", f); |
| break; |
break; |
| case 9: |
case 9: |
| sprintf(buf, "%.3f sec", f); | snprintf(buf, bufsize, "%.3f sec", f); |
| break; |
break; |
| case 12: |
case 12: |
| sprintf(buf, "%.3f sec", f*1000); | snprintf(buf, bufsize, "%.3f sec", f*1000); |
| break; |
break; |
| default: |
default: |
| /* huh, uh, huhuh */ |
/* huh, uh, huhuh */ |
| sprintf(buf, "%.3fe%d sec", f, exp-9); | snprintf(buf, bufsize, "%.3fe%d sec", f, exp-9); |
| } |
} |
| return buf; |
return buf; |
| } |
} |
|
Line 598 pingip_send()
|
Line 873 pingip_send()
|
| ETHERTYPE_IP, |
ETHERTYPE_IP, |
| ETH_ALEN, |
ETH_ALEN, |
| IP_ALEN, |
IP_ALEN, |
| ARPOP_REQUEST, | send_reply ? ARPOP_REPLY : ARPOP_REQUEST, |
| srcmac, |
srcmac, |
| (uint8_t*)&srcip, |
(uint8_t*)&srcip, |
| unsolicited ? (uint8_t*)ethxmas : (uint8_t*)ethnull, |
unsolicited ? (uint8_t*)ethxmas : (uint8_t*)ethnull, |
|
Line 651 pingip_recv(const char *unused, struct pcap_pkthdr *h,
|
Line 926 pingip_recv(const char *unused, struct pcap_pkthdr *h,
|
| int c; |
int c; |
| |
|
| if (verbose > 2) { |
if (verbose > 2) { |
| printf("arping: received response for ip ping\n"); | printf("arping: received response for IP ping\n"); |
| } |
} |
| |
|
| getclock(&arrival); |
getclock(&arrival); |
|
Line 659 pingip_recv(const char *unused, struct pcap_pkthdr *h,
|
Line 934 pingip_recv(const char *unused, struct pcap_pkthdr *h,
|
| heth = (void*)packet; |
heth = (void*)packet; |
| harp = (void*)((char*)heth + LIBNET_ETH_H); |
harp = (void*)((char*)heth + LIBNET_ETH_H); |
| |
|
| if ((htons(harp->ar_op) == ARPOP_REPLY) | // ARP reply. |
| && (htons(harp->ar_pro) == ETHERTYPE_IP) | if (htons(harp->ar_op) != ARPOP_REPLY) { |
| && (htons(harp->ar_hrd) == ARPHRD_ETHER)) { | return; |
| uint32_t ip; | } |
| memcpy(&ip, (char*)harp + harp->ar_hln | if (verbose > 3) { |
| + LIBNET_ARP_H,4); | printf("arping: ... packet is ARP reply\n"); |
| if (addr_must_be_same | } |
| && (memcmp((u_char*)harp+sizeof(struct libnet_arp_hdr), | |
| dstmac, ETH_ALEN))) { | |
| return; | |
| } | |
| if (dstip == ip) { | |
| update_stats(timespec2dbl(&arrival) | |
| - timespec2dbl(&lastpacketsent)); | |
| switch(display) { | |
| case DOT: | |
| numdots++; | |
| count_missing_dots(); | |
| putchar('!'); | |
| break; | |
| case NORMAL: { | |
| char buf[128]; | |
| printf("%d bytes from ", h->len); | |
| for (c = 0; c < 6; c++) { | |
| printf("%.2x%c", heth->_802_3_shost[c], | |
| (c<5)?':':' '); | |
| } | |
| | |
| printf("(%s): index=%d", | |
| libnet_addr2name4(ip,0), | |
| numrecvd); | |
| if (alsototal) { | |
| printf("/%u", numsent-1); | |
| } | |
| printf(" time=%s", | |
| ts2str(&lastpacketsent, | |
| &arrival,buf)); | |
| break; | |
| } | |
| case QUIET: | |
| break; | |
| case RAWRAW: | |
| for (c = 0; c < 6; c++) { | |
| printf("%.2x%c", heth->_802_3_shost[c], | |
| (c<5)?':':' '); | |
| } | |
| printf("%s", libnet_addr2name4(ip,0)); | |
| break; | |
| case RRAW: | |
| printf("%s", libnet_addr2name4(ip,0)); | |
| break; | |
| case RAW: | |
| for (c = 0; c < 6; c++) { | |
| printf("%.2x%s", heth->_802_3_shost[c], | |
| (c<5)?":":""); | |
| } | |
| break; | |
| default: | |
| fprintf(stderr, "arping: can't happen!\n"); | |
| } | |
| |
|
| switch (display) { | // From IPv4 address reply. |
| case QUIET: | if (htons(harp->ar_pro) != ETHERTYPE_IP) { |
| case DOT: | return; |
| break; | } |
| default: | if (verbose > 3) { |
| if (beep) { | printf("arping: ... from IPv4 address\n"); |
| printf("\a"); | } |
| } | |
| printf("\n"); | |
| } | |
| if (numrecvd) { | |
| if (memcmp(lastreplymac, | |
| heth->_802_3_shost, ETH_ALEN)) { | |
| dupfound = 1; | |
| } | |
| } | |
| memcpy(lastreplymac, heth->_802_3_shost, ETH_ALEN); | |
| |
|
| numrecvd++; | // To Ethernet address. |
| } | if (htons(harp->ar_hrd) != ARPHRD_ETHER) { |
| } | return; |
| | } |
| | if (verbose > 3) { |
| | printf("arping: ... to Ethernet address\n"); |
| | } |
| | |
| | // Must be sent from target address. |
| | // Should very likely only be used if using -T. |
| | if (addr_must_be_same) { |
| | if (memcmp((u_char*)harp + sizeof(struct libnet_arp_hdr), |
| | dstmac, ETH_ALEN)) { |
| | return; |
| | } |
| | } |
| | if (verbose > 3) { |
| | printf("arping: ... sent by acceptable host\n"); |
| | } |
| | |
| | // Actually the IPv4 address we asked for. |
| | uint32_t ip; |
| | memcpy(&ip, (char*)harp + harp->ar_hln + LIBNET_ARP_H, 4); |
| | if (dstip != ip) { |
| | return; |
| | } |
| | if (verbose > 3) { |
| | printf("arping: ... for the right IPv4 address!\n"); |
| | } |
| | |
| | update_stats(timespec2dbl(&arrival) - timespec2dbl(&lastpacketsent)); |
| | char buf[128]; |
| | if (beep) { |
| | printf("\a"); |
| | } |
| | switch(display) { |
| | case DOT: |
| | putchar('!'); |
| | break; |
| | case NORMAL: |
| | printf("%d bytes from %s (%s): index=%d", |
| | h->len, format_mac(heth->_802_3_shost, |
| | buf, sizeof(buf)), |
| | libnet_addr2name4(ip, 0), numrecvd); |
| | |
| | if (alsototal) { |
| | printf("/%u", numsent-1); |
| | } |
| | printf(" time=%s", ts2str(&lastpacketsent, &arrival, buf, |
| | sizeof(buf))); |
| | break; |
| | case QUIET: |
| | break; |
| | case RAWRAW: |
| | printf("%s %s", format_mac(heth->_802_3_shost, |
| | buf, sizeof(buf)), |
| | libnet_addr2name4(ip, 0)); |
| | break; |
| | case RRAW: |
| | printf("%s", libnet_addr2name4(ip, 0)); |
| | break; |
| | case RAW: |
| | printf("%s", format_mac(heth->_802_3_shost, |
| | buf, sizeof(buf))); |
| | break; |
| | default: |
| | fprintf(stderr, "arping: can't happen!\n"); |
| | } |
| | fflush(stdout); |
| | |
| | switch (display) { |
| | case QUIET: |
| | case DOT: |
| | break; |
| | default: |
| | printf("\n"); |
| | } |
| | if (numrecvd) { |
| | if (memcmp(lastreplymac, |
| | heth->_802_3_shost, ETH_ALEN)) { |
| | dupfound = 1; |
| | } |
| | } |
| | memcpy(lastreplymac, heth->_802_3_shost, ETH_ALEN); |
| | |
| | numrecvd++; |
| | if (numrecvd >= max_replies) { |
| | sigint(0); |
| | } |
| } |
} |
| |
|
| /** handle incoming packet when pinging an MAC address. |
/** handle incoming packet when pinging an MAC address. |
|
Line 767 pingmac_recv(const char *unused, struct pcap_pkthdr *h
|
Line 1065 pingmac_recv(const char *unused, struct pcap_pkthdr *h
|
| hip = (void*)((char*)heth + LIBNET_ETH_H); |
hip = (void*)((char*)heth + LIBNET_ETH_H); |
| hicmp = (void*)((char*)hip + LIBNET_IPV4_H); |
hicmp = (void*)((char*)hip + LIBNET_IPV4_H); |
| |
|
| if ((htons(hicmp->icmp_type) == ICMP_ECHOREPLY) | // Dest MAC must be me. |
| && ((!memcmp(heth->_802_3_shost, dstmac,ETH_ALEN) | if (memcmp(heth->_802_3_dhost, srcmac, ETH_ALEN)) { |
| || !memcmp(dstmac, ethxmas, ETH_ALEN))) | return; |
| && !memcmp(heth->_802_3_dhost, srcmac, ETH_ALEN)) { | } |
| if (addr_must_be_same) { | |
| uint32_t tmp; | // Source MAC must match, if set. |
| memcpy(&tmp, &hip->ip_src, 4); | if (memcmp(dstmac, ethxmas, ETH_ALEN)) { |
| if (dstip != tmp) { | if (memcmp(heth->_802_3_shost, dstmac, ETH_ALEN)) { |
| return; | return; |
| } | } |
| } | } |
| update_stats(timespec2dbl(&arrival) | |
| - timespec2dbl(&lastpacketsent)); | // IPv4 Address must be me (maybe). |
| switch(display) { | if (addr_must_be_same) { |
| case QUIET: | uint32_t tmp; |
| break; | memcpy(&tmp, &hip->ip_src, 4); |
| case NORMAL: { | if (dstip != tmp) { |
| char buf[128]; | return; |
| printf("%d bytes from %s (",h->len, | } |
| libnet_addr2name4(*(int*)&hip->ip_src, 0)); | } |
| for (c = 0; c < 6; c++) { | |
| printf("%.2x%c", heth->_802_3_shost[c], | // Must be ICMP echo reply. |
| (c<5)?':':')'); | if (htons(hicmp->icmp_type) != ICMP_ECHOREPLY) { |
| } | return; |
| printf(": icmp_seq=%d time=%s", | } |
| htons(hicmp->icmp_seq),ts2str(&lastpacketsent, | |
| &arrival,buf)); | update_stats(timespec2dbl(&arrival) - timespec2dbl(&lastpacketsent)); |
| break; } | if (beep) { |
| case RAW: | printf("\a"); |
| printf("%s", | } |
| libnet_addr2name4(hip->ip_src.s_addr, 0)); | char buf[128]; |
| break; | char buf2[128]; |
| case RRAW: | switch(display) { |
| for (c = 0; c < 6; c++) { | case QUIET: |
| printf("%.2x%s", heth->_802_3_shost[c], | break; |
| (c<5)?":":""); | case DOT: |
| } | putchar('!'); |
| break; | break; |
| case RAWRAW: | case NORMAL: |
| for (c = 0; c < 6; c++) { | printf("%d bytes from %s (%s): icmp_seq=%d time=%s", h->len, |
| printf("%.2x%c", heth->_802_3_shost[c], | libnet_addr2name4(*(int*)&hip->ip_src, 0), |
| (c<5)?':':' '); | format_mac(heth->_802_3_shost, buf, sizeof(buf)), |
| } | htons(hicmp->icmp_seq), |
| printf("%s", | ts2str(&lastpacketsent, &arrival, buf2, sizeof(buf2))); |
| libnet_addr2name4(hip->ip_src.s_addr, 0)); | break; |
| break; | case RAW: |
| default: | printf("%s", libnet_addr2name4(hip->ip_src.s_addr, 0)); |
| fprintf(stderr, "arping: can't-happen-bug\n"); | break; |
| sigint(0); | case RRAW: |
| } | printf("%s", format_mac(heth->_802_3_shost, buf, sizeof(buf))); |
| if (display != QUIET) { | break; |
| printf(beep?"\a\n":"\n"); | case RAWRAW: |
| } | printf("%s %s", |
| numrecvd++; | format_mac(heth->_802_3_shost, buf, sizeof(buf)), |
| } | libnet_addr2name4(hip->ip_src.s_addr, 0)); |
| | break; |
| | default: |
| | fprintf(stderr, "arping: can't-happen-bug\n"); |
| | sigint(0); |
| | } |
| | fflush(stdout); |
| | switch (display) { |
| | case QUIET: |
| | case DOT: |
| | break; |
| | default: |
| | printf("\n"); |
| | } |
| | numrecvd++; |
| | if (numrecvd >= max_replies) { |
| | sigint(0); |
| | } |
| } |
} |
| |
|
| /** |
/** |
|
Line 869 ping_recv(pcap_t *pcap, uint32_t packetwait, pcap_hand
|
Line 1184 ping_recv(pcap_t *pcap, uint32_t packetwait, pcap_hand
|
| ts.tv_nsec = endtime.tv_nsec - ts.tv_nsec; |
ts.tv_nsec = endtime.tv_nsec - ts.tv_nsec; |
| fixup_timespec(&ts); |
fixup_timespec(&ts); |
| if (verbose > 2) { |
if (verbose > 2) { |
| printf("listen for replies for %ld.%09ld sec\n", | printf("arping: listen for replies for %ld.%09ld sec\n", |
| (long)ts.tv_sec, (long)ts.tv_nsec); |
(long)ts.tv_sec, (long)ts.tv_nsec); |
| } |
} |
| |
|
|
Line 914 ping_recv(pcap_t *pcap, uint32_t packetwait, pcap_hand
|
Line 1229 ping_recv(pcap_t *pcap, uint32_t packetwait, pcap_hand
|
| r = select(fd + 1, &fds, NULL, NULL, &tv); |
r = select(fd + 1, &fds, NULL, NULL, &tv); |
| switch (r) { |
switch (r) { |
| case 0: /* timeout */ |
case 0: /* timeout */ |
| if (display == NORMAL) { | if (numrecvd == old_received) { |
| if (numrecvd == old_received) { | if (reverse_beep) { |
| | printf("\a"); |
| | } |
| | switch (display) { |
| | case NORMAL: |
| printf("Timeout\n"); |
printf("Timeout\n"); |
| |
break; |
| |
case DOT: |
| |
printf("."); |
| |
break; |
| } |
} |
| |
fflush(stdout); |
| } |
} |
| done = 1; |
done = 1; |
| break; |
break; |
|
Line 977 int main(int argc, char **argv)
|
Line 1301 int main(int argc, char **argv)
|
| pcap_t *pcap; |
pcap_t *pcap; |
| enum { NONE, PINGMAC, PINGIP } mode = NONE; |
enum { NONE, PINGMAC, PINGIP } mode = NONE; |
| unsigned int packetwait = 1000000; |
unsigned int packetwait = 1000000; |
| |
ebuf[0] = 0; |
| |
|
| for (c = 1; c < argc; c++) { |
for (c = 1; c < argc; c++) { |
| if (!strcmp(argv[c], "--help")) { |
if (!strcmp(argv[c], "--help")) { |
|
Line 990 int main(int argc, char **argv)
|
Line 1315 int main(int argc, char **argv)
|
| dstip = 0xffffffff; |
dstip = 0xffffffff; |
| memcpy(dstmac, ethxmas, ETH_ALEN); |
memcpy(dstmac, ethxmas, ETH_ALEN); |
| |
|
| while (EOF!=(c=getopt(argc,argv,"0aAbBc:dDeFhi:I:pqrRs:S:t:T:uUvw:"))) { | while (EOF != (c = getopt(argc, argv, |
| | "0aAbBC:c:dDeFhi:I:m:pPqrRs:S:t:T:uUvw:W:"))) { |
| switch(c) { |
switch(c) { |
| case '0': |
case '0': |
| srcip = 0; |
srcip = 0; |
|
Line 1013 int main(int argc, char **argv)
|
Line 1339 int main(int argc, char **argv)
|
| case 'c': |
case 'c': |
| maxcount = atoi(optarg); |
maxcount = atoi(optarg); |
| break; |
break; |
| |
case 'C': |
| |
max_replies = atoi(optarg); |
| |
break; |
| case 'd': |
case 'd': |
| finddup = 1; |
finddup = 1; |
| break; |
break; |
|
Line 1040 int main(int argc, char **argv)
|
Line 1369 int main(int argc, char **argv)
|
| case 'I': /* FALL THROUGH */ |
case 'I': /* FALL THROUGH */ |
| ifname = optarg; |
ifname = optarg; |
| break; |
break; |
| |
case 'm': |
| |
timestamp_type = optarg; |
| |
break; |
| case 'p': |
case 'p': |
| promisc = 1; |
promisc = 1; |
| break; |
break; |
| |
case 'P': |
| |
send_reply = 1; |
| |
break; |
| case 'q': |
case 'q': |
| display = QUIET; |
display = QUIET; |
| break; |
break; |
|
Line 1068 int main(int argc, char **argv)
|
Line 1403 int main(int argc, char **argv)
|
| break; |
break; |
| } |
} |
| case 'S': /* set source IP, may be null for don't-know */ |
case 'S': /* set source IP, may be null for don't-know */ |
| do_libnet_init(ifname); | do_libnet_init(ifname, 0); |
| if (-1 == (srcip = libnet_name2addr4(libnet, |
if (-1 == (srcip = libnet_name2addr4(libnet, |
| optarg, |
optarg, |
| LIBNET_RESOLVE))){ |
LIBNET_RESOLVE))){ |
|
Line 1105 int main(int argc, char **argv)
|
Line 1440 int main(int argc, char **argv)
|
| "in MAC ping mode\n"); |
"in MAC ping mode\n"); |
| exit(1); |
exit(1); |
| } |
} |
| do_libnet_init(ifname); | do_libnet_init(ifname, 0); |
| if (-1 == (dstip = libnet_name2addr4(libnet, |
if (-1 == (dstip = libnet_name2addr4(libnet, |
| optarg, |
optarg, |
| LIBNET_RESOLVE))){ |
LIBNET_RESOLVE))){ |
|
Line 1133 int main(int argc, char **argv)
|
Line 1468 int main(int argc, char **argv)
|
| case 'w': |
case 'w': |
| packetwait = (unsigned)atoi(optarg); |
packetwait = (unsigned)atoi(optarg); |
| break; |
break; |
| |
case 'W': |
| |
packetwait = (unsigned)(1000000.0 * atof(optarg)); |
| |
break; |
| default: |
default: |
| usage(1); |
usage(1); |
| } |
} |
|
Line 1142 int main(int argc, char **argv)
|
Line 1480 int main(int argc, char **argv)
|
| #if HAVE_CLOCK_MONOTONIC |
#if HAVE_CLOCK_MONOTONIC |
| struct timespec ts; |
struct timespec ts; |
| clock_getres(CLOCK_MONOTONIC, &ts); |
clock_getres(CLOCK_MONOTONIC, &ts); |
| printf("clock_getres() = %ld %ld\n", | printf("arping: clock_getres() = %ld %ld\n", |
| (long)ts.tv_sec, (long)ts.tv_nsec); |
(long)ts.tv_sec, (long)ts.tv_nsec); |
| #else |
#else |
| printf("Using gettimeofday() for time measurements\n"); | printf("arping: Using gettimeofday() for time measurements\n"); |
| #endif |
#endif |
| } |
} |
| |
|
|
Line 1162 int main(int argc, char **argv)
|
Line 1500 int main(int argc, char **argv)
|
| /* default to own IP address when doing -d */ |
/* default to own IP address when doing -d */ |
| if (finddup && !parm) { |
if (finddup && !parm) { |
| dstip_given = 1; |
dstip_given = 1; |
| do_libnet_init(ifname); | do_libnet_init(ifname, 0); |
| dstip = libnet_get_ipaddr4(libnet); |
dstip = libnet_get_ipaddr4(libnet); |
| if (verbose) { |
if (verbose) { |
| printf("defaulting to checking dup for %s\n", |
printf("defaulting to checking dup for %s\n", |
|
Line 1178 int main(int argc, char **argv)
|
Line 1516 int main(int argc, char **argv)
|
| mode = is_mac_addr(parm)?PINGMAC:PINGIP; |
mode = is_mac_addr(parm)?PINGMAC:PINGIP; |
| } else if (dstip_given) { |
} else if (dstip_given) { |
| mode = PINGIP; |
mode = PINGIP; |
| do_libnet_init(ifname); | do_libnet_init(ifname, 0); |
| parm = strdup(libnet_addr2name4(dstip,0)); |
parm = strdup(libnet_addr2name4(dstip,0)); |
| if (!parm) { |
if (!parm) { |
| fprintf(stderr, "arping: out of mem\n"); |
fprintf(stderr, "arping: out of mem\n"); |
|
Line 1201 int main(int argc, char **argv)
|
Line 1539 int main(int argc, char **argv)
|
| /* |
/* |
| * libnet init (may be done already for resolving) |
* libnet init (may be done already for resolving) |
| */ |
*/ |
| do_libnet_init(ifname); | do_libnet_init(ifname, 0); |
| | |
| /* |
/* |
| * Make sure dstip and parm like eachother |
* Make sure dstip and parm like eachother |
| */ |
*/ |
|
Line 1259 int main(int argc, char **argv)
|
Line 1597 int main(int argc, char **argv)
|
| if (!ifname) { |
if (!ifname) { |
| if (!dont_use_arping_lookupdev) { |
if (!dont_use_arping_lookupdev) { |
| ifname = arping_lookupdev(srcip, dstip, ebuf); |
ifname = arping_lookupdev(srcip, dstip, ebuf); |
| |
strip_newline(ebuf); |
| |
if (!ifname) { |
| |
fprintf(stderr, "arping: lookup dev: %s\n", |
| |
ebuf); |
| |
} |
| } |
} |
| if (!ifname) { |
if (!ifname) { |
| ifname = arping_lookupdev_default(srcip, dstip, ebuf); |
ifname = arping_lookupdev_default(srcip, dstip, ebuf); |
| if (!dont_use_arping_lookupdev) { | strip_newline(ebuf); |
| | if (ifname && !dont_use_arping_lookupdev) { |
| fprintf(stderr, |
fprintf(stderr, |
| "arping: Unable to automatically find " |
"arping: Unable to automatically find " |
| "interface to use. Is it on the local " |
"interface to use. Is it on the local " |
|
Line 1291 int main(int argc, char **argv)
|
Line 1635 int main(int argc, char **argv)
|
| * Init libnet again, because we now know the interface name. |
* Init libnet again, because we now know the interface name. |
| * We should know it by know at least |
* We should know it by know at least |
| */ |
*/ |
| do_libnet_init(ifname); | do_libnet_init(ifname, 0); |
| |
|
| /* |
/* |
| * pcap init |
* pcap init |
| */ |
*/ |
| if (!(pcap = do_pcap_open_live(ifname, 100, promisc, 10, ebuf))) { |
if (!(pcap = do_pcap_open_live(ifname, 100, promisc, 10, ebuf))) { |
| fprintf(stderr, "arping: pcap_open_live(): %s\n",ebuf); | strip_newline(ebuf); |
| | fprintf(stderr, "arping: pcap_open_live(): %s\n", ebuf); |
| exit(1); |
exit(1); |
| } |
} |
| |
drop_privileges(); |
| if (pcap_setnonblock(pcap, 1, ebuf)) { |
if (pcap_setnonblock(pcap, 1, ebuf)) { |
| |
strip_newline(ebuf); |
| fprintf(stderr, "arping: pcap_set_nonblock(): %s\n", ebuf); |
fprintf(stderr, "arping: pcap_set_nonblock(): %s\n", ebuf); |
| exit(1); |
exit(1); |
| } |
} |
| if (verbose > 1) { |
if (verbose > 1) { |
| printf("pcap_get_selectable_fd(): %d\n", | printf("arping: pcap_get_selectable_fd(): %d\n", |
| pcap_get_selectable_fd(pcap)); |
pcap_get_selectable_fd(pcap)); |
| } |
} |
| |
|
| #ifdef BIOCIMMEDIATE |
#ifdef BIOCIMMEDIATE |
| { |
{ |
| |
// This may be redundant if pcap_set_immediate_mode() is present. |
| uint32_t on = 1; |
uint32_t on = 1; |
| if (0 < (ioctl(pcap_fileno(pcap), BIOCIMMEDIATE, |
if (0 < (ioctl(pcap_fileno(pcap), BIOCIMMEDIATE, |
| &on))) { |
&on))) { |
|
Line 1364 int main(int argc, char **argv)
|
Line 1712 int main(int argc, char **argv)
|
| do_signal_init(); |
do_signal_init(); |
| |
|
| if (verbose) { |
if (verbose) { |
| printf("This box: Interface: %s IP: %s MAC address: ", | char buf[128]; |
| ifname, libnet_addr2name4(libnet_get_ipaddr4(libnet), | printf("This box: Interface: %s IP: %s MAC address: %s\n", |
| 0)); | ifname, |
| for (c = 0; c < ETH_ALEN - 1; c++) { | libnet_addr2name4(libnet_get_ipaddr4(libnet), 0), |
| printf("%.2x:", (uint8_t)srcmac[c]); | format_mac(srcmac, buf, sizeof(buf))); |
| } | |
| printf("%.2x\n", (uint8_t)srcmac[ETH_ALEN - 1]); | |
| } |
} |
| |
|
| |
|
|
Line 1389 int main(int argc, char **argv)
|
Line 1735 int main(int argc, char **argv)
|
| r = numrecvd; |
r = numrecvd; |
| ping_recv(pcap,packetwait, |
ping_recv(pcap,packetwait, |
| (pcap_handler)pingip_recv); |
(pcap_handler)pingip_recv); |
| if (reverse_beep && !time_to_die && (r == numrecvd)) { |
|
| printf("\a"); |
|
| fflush(stdout); |
|
| } |
|
| } |
} |
| } else { /* PINGMAC */ |
} else { /* PINGMAC */ |
| unsigned int c; |
unsigned int c; |
|
Line 1402 int main(int argc, char **argv)
|
Line 1744 int main(int argc, char **argv)
|
| r = numrecvd; |
r = numrecvd; |
| ping_recv(pcap,packetwait, |
ping_recv(pcap,packetwait, |
| (pcap_handler)pingmac_recv); |
(pcap_handler)pingmac_recv); |
| if (reverse_beep && !time_to_die && (r == numrecvd)) { |
|
| printf("\a"); |
|
| fflush(stdout); |
|
| } |
|
| } |
} |
| } |
} |
| if (display == DOT) { |
if (display == DOT) { |
| count_missing_dots(); | const float succ = 100.0 - 100.0 * (float)(numrecvd)/(float)numsent; |
| printf("\t%3.0f%% packet loss\n", | printf("\t%3.0f%% packet loss (%d extra)\n", |
| 100.0 - 100.0 * (float)(numrecvd)/(float)numsent); | (succ < 0.0) ? 0.0 : succ, |
| | (succ < 0.0) ? (numrecvd - numsent) : 0); |
| } else if (display == NORMAL) { |
} else if (display == NORMAL) { |
| float succ; | const float succ = 100.0 - 100.0 * (float)(numrecvd)/(float)numsent; |
| succ = 100.0 - 100.0 * (float)(numrecvd)/(float)numsent; | |
| printf("\n--- %s statistics ---\n" |
printf("\n--- %s statistics ---\n" |
| "%d packets transmitted, " |
"%d packets transmitted, " |
| "%d packets received, " |
"%d packets received, " |