Prefer ip command from iproute2 over ifconfig

On Linux systems, `ifconfig` is long deprecated in favor of the `ip`
command from iproute2. Some systems don't have iproute2 (BSDs in
particular), so ddclient will still attempt `ifconfig` if `ip` is
missing.

Also: Don't hide STDERR because error messages are important for
troubleshooting problems. To avoid STDERR noise on systems without the
`ip` command, the command's existence is checked before it is run.

Notes:
  * The fetched addresses could be limited to IPv4 or IPv6 depending
    on `opt('ipv6')`, and non-global addresses could be filtered out,
    but any filtering risks breaking a nontrivial number of existing
    configurations.
  * This change runs the risk of breaking existing configs that set
    `if-skip`. Due to the deprecation of `ifconfig`, and the belief
    that only a negligible number of users set `if-skip`, the benefits
    of this change are believed to outweigh the config migration
    burden imposed on users.

Fixes #93.
This commit is contained in:
Richard Hansen 2020-06-11 17:09:46 -04:00
parent 20429c1199
commit e3a6cbf1b6
2 changed files with 15 additions and 5 deletions

View file

@ -12,6 +12,9 @@ repository history](https://github.com/ddclient/ddclient/commits/master).
### Compatibility changes
* Perl v5.10.1 or later is now required.
* When `use=if`, iproute2's `ip` command is now attempted before falling back
to `ifconfig` (it used to be the other way around). If you set `if-skip`,
please check that your configuration still works as expected.
* Removed the `concont` protocol. If you still use this protocol, please
[file a bug report](https://github.com/ddclient/ddclient/issues) and we
will restore it.

View file

@ -754,7 +754,7 @@ my @opt = (
[ "ip", "=s", "-ip address : set the IP address to 'address'" ],
"",
[ "if", "=s", "-if interface : obtain IP address from 'interface'" ],
[ "if-skip", "=s", "-if-skip pattern : skip any IP addresses before 'pattern' in the output of ifconfig {if}" ],
[ "if-skip", "=s", "-if-skip pattern : skip any IP addresses before 'pattern' in the output of 'ip address show dev {if}' (or 'ifconfig {if}')" ],
"",
[ "web", "=s", "-web provider|url : obtain IP address from provider's IP checking page" ],
[ "web-skip", "=s", "-web-skip pattern : skip any IP addresses before 'pattern' on the web provider|url" ],
@ -1477,8 +1477,15 @@ sub test_possible_ip {
{
local $opt{'use'} = 'if';
foreach my $if (grep {/^[a-zA-Z]/} `ifconfig -a`) {
$if =~ s/:?\s.*//is;
# Note: The `ip` command adds a `@eth0` suffix to the names of VLAN
# interfaces. That `@eth0` suffix is NOT part of the interface name.
my @ifs = map({ /^[^\s:]*:\s*([^\s:@]+)/ ? $1 : () }
`command -v ip >/dev/null && ip -o link show`);
@ifs = map({ /^([a-zA-Z].*?)(?::?\s.*)?$/ ? $1 : () }
`command -v ifconfig >/dev/null && ifconfig -a`) if $? || !@ifs;
@ifs = () if $?;
warning("failed to get list of interfaces") if !@ifs;
foreach my $if (@ifs) {
local $opt{'if'} = $if;
printf "use=if, if=%s address is %s\n", opt('if'), define(get_ip('if'), 'NOT FOUND');
}
@ -2201,8 +2208,8 @@ sub get_ip {
} elsif ($use eq 'if') {
$skip = opt('if-skip', $h) || '';
$reply = `ifconfig $arg 2> /dev/null`;
$reply = `ip addr list dev $arg 2> /dev/null` if $?;
$reply = `command -v ip >/dev/null && ip address show dev $arg`;
$reply = `command -v ifconfig >/dev/null && ifconfig $arg` if $?;
$reply = '' if $?;
} elsif ($use eq 'cmd') {