Add --fwmark/-k option for Linux

pull/293/head
deepkv 11 months ago committed by David Schweikert
parent a3f4c573bf
commit c8e9632150

@ -28,13 +28,14 @@ If you want to install fping from source, proceed as follows:
(see: `./configure --help`) (see: `./configure --help`)
2. Run `make; make install`. 2. Run `make; make install`.
3. Make fping either setuid, or, if under Linux: 3. Make fping either setuid, or, if under Linux:
`sudo setcap cap_net_raw+ep fping` `sudo setcap cap_net_raw,cap_net_admin+ep fping`
If you can't run fping as root or can't use the cap_net_raw capability, you can If you can't run fping as root or can't use the cap_net_raw capability, you can
also run fping in unprivileged mode. This works on MacOS and also on Linux, also run fping in unprivileged mode. This works on MacOS and also on Linux,
provided that your GID is included in the range defined in provided that your GID is included in the range defined in
`/proc/sys/net/ipv4/ping_group_range`. This is particularly useful for running `/proc/sys/net/ipv4/ping_group_range`. This is particularly useful for running
fping in rootless / unprivileged containers. fping in rootless / unprivileged containers. The --fwmark option needs root or
cap_net_admin. setuid will not work for --fwmark.
## Usage ## Usage

@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
sudo setcap cap_net_raw+ep src/fping sudo setcap cap_net_raw,cap_net_admin+ep src/fping
if [[ ! $PATH =~ fping/src ]]; then if [[ ! $PATH =~ fping/src ]]; then
PATH=/home/dws/checkouts/fping/src:$PATH PATH=/home/dws/checkouts/fping/src:$PATH

