shill: Add RTNLMessage: rtnl message parser/composer
Add RTNLMessage type. This will be used to remove some bespoke
messaging parsing, but more immediately, it will be used by the
routing code.
BUG=chromium-os:17277
TEST=New unittest
Change-Id: Idb0559b907f018e021193c51d30f5027c8debec3
Reviewed-on: http://gerrit.chromium.org/gerrit/4183
Reviewed-by: Darin Petkov <petkov@chromium.org>
Tested-by: Paul Stewart <pstew@chromium.org>
diff --git a/Makefile b/Makefile
index 22d66a1..e03f580 100644
--- a/Makefile
+++ b/Makefile
@@ -94,6 +94,7 @@
proxy_factory.o \
rtnl_handler.o \
rtnl_listener.o \
+ rtnl_message.o \
service.o \
service_dbus_adaptor.o \
shill_config.o \
@@ -141,6 +142,7 @@
property_store_unittest.o \
rtnl_handler_unittest.o \
rtnl_listener_unittest.o \
+ rtnl_message_unittest.o \
service_unittest.o \
shill_unittest.o \
testrunner.o \
diff --git a/byte_string.cc b/byte_string.cc
index 3a3412f..3c9db10 100644
--- a/byte_string.cc
+++ b/byte_string.cc
@@ -49,4 +49,8 @@
return data_ == b.data_;
}
+void ByteString::Append(const ByteString &b) {
+ data_.insert(data_.end(), b.data_.begin(), b.data_.end());
+}
+
} // namespace shill
diff --git a/byte_string.h b/byte_string.h
index c4c38b2..0077ff0 100644
--- a/byte_string.h
+++ b/byte_string.h
@@ -5,6 +5,7 @@
#ifndef SHILL_BYTE_STRING_
#define SHILL_BYTE_STRING_
+#include <string>
#include <vector>
#include <base/basictypes.h>
@@ -19,6 +20,12 @@
explicit ByteString(size_t length) : data_(length) {}
ByteString(const unsigned char *data, size_t length)
: data_(data, data + length) {}
+ ByteString(const std::string &data, bool copy_terminator)
+ : data_(reinterpret_cast<const unsigned char *>(data.c_str()),
+ reinterpret_cast<const unsigned char *>(data.c_str() +
+ data.length() +
+ (copy_terminator ?
+ 1 : 0))) {}
ByteString &operator=(const ByteString &b) {
data_ = b.data_;
@@ -43,6 +50,10 @@
bool IsZero() const;
bool Equals(const ByteString &b) const;
+ void Append(const ByteString &b);
+ void Resize(int size) {
+ data_.resize(size, 0);
+ }
private:
std::vector<unsigned char> data_;
diff --git a/byte_string_unittest.cc b/byte_string_unittest.cc
index a7e8f04..e8e6048 100644
--- a/byte_string_unittest.cc
+++ b/byte_string_unittest.cc
@@ -16,6 +16,7 @@
const unsigned char kTest1[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
const unsigned char kTest2[] = { 1, 2, 3, 4 };
const unsigned char kTest3[] = { 0, 0, 0, 0 };
+const char kTest4[] = "Hello world";
} // namespace {}
class ByteStringTest : public Test {
@@ -63,8 +64,16 @@
EXPECT_FALSE(bs2.Equals(bs1));
EXPECT_FALSE(bs3.Equals(bs1));
- ByteString bs4(kTest1, sizeof(kTest1));
- EXPECT_TRUE(bs4.Equals(bs1));
+ ByteString bs4(kTest4, false);
+ EXPECT_EQ(strlen(kTest4), bs4.GetLength());
+ EXPECT_EQ(0, memcmp(kTest4, bs4.GetData(), bs4.GetLength()));
+
+ ByteString bs5(kTest4, true);
+ EXPECT_EQ(strlen(kTest4) + 1, bs5.GetLength());
+ EXPECT_EQ(0, memcmp(kTest4, bs5.GetData(), bs5.GetLength()));
+
+ ByteString bs6(kTest1, sizeof(kTest1));
+ EXPECT_TRUE(bs6.Equals(bs1));
}
TEST_F(ByteStringTest, UInt32) {
@@ -96,4 +105,21 @@
#endif
}
+TEST_F(ByteStringTest, Resize) {
+ ByteString bs1(kTest2, sizeof(kTest2));
+ uint32 val;
+
+ bs1.Resize(sizeof(kTest2) + 10);
+ EXPECT_EQ(sizeof(kTest2) + 10, bs1.GetLength());
+ EXPECT_TRUE(bs1.GetData() != NULL);
+ EXPECT_EQ(0, memcmp(bs1.GetData(), kTest2, sizeof(kTest2)));
+ for (size_t i = sizeof(kTest2); i < sizeof(kTest2) + 10; ++i) {
+ EXPECT_EQ(0, bs1.GetData()[i]);
+ }
+
+ bs1.Resize(sizeof(kTest2) - 2);
+ EXPECT_EQ(sizeof(kTest2) - 2, bs1.GetLength());
+ EXPECT_EQ(0, memcmp(bs1.GetData(), kTest2, sizeof(kTest2) - 2));
+}
+
} // namespace shill
diff --git a/ip_address.h b/ip_address.h
index 1677ca9..f931aee 100644
--- a/ip_address.h
+++ b/ip_address.h
@@ -15,11 +15,10 @@
class IPAddress {
public:
- enum Family {
- kAddressFamilyUnknown,
- kAddressFamilyIPv4 = AF_INET,
- kAddressFamilyIPv6 = AF_INET6
- };
+ typedef unsigned char Family;
+ static const Family kAddressFamilyUnknown = AF_UNSPEC;
+ static const Family kAddressFamilyIPv4 = AF_INET;
+ static const Family kAddressFamilyIPv6 = AF_INET6;
explicit IPAddress(Family family);
IPAddress(Family family, const ByteString &address);
diff --git a/rtnl_message.cc b/rtnl_message.cc
new file mode 100644
index 0000000..92636e4
--- /dev/null
+++ b/rtnl_message.cc
@@ -0,0 +1,296 @@
+// Copyright (c) 2011 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.
+
+#include "shill/rtnl_message.h"
+
+#include <base/logging.h>
+
+#include <sys/socket.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+
+namespace shill {
+
+struct RTNLHeader {
+ RTNLHeader() {
+ memset(this, 0, sizeof(*this));
+ }
+ struct nlmsghdr hdr;
+ union {
+ struct ifinfomsg ifi;
+ struct ifaddrmsg ifa;
+ struct rtmsg rtm;
+ struct rtgenmsg gen;
+ };
+};
+
+RTNLMessage::RTNLMessage()
+ : type_(kMessageTypeUnknown),
+ mode_(kMessageModeUnknown),
+ flags_(0),
+ interface_index_(0),
+ family_(IPAddress::kAddressFamilyUnknown) {}
+
+RTNLMessage::RTNLMessage(MessageType type,
+ MessageMode mode,
+ unsigned int flags,
+ uint32 seq,
+ uint32 pid,
+ int interface_index,
+ IPAddress::Family family)
+ : type_(type),
+ mode_(mode),
+ flags_(flags),
+ seq_(seq),
+ pid_(pid),
+ interface_index_(interface_index),
+ family_(family) {}
+
+bool RTNLMessage::Decode(const ByteString &msg) {
+ bool ret = DecodeInternal(msg);
+ if (!ret) {
+ mode_ = kMessageModeUnknown;
+ type_ = kMessageTypeUnknown;
+ }
+ return ret;
+}
+
+bool RTNLMessage::DecodeInternal(const ByteString &msg) {
+ const RTNLHeader *hdr =
+ reinterpret_cast<const RTNLHeader *>(msg.GetConstData());
+
+ if (msg.GetLength() < sizeof(hdr->hdr) ||
+ msg.GetLength() < hdr->hdr.nlmsg_len)
+ return false;
+
+ MessageMode mode = kMessageModeUnknown;
+ switch (hdr->hdr.nlmsg_type) {
+ case RTM_NEWLINK:
+ case RTM_NEWADDR:
+ case RTM_NEWROUTE:
+ mode = kMessageModeAdd;
+ break;
+
+ case RTM_DELLINK:
+ case RTM_DELADDR:
+ case RTM_DELROUTE:
+ mode = kMessageModeDelete;
+ break;
+
+ default:
+ return false;
+ }
+
+ rtattr *attr_data = NULL;
+ int attr_length = 0;
+
+ switch (hdr->hdr.nlmsg_type) {
+ case RTM_NEWLINK:
+ case RTM_DELLINK:
+ if (!DecodeLink(hdr, mode, &attr_data, &attr_length))
+ return false;
+ break;
+
+ case RTM_NEWADDR:
+ case RTM_DELADDR:
+ if (!DecodeAddress(hdr, mode, &attr_data, &attr_length))
+ return false;
+ break;
+
+ case RTM_NEWROUTE:
+ case RTM_DELROUTE:
+ if (!DecodeRoute(hdr, mode, &attr_data, &attr_length))
+ return false;
+ break;
+
+ default:
+ NOTREACHED();
+ }
+
+ flags_ = hdr->hdr.nlmsg_flags;
+ seq_ = hdr->hdr.nlmsg_seq;
+ pid_ = hdr->hdr.nlmsg_pid;
+
+ while (attr_data && RTA_OK(attr_data, attr_length)) {
+ SetAttribute(
+ attr_data->rta_type,
+ ByteString(reinterpret_cast<unsigned char *>(RTA_DATA(attr_data)),
+ RTA_PAYLOAD(attr_data)));
+ attr_data = RTA_NEXT(attr_data, attr_length);
+ }
+
+ if (attr_length) {
+ // We hit a parse error while going through the attributes
+ attributes_.clear();
+ return false;
+ }
+
+ return true;
+}
+
+bool RTNLMessage::DecodeLink(const RTNLHeader *hdr,
+ MessageMode mode,
+ rtattr **attr_data,
+ int *attr_length) {
+ if (hdr->hdr.nlmsg_len < NLMSG_LENGTH(sizeof(hdr->ifi))) {
+ return false;
+ }
+
+ mode_ = mode;
+ *attr_data = IFLA_RTA(NLMSG_DATA(&hdr->hdr));
+ *attr_length = IFLA_PAYLOAD(&hdr->hdr);
+
+ type_ = kMessageTypeLink;
+ family_ = hdr->ifi.ifi_family;
+ interface_index_ = hdr->ifi.ifi_index;
+ set_link_status(LinkStatus(hdr->ifi.ifi_type,
+ hdr->ifi.ifi_flags,
+ hdr->ifi.ifi_change));
+ return true;
+}
+
+bool RTNLMessage::DecodeAddress(const RTNLHeader *hdr,
+ MessageMode mode,
+ rtattr **attr_data,
+ int *attr_length) {
+ if (hdr->hdr.nlmsg_len < NLMSG_LENGTH(sizeof(hdr->ifa))) {
+ return false;
+ }
+ mode_ = mode;
+ *attr_data = IFA_RTA(NLMSG_DATA(&hdr->hdr));
+ *attr_length = IFA_PAYLOAD(&hdr->hdr);
+
+ type_ = kMessageTypeAddress;
+ family_ = hdr->ifa.ifa_family;
+ interface_index_ = hdr->ifa.ifa_index;
+ set_address_status(AddressStatus(hdr->ifa.ifa_prefixlen,
+ hdr->ifa.ifa_flags,
+ hdr->ifa.ifa_scope));
+ return true;
+}
+
+bool RTNLMessage::DecodeRoute(const RTNLHeader *hdr,
+ MessageMode mode,
+ rtattr **attr_data,
+ int *attr_length) {
+ if (hdr->hdr.nlmsg_len < NLMSG_LENGTH(sizeof(hdr->rtm))) {
+ return false;
+ }
+ mode_ = mode;
+ *attr_data = RTM_RTA(NLMSG_DATA(&hdr->hdr));
+ *attr_length = RTM_PAYLOAD(&hdr->hdr);
+
+ type_ = kMessageTypeRoute;
+ family_ = hdr->rtm.rtm_family;
+ set_route_status(RouteStatus(hdr->rtm.rtm_dst_len,
+ hdr->rtm.rtm_src_len,
+ hdr->rtm.rtm_table,
+ hdr->rtm.rtm_protocol,
+ hdr->rtm.rtm_scope,
+ hdr->rtm.rtm_type,
+ hdr->rtm.rtm_flags));
+ return true;
+}
+
+ByteString RTNLMessage::Encode() {
+ if (type_ != kMessageTypeLink &&
+ type_ != kMessageTypeAddress &&
+ type_ != kMessageTypeRoute) {
+ return ByteString();
+ }
+
+ RTNLHeader hdr;
+ hdr.hdr.nlmsg_flags = flags_;
+ hdr.hdr.nlmsg_seq = seq_;
+ hdr.hdr.nlmsg_pid = pid_;
+ hdr.hdr.nlmsg_seq = 0;
+
+ if (mode_ == kMessageModeGet) {
+ if (type_ == kMessageTypeLink) {
+ hdr.hdr.nlmsg_type = RTM_GETLINK;
+ } else if (type_ == kMessageTypeAddress) {
+ hdr.hdr.nlmsg_type = RTM_GETADDR;
+ } else if (type_ == kMessageTypeRoute) {
+ hdr.hdr.nlmsg_type = RTM_GETROUTE;
+ }
+ hdr.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(hdr.gen));
+ hdr.gen.rtgen_family = family_;
+ } else {
+ switch (type_) {
+ case kMessageTypeLink:
+ EncodeLink(&hdr);
+ break;
+
+ case kMessageTypeAddress:
+ EncodeAddress(&hdr);
+ break;
+
+ case kMessageTypeRoute:
+ EncodeRoute(&hdr);
+ break;
+
+ default:
+ NOTREACHED();
+ }
+ }
+
+ size_t header_length = hdr.hdr.nlmsg_len;
+ ByteString attributes;
+
+ base::hash_map<uint16, ByteString>::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);
+
+ struct rtattr rt_attr = { len, attr->first };
+ ByteString attr_header(reinterpret_cast<unsigned char *>(&rt_attr),
+ sizeof(rt_attr));
+ attr_header.Resize(RTA_ALIGN(attr_header.GetLength()));
+ attributes.Append(attr_header);
+
+ ByteString attr_data(attr->second);
+ attr_data.Resize(RTA_ALIGN(attr_data.GetLength()));
+ attributes.Append(attr_data);
+ }
+
+ ByteString packet(reinterpret_cast<unsigned char *>(&hdr), header_length);
+ packet.Append(attributes);
+
+ return packet;
+}
+
+void RTNLMessage::EncodeLink(RTNLHeader *hdr) {
+ hdr->hdr.nlmsg_type = (mode_ == kMessageModeAdd) ? RTM_NEWLINK : RTM_DELLINK;
+ hdr->hdr.nlmsg_len = NLMSG_LENGTH(sizeof(hdr->ifi));
+ hdr->ifi.ifi_family = family_;
+ hdr->ifi.ifi_type = link_status_.type;
+ hdr->ifi.ifi_flags = link_status_.flags;
+ hdr->ifi.ifi_change = link_status_.change;
+}
+
+void RTNLMessage::EncodeAddress(RTNLHeader *hdr) {
+ hdr->hdr.nlmsg_type = (mode_ == kMessageModeAdd) ? RTM_NEWADDR : RTM_DELADDR;
+ 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_;
+}
+
+void RTNLMessage::EncodeRoute(RTNLHeader *hdr) {
+ hdr->hdr.nlmsg_type =
+ (mode_ == kMessageModeAdd) ? RTM_NEWROUTE : RTM_DELROUTE;
+ hdr->hdr.nlmsg_len = NLMSG_LENGTH(sizeof(hdr->rtm));
+ hdr->rtm.rtm_family = family_;
+ hdr->rtm.rtm_dst_len = route_status_.dst_prefix;
+ hdr->rtm.rtm_src_len = route_status_.src_prefix;
+ hdr->rtm.rtm_table = route_status_.table;
+ hdr->rtm.rtm_protocol = route_status_.protocol;
+ hdr->rtm.rtm_scope = route_status_.scope;
+ hdr->rtm.rtm_type = route_status_.type;
+ hdr->rtm.rtm_flags = route_status_.flags;
+}
+
+} // namespace shill
diff --git a/rtnl_message.h b/rtnl_message.h
new file mode 100644
index 0000000..7d56e9f
--- /dev/null
+++ b/rtnl_message.h
@@ -0,0 +1,185 @@
+// Copyright (c) 2011 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.
+
+#ifndef SHILL_RTNL_MESSAGE_
+#define SHILL_RTNL_MESSAGE_
+
+#include <base/basictypes.h>
+#include <base/hash_tables.h>
+#include <base/stl_util-inl.h>
+
+#include "shill/byte_string.h"
+#include "shill/ip_address.h"
+
+struct rtattr;
+
+namespace shill {
+
+struct RTNLHeader;
+
+class RTNLMessage {
+ public:
+ enum MessageType {
+ kMessageTypeUnknown,
+ kMessageTypeLink,
+ kMessageTypeAddress,
+ kMessageTypeRoute
+ };
+
+ enum MessageMode {
+ kMessageModeUnknown,
+ kMessageModeGet,
+ kMessageModeAdd,
+ kMessageModeDelete
+ };
+
+ struct LinkStatus {
+ LinkStatus()
+ : type(0),
+ flags(0),
+ change(0) {}
+ LinkStatus(unsigned int in_type,
+ unsigned int in_flags,
+ unsigned int in_change)
+ : type(in_type),
+ flags(in_flags),
+ change(in_change) {}
+ unsigned int type;
+ unsigned int flags;
+ unsigned int change;
+ };
+
+ struct AddressStatus {
+ AddressStatus()
+ : prefix_len(0),
+ flags(0),
+ scope(0) {}
+ AddressStatus(unsigned char prefix_len_in,
+ unsigned char flags_in,
+ unsigned char scope_in)
+ : prefix_len(prefix_len_in),
+ flags(flags_in),
+ scope(scope_in) {}
+ unsigned char prefix_len;
+ unsigned char flags;
+ unsigned char scope;
+ };
+
+ struct RouteStatus {
+ RouteStatus()
+ : dst_prefix(0),
+ src_prefix(0),
+ table(0),
+ protocol(0),
+ scope(0),
+ type(0),
+ flags(0) {}
+ RouteStatus(unsigned char dst_prefix_in,
+ unsigned char src_prefix_in,
+ unsigned char table_in,
+ unsigned char protocol_in,
+ unsigned char scope_in,
+ unsigned char type_in,
+ unsigned char flags_in)
+ : dst_prefix(dst_prefix_in),
+ src_prefix(src_prefix_in),
+ table(table_in),
+ protocol(protocol_in),
+ scope(scope_in),
+ type(type_in),
+ flags(flags_in) {}
+ unsigned char dst_prefix;
+ unsigned char src_prefix;
+ unsigned char table;
+ unsigned char protocol;
+ unsigned char scope;
+ unsigned char type;
+ unsigned char flags;
+ };
+
+ // Empty constructor
+ RTNLMessage();
+ // Build an RTNL message from arguments
+ RTNLMessage(MessageType type,
+ MessageMode mode,
+ unsigned int flags,
+ uint32 seq,
+ uint32 pid,
+ int interface_index,
+ IPAddress::Family family);
+
+ // Parse an RTNL message. Returns true on success.
+ bool Decode(const ByteString &data);
+ // Encode an RTNL message. Returns empty ByteString on failure.
+ ByteString Encode();
+
+ // Getters and setters
+ MessageType type() { return type_; }
+ MessageMode mode() { return mode_; }
+ uint16 flags() { return flags_; }
+ uint32 seq() { return seq_; }
+ void set_seq(uint32 seq) { seq_ = seq; }
+ uint32 pid() { return pid_; }
+ uint32 interface_index() { return interface_index_; }
+ IPAddress::Family family() { return family_; }
+
+ const LinkStatus &link_status() { return link_status_; }
+ void set_link_status(LinkStatus link_status) { link_status_ = link_status; }
+ const AddressStatus &address_status() { return address_status_; }
+ void set_address_status(AddressStatus address_status) {
+ address_status_ = address_status;
+ }
+ const RouteStatus &route_status() { return route_status_; }
+ void set_route_status(RouteStatus route_status) {
+ route_status_ = route_status;
+ }
+ // GLint hates "unsigned short", and I don't blame it, but that's the
+ // type that's used in the system headers. Use uint16 instead and hope
+ // that the conversion never ends up truncating on some strange platform.
+ bool HasAttribute(uint16 attr) {
+ return ContainsKey(attributes_, attr);
+ }
+ const ByteString GetAttribute(uint16 attr) {
+ return HasAttribute(attr) ? attributes_[attr] : ByteString(0);
+ }
+ void SetAttribute(uint16 attr, const ByteString &val) {
+ attributes_[attr] = val;
+ }
+
+ private:
+ bool DecodeInternal(const ByteString &msg);
+ bool DecodeLink(const RTNLHeader *hdr,
+ MessageMode mode,
+ rtattr **attr_data,
+ int *attr_length);
+ bool DecodeAddress(const RTNLHeader *hdr,
+ MessageMode mode,
+ rtattr **attr_data,
+ int *attr_length);
+ bool DecodeRoute(const RTNLHeader *hdr,
+ MessageMode mode,
+ rtattr **attr_data,
+ int *attr_length);
+ void EncodeLink(RTNLHeader *hdr);
+ void EncodeAddress(RTNLHeader *hdr);
+ void EncodeRoute(RTNLHeader *hdr);
+
+ MessageType type_;
+ MessageMode mode_;
+ uint16 flags_;
+ uint32 seq_;
+ uint32 pid_;
+ unsigned int interface_index_;
+ IPAddress::Family family_;
+ LinkStatus link_status_;
+ AddressStatus address_status_;
+ RouteStatus route_status_;
+ base::hash_map<uint16, ByteString> attributes_;
+
+ DISALLOW_COPY_AND_ASSIGN(RTNLMessage);
+};
+
+} // namespace shill
+
+#endif // SHILL_RTNL_MESSAGE_
diff --git a/rtnl_message_unittest.cc b/rtnl_message_unittest.cc
new file mode 100644
index 0000000..4ba5876
--- /dev/null
+++ b/rtnl_message_unittest.cc
@@ -0,0 +1,604 @@
+// Copyright (c) 2011 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.
+
+#include <sys/socket.h>
+#include <linux/if.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+
+#include <gtest/gtest.h>
+
+#include "shill/byte_string.h"
+#include "shill/ip_address.h"
+#include "shill/rtnl_message.h"
+
+using testing::Test;
+
+namespace shill {
+
+namespace {
+
+// These test strings were generated by cutting up the output of the
+// "rtmon" utility into individual strings. This tool outputs the raw
+// RTNL packet contents sent by the kernel. The comments above each
+// of these strings is the markup that the "ip monitor" command
+// outputs for each of these RTNL packets.
+
+
+// 2: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP
+// link/ether c0:f8:da:05:03:0b brd ff:ff:ff:ff:ff:ff
+
+const int kNewLinkMessageWlan0InterfaceIndex = 2;
+const unsigned int kNewLinkMessageWlan0InterfaceFlags =
+ IFF_BROADCAST | IFF_MULTICAST | IFF_UP | IFF_LOWER_UP | IFF_RUNNING;
+const unsigned int kNewLinkMessageWlan0InterfaceFlagsChange = 0;
+const uint32 kNewLinkMessageWlan0MTU = 1500;
+const char kNewLinkMessageWlan0MACAddress[] = "\xc0\xf8\xda\x05\x03\x0b";
+const char kNewLinkMessageWlan0InterfaceName[] = "wlan0";
+const char kNewLinkMessageWlan0Qdisc[] = "mq";
+const int kNewLinkMessageWlan0OperState = IF_OPER_UP;
+
+const unsigned char kNewLinkMessageWlan0[] = {
+ 0xe0, 0x03, 0x00, 0x00, 0x10, 0x00, 0x02, 0x00,
+ 0x53, 0x18, 0x1f, 0x4e, 0xac, 0x77, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x43, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x0a, 0x00, 0x03, 0x00, 0x77, 0x6c, 0x61, 0x6e,
+ 0x30, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0d, 0x00,
+ 0xe8, 0x03, 0x00, 0x00, 0x05, 0x00, 0x10, 0x00,
+ 0x06, 0x00, 0x00, 0x00, 0x05, 0x00, 0x11, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0xdc, 0x05, 0x00, 0x00, 0x07, 0x00, 0x06, 0x00,
+ 0x6d, 0x71, 0x00, 0x00, 0x20, 0x00, 0x0e, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x01, 0x00,
+ 0xc0, 0xf8, 0xda, 0x05, 0x03, 0x0b, 0x00, 0x00,
+ 0x0a, 0x00, 0x02, 0x00, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0x00, 0x00, 0x60, 0x00, 0x07, 0x00,
+ 0xa6, 0x65, 0x0f, 0x00, 0xa6, 0x0b, 0x00, 0x00,
+ 0xd2, 0x29, 0x61, 0x06, 0xd7, 0x25, 0x07, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x84, 0x53, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xbc, 0x00, 0x17, 0x00,
+ 0xa6, 0x65, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xa6, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xd2, 0x29, 0x61, 0x06, 0x00, 0x00, 0x00, 0x00,
+ 0xd7, 0x25, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x84, 0x53, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x30, 0x02, 0x1a, 0x00, 0x6c, 0x00, 0x02, 0x00,
+ 0x68, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xc0, 0x01, 0x0a, 0x00, 0x08, 0x00, 0x01, 0x00,
+ 0x10, 0x00, 0x00, 0x80, 0x14, 0x00, 0x05, 0x00,
+ 0xff, 0xff, 0x00, 0x00, 0x22, 0x05, 0x00, 0x00,
+ 0x4f, 0x53, 0x00, 0x00, 0xe8, 0x03, 0x00, 0x00,
+ 0x78, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x40, 0x00, 0x00, 0x00, 0xdc, 0x05, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0xa0, 0x0f, 0x00, 0x00,
+ 0xe8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x3a, 0x09, 0x00, 0x80, 0x51, 0x01, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x58, 0x02, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xfc, 0x00, 0x03, 0x00, 0x1f, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x15, 0xe6, 0x04, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x15, 0xe6, 0x04, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x9b, 0x95, 0xb9, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x9b, 0x95, 0xb9, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x18, 0x02, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x06, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+
+// Deleted 8: eth0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN
+// link/ether 68:7f:74:ba:ef:c7 brd ff:ff:ff:ff:ff:ff
+
+const int kDelLinkMessageEth0InterfaceIndex = 8;
+const unsigned int kDelLinkMessageEth0InterfaceFlags =
+ IFF_BROADCAST | IFF_MULTICAST;
+const unsigned int kDelLinkMessageEth0InterfaceFlagsChange = 0xffffffff;
+const uint32 kDelLinkMessageEth0MTU = 1500;
+const char kDelLinkMessageEth0MACAddress[] = "\x68\x7f\x74\xba\xef\xc7";
+const char kDelLinkMessageEth0InterfacName[] = "eth0";
+const char kDelLinkMessageEth0Qdisc[] = "noop";
+const int kDelLinkMessageEth0OperState = IF_OPER_DOWN;
+
+const unsigned char kDelLinkMessageEth0[] = {
+ 0xb8, 0x01, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0x02, 0x10, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+ 0x09, 0x00, 0x03, 0x00, 0x65, 0x74, 0x68, 0x30,
+ 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0d, 0x00,
+ 0xe8, 0x03, 0x00, 0x00, 0x05, 0x00, 0x10, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x11, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0xdc, 0x05, 0x00, 0x00, 0x09, 0x00, 0x06, 0x00,
+ 0x6e, 0x6f, 0x6f, 0x70, 0x00, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x0a, 0x00, 0x01, 0x00, 0x68, 0x7f, 0x74, 0xba,
+ 0xef, 0xc7, 0x00, 0x00, 0x0a, 0x00, 0x02, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
+ 0x60, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0xfa, 0x05, 0x00, 0x00,
+ 0x34, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xbc, 0x00, 0x17, 0x00, 0x09, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xfa, 0x05, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x34, 0x06, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x15, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x1a, 0x00,
+};
+
+// 8: if8 inet 192.168.10.100/24 brd 192.168.10.255 scope global eth0
+
+const int kNewAddrIPV4InterfaceIndex = 8;
+const char kNewAddrIPV4Address[] = "192.168.10.100";
+const int kNewAddrIPV4AddressPrefix = 24;
+const unsigned char kNewAddrIPV4Scope = RT_SCOPE_UNIVERSE;
+
+const unsigned char kNewAddrIPV4[] = {
+ 0x3c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x18, 0x80, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x01, 0x00, 0xc0, 0xa8, 0x0a, 0x64,
+ 0x08, 0x00, 0x02, 0x00, 0xc0, 0xa8, 0x0a, 0x64,
+ 0x08, 0x00, 0x04, 0x00, 0xc0, 0xa8, 0x0a, 0xff,
+ 0x09, 0x00, 0x03, 0x00, 0x65, 0x74, 0x68, 0x30,
+ 0x00, 0x00, 0x00, 0x00,
+};
+
+
+// Deleted ff02::1:ffa0:688 via ff02::1:ffa0:688 dev if2 metric 0
+
+const int kDelRouteIPV6InterfaceIndex = 2;
+const char kDelRouteIPV6Address[] = "ff02::1:ffa0:688";
+const int kDelRouteIPV6Metric = 0;
+
+const unsigned char kDelRouteIPV6[] = {
+ 0x80, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x0a, 0x80, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x01,
+ 0x00, 0x02, 0x00, 0x00, 0x08, 0x00, 0x0f, 0x00,
+ 0xfe, 0x00, 0x00, 0x00, 0x14, 0x00, 0x01, 0x00,
+ 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0xff, 0xa0, 0x06, 0x88,
+ 0x14, 0x00, 0x05, 0x00, 0xff, 0x02, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0xff, 0xa0, 0x06, 0x88, 0x08, 0x00, 0x04, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x06, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x0c, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x5f, 0x0c, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+// default via 192.168.17.254 dev if12 metric 9
+
+const int kAddRouteIPV4InterfaceIndex = 12;
+const char kAddRouteIPV4Address[] = "192.168.17.254";
+const int kAddRouteIPV4Metric = 9;
+
+const unsigned char kAddRouteIPV4[] = {
+ 0x3c, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0xfe, 0x03, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0f, 0x00,
+ 0xfe, 0x00, 0x00, 0x00, 0x08, 0x00, 0x06, 0x00,
+ 0x09, 0x00, 0x00, 0x00, 0x08, 0x00, 0x05, 0x00,
+ 0xc0, 0xa8, 0x11, 0xfe, 0x08, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00,
+};
+
+
+// This is the same as kAddRouteIPV4 above, except manually corrupted
+// the second to last parameter
+const unsigned char kAddRouteBusted[] = {
+ 0x3c, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0xfe, 0x03, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0f, 0x00,
+ 0xfe, 0x00, 0x00, 0x00, 0x08, 0x00, 0x06, 0x00,
+ 0x09, 0x00, 0x00, 0x00, 0x28, 0x00, 0x05, 0x00,
+ 0xc0, 0xa8, 0x11, 0xfe, 0x08, 0x00, 0x04, 0x00,
+ 0x0c, 0x00, 0x00, 0x00,
+};
+
+// 192.168.10.1 dev if8 lladdr 00:14:d1:cd:d5:2c REACHABLE
+const unsigned char kAddNeighborMessage[] = {
+ 0x4c, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x01, 0x08, 0x00, 0x01, 0x00,
+ 0xc0, 0xa8, 0x0a, 0x01, 0x0a, 0x00, 0x02, 0x00,
+ 0x00, 0x14, 0xd1, 0xcd, 0xd5, 0x2c, 0x00, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00,
+};
+
+} // namespace {}
+
+class RTNLMessageTest : public Test {
+ protected:
+ void TestParseLink(const ByteString &packet,
+ RTNLMessage::MessageMode mode,
+ int interface_index,
+ unsigned int flags,
+ unsigned int change,
+ ByteString address,
+ ByteString name,
+ uint32 mtu,
+ ByteString qdisc,
+ int oper_state) {
+ RTNLMessage msg;
+ EXPECT_TRUE(msg.Decode(packet));
+
+ EXPECT_EQ(RTNLMessage::kMessageTypeLink, msg.type());
+ EXPECT_EQ(mode, msg.mode());
+ EXPECT_EQ(interface_index, msg.interface_index());
+
+ RTNLMessage::LinkStatus status = msg.link_status();
+ EXPECT_EQ(flags, status.flags);
+ EXPECT_EQ(change, status.change);
+
+ EXPECT_TRUE(msg.HasAttribute(IFLA_ADDRESS));
+ EXPECT_EQ(address.GetLength(), msg.GetAttribute(IFLA_ADDRESS).GetLength());
+ EXPECT_TRUE(msg.GetAttribute(IFLA_ADDRESS).Equals(address));
+
+ EXPECT_TRUE(msg.HasAttribute(IFLA_IFNAME));
+ EXPECT_EQ(name.GetLength(), msg.GetAttribute(IFLA_IFNAME).GetLength());
+ EXPECT_TRUE(msg.GetAttribute(IFLA_IFNAME).Equals(name));
+
+ EXPECT_TRUE(msg.HasAttribute(IFLA_MTU));
+ uint32 mtu_val;
+ EXPECT_TRUE(msg.GetAttribute(IFLA_MTU).ConvertToCPUUInt32(&mtu_val));
+ EXPECT_EQ(mtu, mtu_val);
+
+ EXPECT_TRUE(msg.HasAttribute(IFLA_QDISC));
+ EXPECT_EQ(qdisc.GetLength(), msg.GetAttribute(IFLA_QDISC).GetLength());
+ EXPECT_TRUE(msg.GetAttribute(IFLA_QDISC).Equals(qdisc));
+
+ EXPECT_TRUE(msg.HasAttribute(IFLA_OPERSTATE));
+ EXPECT_EQ(oper_state, msg.GetAttribute(IFLA_OPERSTATE).GetConstData()[0]);
+ }
+
+ void TestParseAddress(const ByteString &packet,
+ RTNLMessage::MessageMode mode,
+ int interface_index,
+ const IPAddress &address,
+ int prefix,
+ unsigned char scope) {
+ RTNLMessage msg;
+
+ EXPECT_TRUE(msg.Decode(packet));
+ EXPECT_EQ(RTNLMessage::kMessageTypeAddress, msg.type());
+ EXPECT_EQ(mode, msg.mode());
+ EXPECT_EQ(interface_index, msg.interface_index());
+ EXPECT_EQ(address.family(), msg.family());
+
+ RTNLMessage::AddressStatus status = msg.address_status();
+ EXPECT_EQ(prefix, status.prefix_len);
+ EXPECT_EQ(scope, status.scope);
+
+ EXPECT_TRUE(msg.HasAttribute(IFA_LOCAL));
+ EXPECT_EQ(address.GetLength(), msg.GetAttribute(IFA_LOCAL).GetLength());
+ EXPECT_TRUE(
+ IPAddress(address.family(),
+ msg.GetAttribute(IFA_LOCAL)).Equals(address));
+ }
+
+ void TestParseRoute(const ByteString &packet,
+ RTNLMessage::MessageMode mode,
+ IPAddress::Family family,
+ int interface_index,
+ const IPAddress &dst,
+ int dst_prefix,
+ const IPAddress &src,
+ int src_prefix,
+ const IPAddress &gateway,
+ unsigned char table,
+ int protocol,
+ unsigned char scope,
+ unsigned char type,
+ int metric) {
+ RTNLMessage msg;
+
+ EXPECT_TRUE(msg.Decode(packet));
+ EXPECT_EQ(RTNLMessage::kMessageTypeRoute, msg.type());
+ EXPECT_EQ(0, msg.interface_index());
+ EXPECT_EQ(family, msg.family());
+
+ RTNLMessage::RouteStatus status = msg.route_status();
+ EXPECT_EQ(table, status.table);
+ EXPECT_EQ(protocol, status.protocol);
+ EXPECT_EQ(scope, status.scope);
+ EXPECT_EQ(type, status.type);
+
+ if (!dst.IsDefault()) {
+ EXPECT_TRUE(msg.HasAttribute(RTA_DST));
+ EXPECT_TRUE(IPAddress(family, msg.GetAttribute(RTA_DST)).Equals(dst));
+ }
+
+ if (!src.IsDefault()) {
+ EXPECT_TRUE(msg.HasAttribute(RTA_SRC));
+ EXPECT_TRUE(IPAddress(family, msg.GetAttribute(RTA_SRC)).Equals(src));
+ }
+
+ if (!gateway.IsDefault()) {
+ EXPECT_TRUE(msg.HasAttribute(RTA_GATEWAY));
+ EXPECT_TRUE(IPAddress(family,
+ msg.GetAttribute(RTA_GATEWAY)).Equals(gateway));
+ }
+
+ if (interface_index >= 0) {
+ EXPECT_TRUE(msg.HasAttribute(RTA_OIF));
+ uint32 int_val;
+ EXPECT_TRUE(msg.GetAttribute(RTA_OIF).ConvertToCPUUInt32(&int_val));
+ EXPECT_EQ(interface_index, int_val);
+ } else {
+ EXPECT_FALSE(msg.HasAttribute(RTA_OIF));
+ }
+ if (metric >= 0) {
+ EXPECT_TRUE(msg.HasAttribute(RTA_PRIORITY));
+ uint32 metric_val;
+ EXPECT_TRUE(
+ msg.GetAttribute(RTA_PRIORITY).ConvertToCPUUInt32(&metric_val));
+ EXPECT_EQ(metric, metric_val);
+ } else {
+ EXPECT_FALSE(msg.HasAttribute(RTA_PRIORITY));
+ }
+ }
+};
+
+TEST_F(RTNLMessageTest, NewLinkWlan0) {
+ TestParseLink(ByteString(kNewLinkMessageWlan0, sizeof(kNewLinkMessageWlan0)),
+ RTNLMessage::kMessageModeAdd,
+ kNewLinkMessageWlan0InterfaceIndex,
+ kNewLinkMessageWlan0InterfaceFlags,
+ kNewLinkMessageWlan0InterfaceFlagsChange,
+ ByteString(kNewLinkMessageWlan0MACAddress, false),
+ ByteString(kNewLinkMessageWlan0InterfaceName, true),
+ kNewLinkMessageWlan0MTU,
+ ByteString(kNewLinkMessageWlan0Qdisc, true),
+ kNewLinkMessageWlan0OperState);
+}
+
+TEST_F(RTNLMessageTest, DelLinkEth0) {
+ TestParseLink(ByteString(kDelLinkMessageEth0, sizeof(kDelLinkMessageEth0)),
+ RTNLMessage::kMessageModeDelete,
+ kDelLinkMessageEth0InterfaceIndex,
+ kDelLinkMessageEth0InterfaceFlags,
+ kDelLinkMessageEth0InterfaceFlagsChange,
+ ByteString(kDelLinkMessageEth0MACAddress, false),
+ ByteString(kDelLinkMessageEth0InterfacName, true),
+ kDelLinkMessageEth0MTU,
+ ByteString(kDelLinkMessageEth0Qdisc, true),
+ kDelLinkMessageEth0OperState);
+}
+
+TEST_F(RTNLMessageTest, NewAddrIPv4) {
+ IPAddress addr(IPAddress::kAddressFamilyIPv4);
+
+ EXPECT_TRUE(addr.SetAddressFromString(kNewAddrIPV4Address));
+ TestParseAddress(ByteString(kNewAddrIPV4, sizeof(kNewAddrIPV4)),
+ RTNLMessage::kMessageModeAdd,
+ kNewAddrIPV4InterfaceIndex,
+ addr,
+ kNewAddrIPV4AddressPrefix,
+ kNewAddrIPV4Scope);
+}
+
+TEST_F(RTNLMessageTest, DelRouteIPv6) {
+ IPAddress dst(IPAddress::kAddressFamilyIPv6);
+ IPAddress src(IPAddress::kAddressFamilyIPv6);
+ IPAddress gateway(IPAddress::kAddressFamilyIPv6);
+
+ EXPECT_TRUE(dst.SetAddressFromString(kDelRouteIPV6Address));
+ src.SetAddressToDefault();
+ EXPECT_TRUE(gateway.SetAddressFromString(kDelRouteIPV6Address));
+
+ TestParseRoute(ByteString(kDelRouteIPV6, sizeof(kDelRouteIPV6)),
+ RTNLMessage::kMessageModeDelete,
+ IPAddress::kAddressFamilyIPv6,
+ kDelRouteIPV6InterfaceIndex,
+ dst,
+ 0,
+ src,
+ 0,
+ gateway,
+ RT_TABLE_MAIN,
+ RTPROT_UNSPEC,
+ RT_SCOPE_UNIVERSE,
+ RTN_UNICAST,
+ kDelRouteIPV6Metric);
+}
+
+TEST_F(RTNLMessageTest, AddRouteIPv4) {
+ IPAddress dst(IPAddress::kAddressFamilyIPv4);
+ IPAddress src(IPAddress::kAddressFamilyIPv4);
+ IPAddress gateway(IPAddress::kAddressFamilyIPv4);
+
+ dst.SetAddressToDefault();
+ src.SetAddressToDefault();
+ EXPECT_TRUE(gateway.SetAddressFromString(kAddRouteIPV4Address));
+
+ TestParseRoute(ByteString(kAddRouteIPV4, sizeof(kAddRouteIPV4)),
+ RTNLMessage::kMessageModeAdd,
+ IPAddress::kAddressFamilyIPv4,
+ kAddRouteIPV4InterfaceIndex,
+ dst,
+ 0,
+ src,
+ 0,
+ gateway,
+ RT_TABLE_MAIN,
+ RTPROT_BOOT,
+ RT_SCOPE_UNIVERSE,
+ RTN_UNICAST,
+ kAddRouteIPV4Metric);
+}
+
+TEST_F(RTNLMessageTest, AddRouteBusted) {
+ // RTNLMessage should list parse errors as kMessageUnknown
+ RTNLMessage msg;
+ EXPECT_FALSE(msg.Decode(
+ ByteString(kAddRouteBusted, sizeof(kAddRouteBusted))));
+}
+
+TEST_F(RTNLMessageTest, AddNeighbor) {
+ // RTNLMessage doesn't parse Add-Neighbor messages -- ensure this fails
+ RTNLMessage msg;
+ EXPECT_FALSE(msg.Decode(
+ ByteString(kAddNeighborMessage, sizeof(kAddNeighborMessage))));
+}
+
+TEST_F(RTNLMessageTest, Encode) {
+ RTNLMessage msg(RTNLMessage::kMessageTypeRoute,
+ RTNLMessage::kMessageModeAdd,
+ 0, 1, 2, 0,
+ IPAddress::kAddressFamilyIPv4);
+ IPAddress dst(IPAddress::kAddressFamilyIPv4);
+ IPAddress src(IPAddress::kAddressFamilyIPv4);
+ IPAddress gateway(IPAddress::kAddressFamilyIPv4);
+
+ dst.SetAddressToDefault();
+ src.SetAddressToDefault();
+ EXPECT_TRUE(gateway.SetAddressFromString("192.168.0.1"));
+
+ msg.set_route_status(RTNLMessage::RouteStatus(
+ 0, 0, RT_TABLE_MAIN, RTPROT_BOOT, RT_SCOPE_UNIVERSE, RTN_UNICAST, 0));
+ msg.SetAttribute(RTA_DST, dst.address());
+ msg.SetAttribute(RTA_SRC, src.address());
+ msg.SetAttribute(RTA_GATEWAY, gateway.address());
+ msg.SetAttribute(RTA_OIF, ByteString::CreateFromCPUUInt32(12));
+ msg.SetAttribute(RTA_PRIORITY, ByteString::CreateFromCPUUInt32(13));
+
+
+ TestParseRoute(msg.Encode(),
+ RTNLMessage::kMessageModeAdd,
+ IPAddress::kAddressFamilyIPv4,
+ 12,
+ dst,
+ 0,
+ src,
+ 0,
+ gateway,
+ RT_TABLE_MAIN,
+ RTPROT_BOOT,
+ RT_SCOPE_UNIVERSE,
+ RTN_UNICAST,
+ 13);
+}
+
+} // namespace shill