shill: rtnl: Handle setting of peer address
Bonus changes: Rename "subnet_cidr" to "subnet_prefix". Set a default
subnet prefix for OpenVPNDriver IPConfigs.
BUG=chromium-os:28003
TEST=Unit tests.
Change-Id: I953748b3ecb1a45237cedc18482c647eebe27efa
Reviewed-on: https://gerrit.chromium.org/gerrit/18461
Reviewed-by: Darin Petkov <petkov@chromium.org>
Tested-by: Paul Stewart <pstew@chromium.org>
Commit-Ready: Paul Stewart <pstew@chromium.org>
diff --git a/connection.cc b/connection.cc
index bdec018..cb1012b 100644
--- a/connection.cc
+++ b/connection.cc
@@ -56,7 +56,7 @@
LOG(ERROR) << "Local address " << properties.address << " is invalid";
return;
}
- local.set_prefix(properties.subnet_cidr);
+ local.set_prefix(properties.subnet_prefix);
IPAddress broadcast(properties.address_family);
if (!broadcast.SetAddressFromString(properties.broadcast_address) &&
@@ -66,7 +66,15 @@
return;
}
- rtnl_handler_->AddInterfaceAddress(interface_index_, local, broadcast);
+ IPAddress peer(properties.address_family);
+ if (!properties.peer_address.empty() &&
+ !peer.SetAddressFromString(properties.peer_address)) {
+ LOG(ERROR) << "Peer address " << properties.peer_address
+ << " is invalid";
+ return;
+ }
+
+ rtnl_handler_->AddInterfaceAddress(interface_index_, local, broadcast, peer);
routing_table_->SetDefaultRoute(interface_index_, config,
GetMetric(is_default_));
diff --git a/connection_unittest.cc b/connection_unittest.cc
index 728f347..0aeae1e 100644
--- a/connection_unittest.cc
+++ b/connection_unittest.cc
@@ -104,7 +104,7 @@
TEST_F(ConnectionTest, AddConfig) {
EXPECT_CALL(rtnl_handler_,
- AddInterfaceAddress(kTestDeviceInterfaceIndex0, _, _));
+ AddInterfaceAddress(kTestDeviceInterfaceIndex0, _, _, _));
EXPECT_CALL(routing_table_,
SetDefaultRoute(kTestDeviceInterfaceIndex0,
ipconfig_,
@@ -165,7 +165,7 @@
connection_->SetIsDefault(true);
EXPECT_CALL(rtnl_handler_,
- AddInterfaceAddress(kTestDeviceInterfaceIndex0, _, _));
+ AddInterfaceAddress(kTestDeviceInterfaceIndex0, _, _, _));
EXPECT_CALL(routing_table_, SetDefaultRoute(kTestDeviceInterfaceIndex0,
ipconfig_,
Connection::kDefaultMetric));
diff --git a/dhcp_config.cc b/dhcp_config.cc
index ec74ff4..2511e2f 100644
--- a/dhcp_config.cc
+++ b/dhcp_config.cc
@@ -245,7 +245,7 @@
return false;
}
} else if (key == kConfigurationKeySubnetCIDR) {
- properties->subnet_cidr = value.reader().get_byte();
+ properties->subnet_prefix = value.reader().get_byte();
} else if (key == kConfigurationKeyBroadcastAddress) {
properties->broadcast_address =
GetIPv4AddressString(value.reader().get_uint32());
diff --git a/dhcp_config_unittest.cc b/dhcp_config_unittest.cc
index aa853b1..db6ca29 100644
--- a/dhcp_config_unittest.cc
+++ b/dhcp_config_unittest.cc
@@ -133,7 +133,7 @@
IPConfig::Properties properties;
ASSERT_TRUE(config_->ParseConfiguration(conf, &properties));
EXPECT_EQ("4.3.2.1", properties.address);
- EXPECT_EQ(16, properties.subnet_cidr);
+ EXPECT_EQ(16, properties.subnet_prefix);
EXPECT_EQ("64.48.32.16", properties.broadcast_address);
EXPECT_EQ("8.6.4.2", properties.gateway);
ASSERT_EQ(2, properties.dns_servers.size());
diff --git a/ip_address.cc b/ip_address.cc
index a6ae127..1e36d55 100644
--- a/ip_address.cc
+++ b/ip_address.cc
@@ -62,16 +62,21 @@
}
// static
+size_t IPAddress::GetMaxPrefixLength(Family family) {
+ return GetAddressLength(family) * 8;
+}
+
+// static
size_t IPAddress::GetPrefixLengthFromMask(Family family, const string &mask) {
switch (family) {
case kFamilyIPv4: {
in_addr_t mask_val = inet_network(mask.c_str());
- int subnet_cidr = 0;
+ int subnet_prefix = 0;
while (mask_val) {
- subnet_cidr++;
+ subnet_prefix++;
mask_val <<= 1;
}
- return subnet_cidr;
+ return subnet_prefix;
}
case kFamilyIPv6:
NOTIMPLEMENTED();
diff --git a/ip_address.h b/ip_address.h
index df872c7..d69f896 100644
--- a/ip_address.h
+++ b/ip_address.h
@@ -42,6 +42,10 @@
// Get the length in bytes of addresses of the given family
static size_t GetAddressLength(Family family);
+ // Returns the maximum prefix length for address family |family|, i.e.,
+ // the length of this address type in bits.
+ static size_t GetMaxPrefixLength(Family family);
+
// Returns the prefix length given an address |family| and a |mask|. For
// example, returns 24 for an IPv4 mask 255.255.255.0.
static size_t GetPrefixLengthFromMask(Family family, const std::string &mask);
diff --git a/ipconfig.cc b/ipconfig.cc
index ed28ba1..489f326 100644
--- a/ipconfig.cc
+++ b/ipconfig.cc
@@ -58,7 +58,8 @@
&properties_.dns_servers);
store_.RegisterString(flimflam::kPeerAddressProperty,
&properties_.peer_address);
- store_.RegisterInt32(flimflam::kPrefixlenProperty, &properties_.subnet_cidr);
+ store_.RegisterInt32(flimflam::kPrefixlenProperty,
+ &properties_.subnet_prefix);
// TODO(cmasone): Does anyone use this?
// store_.RegisterStrings(flimflam::kSearchDomainsProperty,
// &properties_.domain_search);
diff --git a/ipconfig.h b/ipconfig.h
index e0f8340..4d341e4 100644
--- a/ipconfig.h
+++ b/ipconfig.h
@@ -37,12 +37,12 @@
struct Properties {
Properties() : address_family(IPAddress::kFamilyUnknown),
- subnet_cidr(0),
+ subnet_prefix(0),
mtu(0) {}
IPAddress::Family address_family;
std::string address;
- int32 subnet_cidr;
+ int32 subnet_prefix;
std::string broadcast_address;
std::vector<std::string> dns_servers;
std::string domain_name;
diff --git a/ipconfig_unittest.cc b/ipconfig_unittest.cc
index 832285e..16051cb 100644
--- a/ipconfig_unittest.cc
+++ b/ipconfig_unittest.cc
@@ -71,7 +71,7 @@
TEST_F(IPConfigTest, UpdateProperties) {
IPConfig::Properties properties;
properties.address = "1.2.3.4";
- properties.subnet_cidr = 24;
+ properties.subnet_prefix = 24;
properties.broadcast_address = "11.22.33.44";
properties.gateway = "5.6.7.8";
properties.dns_servers.push_back("10.20.30.40");
@@ -82,7 +82,7 @@
properties.mtu = 700;
ipconfig_->UpdateProperties(properties, true);
EXPECT_EQ("1.2.3.4", ipconfig_->properties().address);
- EXPECT_EQ(24, ipconfig_->properties().subnet_cidr);
+ EXPECT_EQ(24, ipconfig_->properties().subnet_prefix);
EXPECT_EQ("11.22.33.44", ipconfig_->properties().broadcast_address);
EXPECT_EQ("5.6.7.8", ipconfig_->properties().gateway);
ASSERT_EQ(2, ipconfig_->properties().dns_servers.size());
diff --git a/mock_rtnl_handler.h b/mock_rtnl_handler.h
index f630b75..a5b14c4 100644
--- a/mock_rtnl_handler.h
+++ b/mock_rtnl_handler.h
@@ -25,9 +25,10 @@
MOCK_METHOD3(SetInterfaceFlags, void(int interface_index,
unsigned int flags,
unsigned int change));
- MOCK_METHOD3(AddInterfaceAddress, bool(int interface_index,
+ MOCK_METHOD4(AddInterfaceAddress, bool(int interface_index,
const IPAddress &local,
- const IPAddress &broadcast));
+ const IPAddress &broadcast,
+ const IPAddress &peer));
MOCK_METHOD2(RemoveInterfaceAddress, bool(int interface_index,
const IPAddress &local));
MOCK_METHOD1(RequestDump, void(int request_flags));
diff --git a/openvpn_driver.cc b/openvpn_driver.cc
index 6bcddde..990c74a 100644
--- a/openvpn_driver.cc
+++ b/openvpn_driver.cc
@@ -183,6 +183,8 @@
ForeignOptions foreign_options;
RouteOptions routes;
properties->address_family = IPAddress::kFamilyIPv4;
+ properties->subnet_prefix = IPAddress::GetMaxPrefixLength(
+ properties->address_family);
for (map<string, string>::const_iterator it = configuration.begin();
it != configuration.end(); ++it) {
const string &key = it->first;
@@ -193,7 +195,7 @@
} else if (LowerCaseEqualsASCII(key, kOpenVPNIfconfigBroadcast)) {
properties->broadcast_address = value;
} else if (LowerCaseEqualsASCII(key, kOpenVPNIfconfigNetmask)) {
- properties->subnet_cidr =
+ properties->subnet_prefix =
IPAddress::GetPrefixLengthFromMask(properties->address_family, value);
} else if (LowerCaseEqualsASCII(key, kOpenVPNIfconfigRemote)) {
properties->peer_address = value;
diff --git a/openvpn_driver_unittest.cc b/openvpn_driver_unittest.cc
index 2b087a6..6e39ea6 100644
--- a/openvpn_driver_unittest.cc
+++ b/openvpn_driver_unittest.cc
@@ -289,7 +289,7 @@
EXPECT_EQ(IPAddress::kFamilyIPv4, props.address_family);
EXPECT_EQ("4.5.6.7", props.address);
EXPECT_EQ("1.2.255.255", props.broadcast_address);
- EXPECT_EQ(24, props.subnet_cidr);
+ EXPECT_EQ(24, props.subnet_prefix);
EXPECT_EQ("33.44.55.66", props.peer_address);
EXPECT_EQ("192.168.1.1", props.gateway);
EXPECT_EQ("99.88.77.66", props.trusted_ip);
diff --git a/rtnl_handler.cc b/rtnl_handler.cc
index 0ab508b..8936c94 100644
--- a/rtnl_handler.cc
+++ b/rtnl_handler.cc
@@ -268,8 +268,10 @@
RTNLMessage::Mode mode,
int flags,
const IPAddress &local,
- const IPAddress &gateway) {
+ const IPAddress &gateway,
+ const IPAddress &peer) {
CHECK(local.family() == gateway.family());
+ CHECK(local.family() == peer.family());
RTNLMessage msg(
RTNLMessage::kTypeAddress,
@@ -285,24 +287,27 @@
0,
0));
- // TODO(pstew): This code only works for Ethernet-like setups,
- // not with devices that have a peer address like PPP.
msg.SetAttribute(IFA_LOCAL, local.address());
if (!gateway.IsDefault()) {
msg.SetAttribute(IFA_BROADCAST, gateway.address());
}
+ if (!peer.IsDefault()) {
+ msg.SetAttribute(IFA_ADDRESS, peer.address());
+ }
return SendMessage(&msg);
}
bool RTNLHandler::AddInterfaceAddress(int interface_index,
const IPAddress &local,
- const IPAddress &broadcast) {
+ const IPAddress &broadcast,
+ const IPAddress &peer) {
return AddressRequest(interface_index,
RTNLMessage::kModeAdd,
NLM_F_CREATE | NLM_F_EXCL,
local,
- broadcast);
+ broadcast,
+ peer);
}
bool RTNLHandler::RemoveInterfaceAddress(int interface_index,
@@ -311,6 +316,7 @@
RTNLMessage::kModeDelete,
0,
local,
+ IPAddress(local.family()),
IPAddress(local.family()));
}
diff --git a/rtnl_handler.h b/rtnl_handler.h
index 235950b..d6fe967 100644
--- a/rtnl_handler.h
+++ b/rtnl_handler.h
@@ -72,7 +72,8 @@
// 'interface_index'.
virtual bool AddInterfaceAddress(int interface_index,
const IPAddress &local,
- const IPAddress &gateway);
+ const IPAddress &gateway,
+ const IPAddress &peer);
// Remove address from a network interface that has a kernel index of
// 'interface_index'.
@@ -126,7 +127,8 @@
RTNLMessage::Mode mode,
int flags,
const IPAddress &local,
- const IPAddress &gateway);
+ const IPAddress &gateway,
+ const IPAddress &peer);
Sockets *sockets_;
bool in_request_;