@ -1,10 +1,11 @@
#!/usr/bin/perl -w #!/usr/bin/perl -w
use Test::Command tests => 9; use Test::Command tests => 12;
use Test::More; use Test::More;
# -i n interval between sending ping packets (in millisec) (default 25) # -i n interval between sending ping packets (in millisec) (default 25)
# -l loop sending pings forever # -l loop sending pings forever
# -k set fwmark on ping packets
# -m ping multiple interfaces on target host # -m ping multiple interfaces on target host
# -M don't fragment # -M don't fragment
@ -24,6 +25,17 @@ $cmd->stdout_like(qr{127\.0\.0\.1 : \[0\], 64 bytes, \d\.\d+ ms \(\d\.\d+ avg, 0
}); });
} }
# fping -k
SKIP: {
if($^O ne 'linux') {
skip '-k option is only supported on Linux', 3;
}
my $cmd = Test::Command->new(cmd => 'sudo env "PATH=$PATH" fping -k 256 127.0.0.1');
$cmd->exit_is_num(0);
$cmd->stdout_is_eq("127.0.0.1 is alive\n");
$cmd->stderr_is_eq("");
}
# fping -l with SIGQUIT # fping -l with SIGQUIT
{ {
my $cmd = Test::Command->new(cmd => '(sleep 2; pkill -QUIT fping; sleep 2; pkill fping)& fping -p 900 -l 127.0.0.1'); my $cmd = Test::Command->new(cmd => '(sleep 2; pkill -QUIT fping; sleep 2; pkill fping)& fping -p 900 -l 127.0.0.1');

@ -54,8 +54,8 @@ rm -rf $RPM_BUILD_ROOT
%post %post
if [ -x /usr/sbin/setcap ]; then if [ -x /usr/sbin/setcap ]; then
/bin/chmod 0755 /usr/sbin/fping* /bin/chmod 0755 /usr/sbin/fping*
/usr/sbin/setcap cap_net_raw+ep /usr/sbin/fping /usr/sbin/setcap cap_net_raw,cap_net_admin+ep /usr/sbin/fping
/usr/sbin/setcap cap_net_raw+ep /usr/sbin/fping6 /usr/sbin/setcap cap_net_raw,cap_net_admin+ep /usr/sbin/fping6
fi fi
%changelog %changelog

@ -130,6 +130,11 @@ to any target (default is 10, minimum is 1).
Set the interface (requires SO_BINDTODEVICE support). Set the interface (requires SO_BINDTODEVICE support).
=item B<-k>, B<--fwmark>=I<FWMARK>
Set FWMARK on ping packets for policy-based routing. Requires Linux kernel
2.6.25<=, and root privileges or cap_net_admin.
=item B<-l>, B<--loop> =item B<-l>, B<--loop>
Loop sending packets to each target indefinitely. Can be interrupted with Loop sending packets to each target indefinitely. Can be interrupted with

@ -363,6 +363,8 @@ int randomly_lose_flag, trace_flag, print_per_system_flag;
int lose_factor; int lose_factor;
#endif /* DEBUG || _DEBUG */ #endif /* DEBUG || _DEBUG */
unsigned int fwmark = 0;
char *filename = NULL; /* file containing hosts to ping */ char *filename = NULL; /* file containing hosts to ping */
/*** forward declarations ***/ /*** forward declarations ***/
@ -518,6 +520,9 @@ int main(int argc, char **argv)
{ "ttl", 'H', OPTPARSE_REQUIRED }, { "ttl", 'H', OPTPARSE_REQUIRED },
{ "interval", 'i', OPTPARSE_REQUIRED }, { "interval", 'i', OPTPARSE_REQUIRED },
{ "iface", 'I', OPTPARSE_REQUIRED }, { "iface", 'I', OPTPARSE_REQUIRED },
#ifdef SO_MARK
{ "fwmark", 'k', OPTPARSE_REQUIRED },
#endif
{ "loop", 'l', OPTPARSE_NONE }, { "loop", 'l', OPTPARSE_NONE },
{ "all", 'm', OPTPARSE_NONE }, { "all", 'm', OPTPARSE_NONE },
{ "dontfrag", 'M', OPTPARSE_NONE }, { "dontfrag", 'M', OPTPARSE_NONE },
@ -761,6 +766,23 @@ int main(int argc, char **argv)
case 'f': case 'f':
filename = optparse_state.optarg; filename = optparse_state.optarg;
break; break;
#ifdef SO_MARK
case 'k':
if (!(fwmark = (unsigned int)atol(optparse_state.optarg)))
usage(1);
if (socket4 >= 0)
if(-1 == setsockopt(socket4, SOL_SOCKET, SO_MARK, &fwmark, sizeof fwmark))
perror("fwmark ipv4");
#ifdef IPV6
if (socket6 >= 0)
if(-1 == setsockopt(socket6, SOL_SOCKET, SO_MARK, &fwmark, sizeof fwmark))
perror("fwmark ipv6");
#endif
break;
#endif
case 'g': case 'g':
/* use IP list generation */ /* use IP list generation */
@ -2923,6 +2945,9 @@ void usage(int is_error)
fprintf(out, " -H, --ttl=N set the IP TTL value (Time To Live hops)\n"); fprintf(out, " -H, --ttl=N set the IP TTL value (Time To Live hops)\n");
#ifdef SO_BINDTODEVICE #ifdef SO_BINDTODEVICE
fprintf(out, " -I, --iface=IFACE bind to a particular interface\n"); fprintf(out, " -I, --iface=IFACE bind to a particular interface\n");
#endif
#ifdef SO_MARK
fprintf(out, " -k, --fwmark=FWMARK set the routing mark\n");
#endif #endif
fprintf(out, " -l, --loop loop mode: send pings forever\n"); fprintf(out, " -l, --loop loop mode: send pings forever\n");
fprintf(out, " -m, --all use all IPs of provided hostnames (e.g. IPv4 and IPv6), use with -A\n"); fprintf(out, " -m, --all use all IPs of provided hostnames (e.g. IPv4 and IPv6), use with -A\n");

Loading…
Cancel
Save