shill: OpenVPNDriver: Work around netmask in remote
In some OpenVPN configurations, the netmask is sent in the
"ifconfig_remote" argument instead of "ifconfig_netmask" where it
should be. Work around this by examining the content of the address.
Precedent for this processing can be found in other connection
managers, for example
https://mail.gnome.org/archives/commits-list/2009-July/msg03401.html
BUG=chromium:241264
TEST=Unit tests
Change-Id: I15c9746e8af528c357eec023327a6375e8dc2599
Reviewed-on: https://gerrit.chromium.org/gerrit/51529
Commit-Queue: Paul Stewart <pstew@chromium.org>
Reviewed-by: Paul Stewart <pstew@chromium.org>
Tested-by: Paul Stewart <pstew@chromium.org>
diff --git a/openvpn_driver.cc b/openvpn_driver.cc
index 27662cc..bdb186f 100644
--- a/openvpn_driver.cc
+++ b/openvpn_driver.cc
@@ -60,6 +60,12 @@
const char kOpenVPNVerbProperty[] = "OpenVPN.Verb";
const char kVPNMTUProperty[] = "VPN.MTU";
+// Some configurations pass the netmask in the ifconfig_remote property.
+// This is due to some servers not explicitly indicating that they are using
+// a "broadcast mode" network instead of peer-to-peer. See
+// http://crbug.com/241264 for an example of this issue.
+const char kSuspectedNetmaskPrefix[] = "255.";
+
} // namespace
// TODO(petkov): Move to chromeos/dbus/service_constants.h.
@@ -354,7 +360,21 @@
properties->subnet_prefix =
IPAddress::GetPrefixLengthFromMask(properties->address_family, value);
} else if (LowerCaseEqualsASCII(key, kOpenVPNIfconfigRemote)) {
- properties->peer_address = value;
+ if (StartsWithASCII(value, kSuspectedNetmaskPrefix, false)) {
+ LOG(WARNING) << "Option " << key << " value " << value
+ << " looks more like a netmask than a peer address; "
+ << "assuming it is the former.";
+ // In this situation, the "peer_address" value will be left
+ // unset and Connection::UpdateFromIPConfig() will treat the
+ // interface as if it were a broadcast-style network. The
+ // kernel will, automatically set the peer address equal to
+ // the local address.
+ properties->subnet_prefix =
+ IPAddress::GetPrefixLengthFromMask(properties->address_family,
+ value);
+ } else {
+ properties->peer_address = value;
+ }
} else if (LowerCaseEqualsASCII(key, kOpenVPNRouteVPNGateway)) {
properties->gateway = value;
} else if (LowerCaseEqualsASCII(key, kOpenVPNTrustedIP)) {
diff --git a/openvpn_driver_unittest.cc b/openvpn_driver_unittest.cc
index 2bfa153..1221c37 100644
--- a/openvpn_driver_unittest.cc
+++ b/openvpn_driver_unittest.cc
@@ -509,6 +509,13 @@
OpenVPNDriver::ParseIPConfiguration(config, &props);
EXPECT_EQ(18, props.subnet_prefix);
+ // An "ifconfig_remote" parameter that looks like a netmask should be
+ // applied to the subnet prefix instead of to the peer address.
+ config["ifconfig_remotE"] = "255.255.0.0";
+ OpenVPNDriver::ParseIPConfiguration(config, &props);
+ EXPECT_EQ(16, props.subnet_prefix);
+ EXPECT_EQ("", props.peer_address);
+
config["ifconfig_loCal"] = "4.5.6.7";
config["ifconfiG_broadcast"] = "1.2.255.255";
config["ifconFig_netmAsk"] = "255.255.255.0";