shill: Connection: Add facility to add host routes
This requires a facility for tracking outstanding RTNL route requests,
and adding routes when they the response arrives. A few small fixes
to RTNL handling needed to be added.
BUG=chromium-os:27483
TEST=New Unit Tests, manual: Assocated my new Neptune proto to test
network.
Change-Id: I701fa244041ad9e0d0a502a263d83792ab3c9114
Reviewed-on: https://gerrit.chromium.org/gerrit/17889
Commit-Ready: Paul Stewart <pstew@chromium.org>
Reviewed-by: Paul Stewart <pstew@chromium.org>
Tested-by: Paul Stewart <pstew@chromium.org>
diff --git a/rtnl_message.cc b/rtnl_message.cc
index bf9e8d0..6b4c6a0 100644
--- a/rtnl_message.cc
+++ b/rtnl_message.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -50,8 +50,7 @@
bool RTNLMessage::Decode(const ByteString &msg) {
bool ret = DecodeInternal(msg);
if (!ret) {
- mode_ = kModeUnknown;
- type_ = kTypeUnknown;
+ Reset();
}
return ret;
}
@@ -193,7 +192,7 @@
return true;
}
-ByteString RTNLMessage::Encode() {
+ByteString RTNLMessage::Encode() const {
if (type_ != kTypeLink &&
type_ != kTypeAddress &&
type_ != kTypeRoute) {
@@ -204,7 +203,6 @@
hdr.hdr.nlmsg_flags = flags_;
hdr.hdr.nlmsg_seq = seq_;
hdr.hdr.nlmsg_pid = pid_;
- hdr.hdr.nlmsg_seq = 0;
if (mode_ == kModeGet) {
if (type_ == kTypeLink) {
@@ -213,6 +211,9 @@
hdr.hdr.nlmsg_type = RTM_GETADDR;
} else if (type_ == kTypeRoute) {
hdr.hdr.nlmsg_type = RTM_GETROUTE;
+ } else {
+ NOTIMPLEMENTED();
+ return ByteString();
}
hdr.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(hdr.gen));
hdr.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
@@ -220,15 +221,21 @@
} else {
switch (type_) {
case kTypeLink:
- EncodeLink(&hdr);
+ if (!EncodeLink(&hdr)) {
+ return ByteString();
+ }
break;
case kTypeAddress:
- EncodeAddress(&hdr);
+ if (!EncodeAddress(&hdr)) {
+ return ByteString();
+ }
break;
case kTypeRoute:
- EncodeRoute(&hdr);
+ if (!EncodeRoute(&hdr)) {
+ return ByteString();
+ }
break;
default:
@@ -239,7 +246,7 @@
size_t header_length = hdr.hdr.nlmsg_len;
ByteString attributes;
- base::hash_map<uint16, ByteString>::iterator attr;
+ base::hash_map<uint16, ByteString>::const_iterator attr;
for (attr = attributes_.begin(); attr != attributes_.end(); ++attr) {
size_t len = RTA_LENGTH(attr->second.GetLength());
hdr.hdr.nlmsg_len = NLMSG_ALIGN(hdr.hdr.nlmsg_len) + RTA_ALIGN(len);
@@ -261,28 +268,69 @@
return packet;
}
-void RTNLMessage::EncodeLink(RTNLHeader *hdr) {
- hdr->hdr.nlmsg_type = (mode_ == kModeAdd) ? RTM_NEWLINK : RTM_DELLINK;
+bool RTNLMessage::EncodeLink(RTNLHeader *hdr) const {
+ switch (mode_) {
+ case kModeAdd:
+ hdr->hdr.nlmsg_type = RTM_NEWLINK;
+ break;
+ case kModeDelete:
+ hdr->hdr.nlmsg_type = RTM_DELLINK;
+ break;
+ case kModeQuery:
+ hdr->hdr.nlmsg_type = RTM_GETLINK;
+ break;
+ default:
+ NOTIMPLEMENTED();
+ return false;
+ }
hdr->hdr.nlmsg_len = NLMSG_LENGTH(sizeof(hdr->ifi));
hdr->ifi.ifi_family = family_;
hdr->ifi.ifi_index = interface_index_;
hdr->ifi.ifi_type = link_status_.type;
hdr->ifi.ifi_flags = link_status_.flags;
hdr->ifi.ifi_change = link_status_.change;
+ return true;
}
-void RTNLMessage::EncodeAddress(RTNLHeader *hdr) {
- hdr->hdr.nlmsg_type = (mode_ == kModeAdd) ? RTM_NEWADDR : RTM_DELADDR;
+bool RTNLMessage::EncodeAddress(RTNLHeader *hdr) const {
+ switch (mode_) {
+ case kModeAdd:
+ hdr->hdr.nlmsg_type = RTM_NEWADDR;
+ break;
+ case kModeDelete:
+ hdr->hdr.nlmsg_type = RTM_DELADDR;
+ break;
+ case kModeQuery:
+ hdr->hdr.nlmsg_type = RTM_GETADDR;
+ break;
+ default:
+ NOTIMPLEMENTED();
+ return false;
+ }
hdr->hdr.nlmsg_len = NLMSG_LENGTH(sizeof(hdr->ifa));
hdr->ifa.ifa_family = family_;
hdr->ifa.ifa_prefixlen = address_status_.prefix_len;
hdr->ifa.ifa_flags = address_status_.flags;
hdr->ifa.ifa_scope = address_status_.scope;
hdr->ifa.ifa_index = interface_index_;
+ return true;
}
-void RTNLMessage::EncodeRoute(RTNLHeader *hdr) {
- hdr->hdr.nlmsg_type = (mode_ == kModeAdd) ? RTM_NEWROUTE : RTM_DELROUTE;
+bool RTNLMessage::EncodeRoute(RTNLHeader *hdr) const {
+ switch (mode_) {
+ case kModeAdd:
+ hdr->hdr.nlmsg_type = RTM_NEWROUTE;
+ break;
+ case kModeDelete:
+ hdr->hdr.nlmsg_type = RTM_DELROUTE;
+ break;
+ case kModeQuery:
+ hdr->hdr.nlmsg_type = RTM_GETROUTE;
+ break;
+ default:
+ NOTIMPLEMENTED();
+ return false;
+ }
hdr->hdr.nlmsg_len = NLMSG_LENGTH(sizeof(hdr->rtm));
hdr->rtm.rtm_family = family_;
hdr->rtm.rtm_dst_len = route_status_.dst_prefix;
@@ -292,6 +340,20 @@
hdr->rtm.rtm_scope = route_status_.scope;
hdr->rtm.rtm_type = route_status_.type;
hdr->rtm.rtm_flags = route_status_.flags;
+ return true;
+}
+
+void RTNLMessage::Reset() {
+ mode_ = kModeUnknown;
+ type_ = kTypeUnknown;
+ flags_ = 0;
+ seq_ = 0;
+ interface_index_ = 0;
+ family_ = IPAddress::kFamilyUnknown;
+ link_status_ = LinkStatus();
+ address_status_ = AddressStatus();
+ route_status_ = RouteStatus();
+ attributes_.clear();
}
} // namespace shill