blob: 893241e21780e95c509cfe52ec4dc6a7543b976c [file] [log] [blame] [edit]
// Copyright 2018 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "net-base/rtnl_message.h"
#include <linux/fib_rules.h>
#include <linux/if.h> // NOLINT(build/include_alpha) - needs sockaddr.
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <sys/socket.h>
#include <string>
#include <vector>
#include <base/containers/span.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <re2/re2.h>
#include "net-base/byte_utils.h"
#include "net-base/http_url.h"
#include "net-base/ipv6_address.h"
using testing::Optional;
using testing::Test;
namespace net_base {
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_t kNewLinkMessageWlan0MTU = 1500;
constexpr uint8_t kNewLinkMessageWlan0MacAddress[] = {0xc0, 0xf8, 0xda,
0x05, 0x03, 0x0b};
const char kNewLinkMessageWlan0InterfaceName[] = "wlan0";
const char kNewLinkMessageWlan0Qdisc[] = "mq";
const int kNewLinkMessageWlan0OperState = IF_OPER_UP;
alignas(4) const uint8_t 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,
};
const int kNewLinkMessageIbf1InterfaceIndex = 17;
const char kNewLinkMessageIbf1InterfaceName[] = "ifb1";
alignas(4) const uint8_t kNewLinkMessageIfb1[] = {
0xec, 0x04, 0x00, 0x00, 0x10, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00,
0x2a, 0x47, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x11, 0x00, 0x00, 0x00,
0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x03, 0x00,
0x69, 0x66, 0x62, 0x31, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0d, 0x00,
0x20, 0x00, 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, 0x08, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00,
0x08, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x1f, 0x00,
0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x28, 0x00, 0xff, 0xff, 0x00, 0x00,
0x08, 0x00, 0x29, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x20, 0x00,
0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x21, 0x00, 0x01, 0x00, 0x00, 0x00,
0x09, 0x00, 0x06, 0x00, 0x6e, 0x6f, 0x6f, 0x70, 0x00, 0x00, 0x00, 0x00,
0x08, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x27, 0x00,
0x00, 0x00, 0x00, 0x00, 0x24, 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,
0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x01, 0x00, 0xa2, 0xdc, 0xe7, 0xa3,
0xd5, 0xfc, 0x00, 0x00, 0x0a, 0x00, 0x02, 0x00, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0x00, 0x00, 0xbc, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x60, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0c, 0x00, 0x12, 0x00, 0x08, 0x00, 0x01, 0x00, 0x69, 0x66, 0x62, 0x00,
0xe8, 0x02, 0x1a, 0x00, 0x7c, 0x00, 0x02, 0x00, 0x78, 0x00, 0x01, 0x00,
0x01, 0x00, 0x00, 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, 0x02, 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, 0x00, 0x00, 0x00, 0x00, 0x10, 0x27, 0x00, 0x00,
0xe8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x02, 0x0a, 0x00,
0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x05, 0x00,
0xff, 0xff, 0x00, 0x00, 0xd5, 0x23, 0x02, 0x00, 0x65, 0x77, 0x00, 0x00,
0xe8, 0x03, 0x00, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
0x40, 0x00, 0x00, 0x00, 0xdc, 0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0xff, 0xa0, 0x0f, 0x00, 0x00, 0xe8, 0x03, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x80, 0x3a, 0x09, 0x00, 0x80, 0x51, 0x01, 0x00,
0x03, 0x00, 0x00, 0x00, 0x58, 0x02, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x60, 0xea, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x27, 0x00, 0x00,
0xe8, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 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, 0x00, 0x00, 0x00, 0x00,
0x80, 0xee, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x2c, 0x01, 0x03, 0x00, 0x25, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x06, 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, 0x14, 0x00, 0x07, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x08, 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_t kDelLinkMessageEth0MTU = 1500;
const uint8_t kDelLinkMessageEth0MacAddress[] = {0x68, 0x7f, 0x74,
0xba, 0xef, 0xc7};
const char kDelLinkMessageEth0InterfacName[] = "eth0";
const char kDelLinkMessageEth0Qdisc[] = "noop";
const int kDelLinkMessageEth0OperState = IF_OPER_DOWN;
alignas(4) const uint8_t 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;
alignas(4) const uint8_t 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 15: if15 inet6 fe80::6a7f:74ff:feba:efc7/64 scope link
// valid_lft forever preferred_lft forever
const int kDelAddrIPV6InterfaceIndex = 15;
const char kDelAddrIPV6Address[] = "fe80::6a7f:74ff:feba:efc7";
const int kDelAddrIPV6AddressPrefix = 64;
const unsigned char kDelAddrIPV6Scope = RT_SCOPE_LINK;
alignas(4) const uint8_t kDelAddrIPV6[] = {
0x40, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x40, 0x80, 0xfd, 0x0f, 0x00,
0x00, 0x00, 0x14, 0x00, 0x01, 0x00, 0xfe, 0x80, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x6a, 0x7f, 0x74, 0xff, 0xfe, 0xba, 0xef, 0xc7,
0x14, 0x00, 0x06, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xbf, 0xdb, 0x02, 0x00, 0xbf, 0xdb, 0x02, 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 kDelRouteIPV6Prefix = 128;
const int kDelRouteIPV6Metric = 0;
alignas(4) const uint8_t 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;
alignas(4) const uint8_t 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
alignas(4) const uint8_t 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
alignas(4) const uint8_t 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,
};
// RDNSS notification
// Lifetime: infinity (0xffffffff)
// Server addresses: 2001:db8:100:f101::1, 2001:db8:100:f101::2
alignas(4) const uint8_t kNdRdnssMessage[] = {
0x5c, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x28, 0x00, 0x01, 0x00, 0x00, 0x00,
0x86, 0x00, 0x03, 0x00, 0x14, 0x00, 0x01, 0x00, 0x19, 0x05, 0x00, 0x00,
0xff, 0xff, 0xff, 0xff, 0x20, 0x01, 0x0d, 0xb8, 0x01, 0x00, 0xf1, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0x01, 0x0d, 0xb8,
0x01, 0x00, 0xf1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
0x14, 0x00, 0x01, 0x00, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x50, 0xf8, 0x86, 0xff,
};
// DNSSL notification
// ifindex: 7
// Lifetime: 600
// Domain names: foo.bar, foo.2.bar
alignas(4) const uint8_t kNdDnsslMessage[] = {
0x54, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x20, 0x00, 0x07, 0x00, 0x00, 0x00,
0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x04, 0x00, 0x00,
0x00, 0x00, 0x02, 0x58, 0x03, 0x66, 0x6f, 0x6f, 0x03, 0x62, 0x61, 0x72,
0x00, 0x03, 0x66, 0x6f, 0x6f, 0x01, 0x32, 0x03, 0x62, 0x61, 0x72, 0x00,
0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x01, 0x00, 0xfe, 0x80, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x88, 0xb9, 0xec, 0xff, 0xfe, 0x20, 0x7e, 0x26,
};
// Invalid DNSSL notification
// ifindex: 5
// Lifetime: 300
// Domain names: non-UTF8 data
alignas(4) const uint8_t kInvalidNdDnsslMessage[] = {
0x54, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x20, 0x00, 0x05, 0x00, 0x00, 0x00,
0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x04, 0x00, 0x00,
0x00, 0x00, 0x01, 0x2c, 0x03, 0xb6, 0xa0, 0x6f, 0x03, 0xb7, 0xc5, 0x72,
0x00, 0x03, 0xaa, 0x6f, 0x6f, 0x01, 0x32, 0x03, 0x62, 0x61, 0x72, 0x00,
0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x01, 0x00, 0xfe, 0x80, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x88, 0xb9, 0xec, 0xff, 0xfe, 0x20, 0x7e, 0x26,
};
// CaptivePortal notification
// ifindex: 7
// URI: https://example.org/api
alignas(4) const uint8_t kNdCaptivePortalMessage[] = {
// struct nlmsghdr
0x50, 0x00, 0x00, 0x00, // nlmsg_len = 80
0x44, 0x00, // nlmsg_type = RTM_NEWNDUSEROPT
0x00, 0x00, // nlmsg_flags
0x00, 0x00, 0x00, 0x00, // nlmsg_seq
0x00, 0x00, 0x00, 0x00, // nlmsg_pid
// struct nduseroptmsg
0x0a, // nduseropt_family = AF_INET6
0x00, // nduseropt_pad1
0x20, 0x00, // nduseropt_opts_len = 32
0x07, 0x00, 0x00, 0x00, // nduseropt_ifindex = 7
0x86, // nduseropt_icmp_type
0x00, // nduseropt_icmp_code
0x00, 0x00, // nduseropt_pad2
0x00, 0x00, 0x00, 0x00, // nduseropt_pad3
// RA option defined by RFC8910 Section 2.3
0x25, // Type = ND_OPT_CAPTIVE_PORTAL
0x04, // Length = 4 (32 bytes)
0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x65, 0x78, 0x61, 0x6d,
0x70, 0x6c, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x61, 0x70, 0x69, 0x2f,
0x61, 0x73, 0x64, 0x66, 0x67, 0x68, // URI = https://example.org/api/asdfgh
0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0xb9, 0xec, 0xff,
0xfe, 0x20, 0x7e, 0x26, // Link local source address of the RA packet.
};
// PREF64 = 64:ff9b::/96
alignas(4) const uint8_t kPref64Message[] = {
// struct nlmsghdr
0x40, 0x00, 0x00, 0x00, // nlmsg_len = 64
0x44, 0x00, // nlmsg_type = RTM_NEWNDUSEROPT
0x00, 0x00, // nlmsg_flags
0x00, 0x00, 0x00, 0x00, // nlmsg_seq
0x00, 0x00, 0x00, 0x00, // nlmsg_pid
// struct nduseroptmsg
0x0a, // nduseropt_family = AF_INET6
0x00, // nduseropt_pad1
0x10, 0x00, // nduseropt_opts_len = 16
0x07, 0x00, 0x00, 0x00, // nduseropt_ifindex = 7
0x86, // nduseropt_icmp_type
0x00, // nduseropt_icmp_code
0x00, 0x00, // nduseropt_pad2
0x00, 0x00, 0x00, 0x00, // nduseropt_pad3
// PREF64 Option
0x26, 0x02, 0x0e, 0x10, 0x00, 0x64, 0xff, 0x9b, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0xb9, 0xec, 0xff,
0xfe, 0x20, 0x7e, 0x26, // Link local source address of the RA packet.
};
// RTM_NEWPREFIX notification
// ifindex: 2
// Prefix: 2001:db8:480:ee08::/64
alignas(4) const uint8_t kPrefixMessage[] = {
// struct nlmsghdr
0x3c, 0x00, 0x00, 0x00, // nlmsg_len = 60
0x34, 0x00, // nlmsg_type = RTM_NEWPREFIX
0x00, 0x00, // nlmsg_flags
0x00, 0x00, 0x00, 0x00, // nlmsg_seq
0x00, 0x00, 0x00, 0x00, // nlmsg_pid
// struct prefixmsg
0x0a, // prefix_family = AF_INET6
0x00, // prefix_pad1
0x00, 0x00, // prefix_pad2
0x02, 0x00, 0x00, 0x00, // prefix_ifindex = 2
0x03, // prefix_type = 3 (ND_OPT_PREFIX_INFORMATION)
0x40, // prefix_len = 64
0xc0, // prefix_flags = 0xC0 (L,A)
0x00, // prefix_pad3
// PREFIX_ADDRESS option
0x14, 0x00, 0x01, 0x00, 0x20, 0x01, 0x0d, 0xb8, 0x04, 0x80, 0xee, 0x08,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// PREFIX_CACHEINFO option
0x0c, 0x00, 0x02, 0x00, 0x80, 0x3a, 0x09, 0x00, 0x00, 0x8d, 0x27, 0x00};
// Add IPv4 rule for src 100.87.84.110/24 table 1002
alignas(4) const uint8_t kRuleMessage1[] = {
0x3C, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x39, 0x0, 0x0, 0x0,
0xCE, 0x4, 0x0, 0x0, 0x2, 0x0, 0x18, 0x0, 0xFC, 0x0, 0x0, 0x1,
0x0, 0x0, 0x0, 0x0, 0x8, 0x0, 0xF, 0x0, 0xEA, 0x3, 0x0, 0x0,
0x8, 0x0, 0xE, 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0x8, 0x0, 0x6, 0x0,
0xA, 0x0, 0x0, 0x0, 0x8, 0x0, 0x2, 0x0, 0x64, 0x57, 0x54, 0x6E};
// Delete IPv4 rule for iif eth0 table 1002
alignas(4) const uint8_t kRuleMessage2[] = {
0x40, 0x0, 0x0, 0x0, 0x21, 0x0, 0x0, 0x0, 0xFA, 0x0, 0x0, 0x0, 0x60,
0x4, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0xFC, 0x0, 0x0, 0x1, 0x0, 0x0,
0x0, 0x0, 0x8, 0x0, 0xF, 0x0, 0xEA, 0x3, 0x0, 0x0, 0x8, 0x0, 0xE,
0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0x9, 0x0, 0x3, 0x0, 0x65, 0x74, 0x68, 0x30,
0x0, 0x0, 0x0, 0x0, 0x8, 0x0, 0x6, 0x0, 0xA, 0x0, 0x0, 0x0};
// Add IPv4 rule for fwmark 0x1234/0xFFFF table 1002
alignas(4) const uint8_t kRuleMessage3[] = {
0x44, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x87, 0xB1, 0xA1, 0x5E,
0xD0, 0xE, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0xFC, 0x0, 0x0, 0x1,
0x0, 0x0, 0x0, 0x0, 0x8, 0x0, 0xF, 0x0, 0xEA, 0x3, 0x0, 0x0,
0x8, 0x0, 0xE, 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0x8, 0x0, 0x6, 0x0,
0x8, 0x0, 0x0, 0x0, 0x8, 0x0, 0xA, 0x0, 0x34, 0x12, 0x0, 0x0,
0x8, 0x0, 0x10, 0x0, 0xFF, 0xFF, 0x0, 0x0};
// Add IPv6 rule for table 1002
alignas(4) const uint8_t kRuleMessage4[] = {
0x2c, 0x0, 0x0, 0x0, 0x20, 0x0, 0x2, 0x0, 0x2, 0x0, 0x0,
0x0, 0xce, 0x4, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0xff, 0x0,
0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x8, 0x0, 0xf, 0x0, 0xff,
0x0, 0x0, 0x0, 0x8, 0x0, 0xe, 0x0, 0xff, 0xff, 0xff, 0xff};
RTNLMessage CreateFakeMessage() {
return RTNLMessage(RTNLMessage::kTypeLink, RTNLMessage::kModeGet,
/*flags=*/0,
/*seq=*/0,
/*pid=*/0,
/*interface_index=*/0, AF_INET);
}
} // namespace
class RTNLMessageTest : public Test {
protected:
void TestParseLink(base::span<const uint8_t> packet,
RTNLMessage::Mode mode,
int interface_index,
unsigned int flags,
unsigned int change,
const std::vector<uint8_t>& address,
const std::string& name,
uint32_t mtu,
const std::string& qdisc,
int oper_state) {
const auto msg = RTNLMessage::Decode(packet);
EXPECT_TRUE(msg);
EXPECT_EQ(RTNLMessage::kTypeLink, 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(msg->GetAttribute(IFLA_ADDRESS), address);
EXPECT_TRUE(msg->HasAttribute(IFLA_IFNAME));
EXPECT_EQ(msg->GetAttribute(IFLA_IFNAME),
net_base::byte_utils::StringToCStringBytes(name));
EXPECT_EQ(name, msg->GetIflaIfname());
EXPECT_TRUE(msg->HasAttribute(IFLA_MTU));
EXPECT_EQ(
*net_base::byte_utils::FromBytes<uint32_t>(msg->GetAttribute(IFLA_MTU)),
mtu);
EXPECT_TRUE(msg->HasAttribute(IFLA_QDISC));
EXPECT_EQ(msg->GetAttribute(IFLA_QDISC),
net_base::byte_utils::StringToCStringBytes(qdisc));
EXPECT_TRUE(msg->HasAttribute(IFLA_OPERSTATE));
EXPECT_EQ(oper_state, msg->GetAttribute(IFLA_OPERSTATE).data()[0]);
}
void TestParseAddress(base::span<const uint8_t> packet,
RTNLMessage::Mode mode,
int interface_index,
const IPCIDR& address,
unsigned char scope) {
const auto msg = RTNLMessage::Decode(packet);
EXPECT_TRUE(msg);
EXPECT_EQ(RTNLMessage::kTypeAddress, msg->type());
EXPECT_EQ(mode, msg->mode());
EXPECT_EQ(interface_index, msg->interface_index());
EXPECT_EQ(ToSAFamily(address.GetFamily()), msg->family());
RTNLMessage::AddressStatus status = msg->address_status();
EXPECT_EQ(scope, status.scope);
EXPECT_TRUE(msg->HasAttribute(IFA_ADDRESS));
EXPECT_EQ(msg->GetAttribute(IFA_ADDRESS), address.address().ToBytes());
EXPECT_EQ(msg->GetAddress(), address);
}
void TestParseRoute(base::span<const uint8_t> packet,
RTNLMessage::Mode /*mode*/,
sa_family_t family,
int interface_index,
std::optional<IPCIDR> dst,
std::optional<IPCIDR> src,
std::optional<IPAddress> gateway,
unsigned char table,
int protocol,
unsigned char scope,
unsigned char type,
int metric) {
const auto msg = RTNLMessage::Decode(packet);
EXPECT_TRUE(msg);
EXPECT_EQ(RTNLMessage::kTypeRoute, 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) {
EXPECT_TRUE(msg->HasAttribute(RTA_DST));
EXPECT_EQ(status.dst_prefix, dst->prefix_length());
EXPECT_EQ(msg->GetAttribute(RTA_DST), dst->address().ToBytes());
EXPECT_EQ(msg->GetRtaDst(), dst);
}
if (src) {
EXPECT_TRUE(msg->HasAttribute(RTA_SRC));
EXPECT_EQ(status.src_prefix, src->prefix_length());
EXPECT_EQ(msg->GetAttribute(RTA_SRC), src->address().ToBytes());
EXPECT_EQ(msg->GetRtaSrc(), src);
}
if (gateway) {
EXPECT_TRUE(msg->HasAttribute(RTA_GATEWAY));
EXPECT_EQ(msg->GetAttribute(RTA_GATEWAY), gateway->ToBytes());
EXPECT_EQ(msg->GetRtaGateway(), gateway);
}
if (interface_index >= 0) {
EXPECT_TRUE(msg->HasAttribute(RTA_OIF));
EXPECT_EQ(*net_base::byte_utils::FromBytes<uint32_t>(
msg->GetAttribute(RTA_OIF)),
interface_index);
EXPECT_EQ(msg->GetRtaOif(), interface_index);
} else {
EXPECT_FALSE(msg->HasAttribute(RTA_OIF));
}
if (metric >= 0) {
EXPECT_TRUE(msg->HasAttribute(RTA_PRIORITY));
EXPECT_EQ(*net_base::byte_utils::FromBytes<uint32_t>(
msg->GetAttribute(RTA_PRIORITY)),
metric);
} else {
EXPECT_FALSE(msg->HasAttribute(RTA_PRIORITY));
}
}
void TestParseRule(base::span<const uint8_t> packet,
RTNLMessage::Mode /*mode*/,
sa_family_t family,
unsigned char table,
int protocol,
unsigned char scope,
unsigned char type,
const std::optional<IPCIDR>& dst,
const std::optional<IPCIDR>& src,
uint32_t priority,
uint32_t fwmark,
uint32_t fwmask,
uint32_t uidrange_start,
uint32_t uidrange_end,
const std::string& ifname) {
const auto msg = RTNLMessage::Decode(packet);
EXPECT_TRUE(msg);
EXPECT_EQ(RTNLMessage::kTypeRule, 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) {
EXPECT_TRUE(msg->HasAttribute(FRA_DST));
EXPECT_EQ(msg->GetFraDst(), dst);
}
if (src) {
EXPECT_TRUE(msg->HasAttribute(FRA_SRC));
EXPECT_EQ(msg->GetFraSrc(), src);
}
EXPECT_TRUE(msg->HasAttribute(FRA_PRIORITY));
EXPECT_EQ(*net_base::byte_utils::FromBytes<uint32_t>(
msg->GetAttribute(FRA_PRIORITY)),
priority);
if (fwmark || fwmask) {
EXPECT_TRUE(msg->HasAttribute(FRA_FWMARK));
EXPECT_TRUE(msg->HasAttribute(FRA_FWMASK));
EXPECT_EQ(*net_base::byte_utils::FromBytes<uint32_t>(
msg->GetAttribute(FRA_FWMARK)),
fwmark);
EXPECT_EQ(*net_base::byte_utils::FromBytes<uint32_t>(
msg->GetAttribute(FRA_FWMASK)),
fwmask);
} else {
EXPECT_FALSE(msg->HasAttribute(FRA_FWMARK));
EXPECT_FALSE(msg->HasAttribute(FRA_FWMASK));
}
if (uidrange_start || uidrange_end) {
EXPECT_TRUE(msg->HasAttribute(FRA_UID_RANGE));
const auto decoded_range =
*net_base::byte_utils::FromBytes<struct fib_rule_uid_range>(
msg->GetAttribute(FRA_UID_RANGE));
EXPECT_EQ(uidrange_start, decoded_range.start);
EXPECT_EQ(uidrange_end, decoded_range.end);
} else {
EXPECT_FALSE(msg->HasAttribute(FRA_UID_RANGE));
}
if (!ifname.empty()) {
EXPECT_TRUE(msg->HasAttribute(FRA_IFNAME));
const std::string decoded_ifname =
reinterpret_cast<const char*>(msg->GetAttribute(FRA_IFNAME).data());
EXPECT_STREQ(ifname.c_str(), decoded_ifname.c_str());
} else {
EXPECT_FALSE(msg->HasAttribute(FRA_IFNAME));
}
}
void TestParseRdnss(base::span<const uint8_t> packet,
RTNLMessage::Mode mode,
int interface_index,
uint32_t lifetime,
const std::string& dns_server_addresses) {
const auto msg = RTNLMessage::Decode(packet);
EXPECT_TRUE(msg);
EXPECT_EQ(RTNLMessage::kTypeRdnss, msg->type());
EXPECT_EQ(mode, msg->mode());
EXPECT_EQ(interface_index, msg->interface_index());
RTNLMessage::RdnssOption rdnss = msg->rdnss_option();
// Format addresses string for verification.
std::string addresses;
bool first = true;
for (auto& ip : rdnss.addresses) {
if (!first) {
addresses += ", ";
} else {
first = false;
}
addresses += ip.ToString();
}
// Verify life time and addresses.
EXPECT_EQ(lifetime, rdnss.lifetime);
EXPECT_EQ(dns_server_addresses, addresses);
}
void TestParseNeighbor(base::span<const uint8_t> packet,
RTNLMessage::Mode mode,
sa_family_t family,
int interface_index,
uint16_t state,
uint8_t flags,
uint8_t type) {
const auto msg = RTNLMessage::Decode(packet);
EXPECT_TRUE(msg);
EXPECT_EQ(RTNLMessage::kTypeNeighbor, msg->type());
EXPECT_EQ(mode, msg->mode());
EXPECT_EQ(family, msg->family());
EXPECT_EQ(interface_index, msg->interface_index());
RTNLMessage::NeighborStatus neighbor = msg->neighbor_status();
EXPECT_EQ(neighbor.state, state);
EXPECT_EQ(neighbor.flags, flags);
EXPECT_EQ(neighbor.type, type);
}
};
TEST_F(RTNLMessageTest, NewLinkWlan0) {
TestParseLink(kNewLinkMessageWlan0, RTNLMessage::kModeAdd,
kNewLinkMessageWlan0InterfaceIndex,
kNewLinkMessageWlan0InterfaceFlags,
kNewLinkMessageWlan0InterfaceFlagsChange,
{std::begin(kNewLinkMessageWlan0MacAddress),
std::end(kNewLinkMessageWlan0MacAddress)},
kNewLinkMessageWlan0InterfaceName, kNewLinkMessageWlan0MTU,
kNewLinkMessageWlan0Qdisc, kNewLinkMessageWlan0OperState);
}
TEST_F(RTNLMessageTest, NewLinkIfb1) {
const auto msg = RTNLMessage::Decode(kNewLinkMessageIfb1);
EXPECT_TRUE(msg);
EXPECT_EQ(RTNLMessage::kTypeLink, msg->type());
EXPECT_EQ(RTNLMessage::kModeAdd, msg->mode());
EXPECT_EQ(kNewLinkMessageIbf1InterfaceIndex, msg->interface_index());
EXPECT_TRUE(msg->HasAttribute(IFLA_IFNAME));
EXPECT_EQ(msg->GetAttribute(IFLA_IFNAME),
net_base::byte_utils::StringToCStringBytes(
kNewLinkMessageIbf1InterfaceName));
EXPECT_TRUE(msg->HasAttribute(IFLA_LINKINFO));
EXPECT_STREQ("ifb", msg->link_status().kind.value().c_str());
}
TEST_F(RTNLMessageTest, DelLinkEth0) {
TestParseLink(kDelLinkMessageEth0, RTNLMessage::kModeDelete,
kDelLinkMessageEth0InterfaceIndex,
kDelLinkMessageEth0InterfaceFlags,
kDelLinkMessageEth0InterfaceFlagsChange,
{std::begin(kDelLinkMessageEth0MacAddress),
std::end(kDelLinkMessageEth0MacAddress)},
kDelLinkMessageEth0InterfacName, kDelLinkMessageEth0MTU,
kDelLinkMessageEth0Qdisc, kDelLinkMessageEth0OperState);
}
TEST_F(RTNLMessageTest, NewAddrIPv4) {
const auto addr = *IPCIDR::CreateFromStringAndPrefix(
kNewAddrIPV4Address, kNewAddrIPV4AddressPrefix);
TestParseAddress(kNewAddrIPV4, RTNLMessage::kModeAdd,
kNewAddrIPV4InterfaceIndex, addr, kNewAddrIPV4Scope);
}
TEST_F(RTNLMessageTest, DelAddrIPv6) {
const auto addr = *IPCIDR::CreateFromStringAndPrefix(
kDelAddrIPV6Address, kDelAddrIPV6AddressPrefix);
TestParseAddress(kDelAddrIPV6, RTNLMessage::kModeDelete,
kDelAddrIPV6InterfaceIndex, addr, kDelAddrIPV6Scope);
}
TEST_F(RTNLMessageTest, DelRouteIPv6) {
const auto dst = *IPCIDR::CreateFromStringAndPrefix(kDelRouteIPV6Address,
kDelRouteIPV6Prefix);
const auto gateway = *IPAddress::CreateFromString(kDelRouteIPV6Address);
TestParseRoute(kDelRouteIPV6, RTNLMessage::kModeDelete, AF_INET6,
kDelRouteIPV6InterfaceIndex, dst, /*src=*/std::nullopt,
gateway, RT_TABLE_MAIN, RTPROT_UNSPEC, RT_SCOPE_UNIVERSE,
RTN_UNICAST, kDelRouteIPV6Metric);
}
TEST_F(RTNLMessageTest, AddRouteIPv4) {
const auto gateway = *IPAddress::CreateFromString(kAddRouteIPV4Address);
TestParseRoute(kAddRouteIPV4, RTNLMessage::kModeAdd, AF_INET,
kAddRouteIPV4InterfaceIndex,
/*dst=*/std::nullopt,
/*src=*/std::nullopt, gateway, RT_TABLE_MAIN, RTPROT_BOOT,
RT_SCOPE_UNIVERSE, RTN_UNICAST, kAddRouteIPV4Metric);
}
TEST_F(RTNLMessageTest, NewRdnssOption) {
int interface_index = 1;
uint32_t lifetime = 0xffffffff;
std::string dns_server_addresses =
"2001:db8:100:f101::1, 2001:db8:100:f101::2";
TestParseRdnss(kNdRdnssMessage, RTNLMessage::kModeAdd, interface_index,
lifetime, dns_server_addresses);
}
TEST_F(RTNLMessageTest, DnsslOption) {
const auto msg = RTNLMessage::Decode(kNdDnsslMessage);
std::vector<std::string> expected_domains = {"foo.bar", "foo.2.bar"};
EXPECT_TRUE(msg);
EXPECT_EQ(RTNLMessage::kTypeDnssl, msg->type());
EXPECT_EQ(RTNLMessage::kModeAdd, msg->mode());
EXPECT_EQ(7, msg->interface_index());
RTNLMessage::DnsslOption dnssl = msg->dnssl_option();
// Verify life time and domains.
EXPECT_EQ(600, dnssl.lifetime);
EXPECT_EQ(expected_domains, dnssl.domains);
}
TEST_F(RTNLMessageTest, DnsslOptionWithInvalidData) {
EXPECT_EQ(nullptr, RTNLMessage::Decode(kInvalidNdDnsslMessage));
}
TEST_F(RTNLMessageTest, CaptivePortalOption) {
const auto msg = RTNLMessage::Decode(kNdCaptivePortalMessage);
const HttpUrl expected_uri =
*HttpUrl::CreateFromString("https://example.org/api/asdfgh");
ASSERT_TRUE(msg);
EXPECT_EQ(RTNLMessage::kTypeCaptivePortal, msg->type());
EXPECT_EQ(RTNLMessage::kModeAdd, msg->mode());
EXPECT_EQ(7, msg->interface_index());
EXPECT_EQ(expected_uri, msg->captive_portal_uri());
}
TEST_F(RTNLMessageTest, Pref64Option) {
const auto msg = RTNLMessage::Decode(kPref64Message);
const IPv6CIDR expected_pref =
*IPv6CIDR::CreateFromCIDRString("64:ff9b::/96");
ASSERT_TRUE(msg);
EXPECT_EQ(RTNLMessage::kTypePref64, msg->type());
EXPECT_EQ(RTNLMessage::kModeAdd, msg->mode());
EXPECT_EQ(expected_pref, msg->pref64());
}
TEST_F(RTNLMessageTest, NewPrefix) {
const auto msg = RTNLMessage::Decode(kPrefixMessage);
const IPv6CIDR expected_prefix =
*IPv6CIDR::CreateFromCIDRString("2001:db8:480:ee08::/64");
ASSERT_TRUE(msg);
EXPECT_EQ(RTNLMessage::kTypePrefix, msg->type());
EXPECT_EQ(RTNLMessage::kModeAdd, msg->mode());
EXPECT_EQ(expected_prefix, msg->prefix_status().prefix);
EXPECT_EQ(0xc0, msg->prefix_status().prefix_flags);
}
TEST_F(RTNLMessageTest, ParseRuleEvents) {
struct {
const unsigned char* payload;
size_t length;
std::string iif;
std::string oif;
std::optional<IPCIDR> src;
std::optional<IPCIDR> dst;
uint32_t fwmark;
uint32_t fwmask;
uint32_t table;
uint32_t priority;
} test_cases[] = {
{kRuleMessage1, sizeof(kRuleMessage1), "", "",
IPCIDR::CreateFromStringAndPrefix("100.87.84.110", 24), std::nullopt, 0,
0, 1002, 10},
{kRuleMessage2, sizeof(kRuleMessage2), "eth0", "", std::nullopt,
std::nullopt, 0, 0, 1002, 10},
{kRuleMessage3, sizeof(kRuleMessage3), "", "", std::nullopt, std::nullopt,
0x1234, 0xffff, 1002, 8},
{kRuleMessage4, sizeof(kRuleMessage4), "", "", std::nullopt, std::nullopt,
0, 0, 255, 0},
};
for (const auto& tt : test_cases) {
const auto msg = RTNLMessage::Decode({tt.payload, tt.length});
EXPECT_TRUE(msg);
EXPECT_EQ(tt.iif, msg->GetFraIifname());
EXPECT_EQ(tt.oif, msg->GetFraOifname());
EXPECT_EQ(tt.src, msg->GetFraSrc());
EXPECT_EQ(tt.dst, msg->GetFraDst());
EXPECT_EQ(tt.fwmark, msg->GetFraFwmark());
EXPECT_EQ(tt.fwmask, msg->GetFraFwmask());
EXPECT_EQ(tt.table, msg->GetFraTable());
EXPECT_EQ(tt.priority, msg->GetFraPriority());
}
}
TEST_F(RTNLMessageTest, AddRouteBusted) {
// RTNLMessage should list parse errors as kMessageUnknown
const auto msg = RTNLMessage::Decode(kAddRouteBusted);
EXPECT_FALSE(msg);
}
TEST_F(RTNLMessageTest, AddNeighbor) {
TestParseNeighbor(kAddNeighborMessage, RTNLMessage::kModeAdd, AF_INET, 8,
NUD_REACHABLE, 0, NDA_DST);
}
TEST_F(RTNLMessageTest, EncodeDelNeighbor) {
RTNLMessage msg(RTNLMessage::kTypeNeighbor, RTNLMessage::kModeDelete, 0, 1, 2,
0, AF_INET);
msg.set_neighbor_status(
RTNLMessage::NeighborStatus(0, NTF_ROUTER, NDA_LLADDR));
TestParseNeighbor(msg.Encode(), RTNLMessage::kModeDelete, AF_INET, 0, 0,
NTF_ROUTER, NDA_LLADDR);
}
TEST_F(RTNLMessageTest, EncodeRouteAdd) {
RTNLMessage msg(RTNLMessage::kTypeRoute, RTNLMessage::kModeAdd, 0, 1, 2, 0,
AF_INET);
const auto dst = IPCIDR(IPv4CIDR());
const auto src = IPCIDR(IPv4CIDR());
const auto gateway = *IPAddress::CreateFromString("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().ToBytes());
msg.SetAttribute(RTA_SRC, src.address().ToBytes());
msg.SetAttribute(RTA_GATEWAY, gateway.ToBytes());
msg.SetAttribute(RTA_OIF, net_base::byte_utils::ToBytes<uint32_t>(12));
msg.SetAttribute(RTA_PRIORITY, net_base::byte_utils::ToBytes<uint32_t>(13));
TestParseRoute(msg.Encode(), RTNLMessage::kModeAdd, AF_INET, 12, dst, src,
gateway, RT_TABLE_MAIN, RTPROT_BOOT, RT_SCOPE_UNIVERSE,
RTN_UNICAST, 13);
}
TEST_F(RTNLMessageTest, EncodeRuleAdd) {
RTNLMessage msg(RTNLMessage::kTypeRule, RTNLMessage::kModeAdd, 0, 1, 2, 0,
AF_INET);
const auto dst = *IPCIDR::CreateFromCIDRString("192.168.1.0/32");
const auto src = *IPCIDR::CreateFromCIDRString("192.168.2.0/32");
msg.set_route_status(RTNLMessage::RouteStatus(
static_cast<unsigned char>(dst.prefix_length()),
static_cast<unsigned char>(src.prefix_length()), RT_TABLE_MAIN,
RTPROT_BOOT, RT_SCOPE_UNIVERSE, RTN_UNICAST, 0));
msg.SetAttribute(FRA_DST, dst.address().ToBytes());
msg.SetAttribute(FRA_SRC, src.address().ToBytes());
msg.SetAttribute(FRA_PRIORITY, net_base::byte_utils::ToBytes<uint32_t>(13));
msg.SetAttribute(FRA_FWMARK, net_base::byte_utils::ToBytes<uint32_t>(0x1234));
msg.SetAttribute(FRA_FWMASK, net_base::byte_utils::ToBytes<uint32_t>(0xffff));
struct fib_rule_uid_range r = {.start = 1000, .end = 2000};
msg.SetAttribute(FRA_UID_RANGE,
{reinterpret_cast<const uint8_t*>(&r),
reinterpret_cast<const uint8_t*>(&r) + sizeof(r)});
msg.SetAttribute(FRA_IFNAME,
net_base::byte_utils::StringToCStringBytes("fake0"));
TestParseRule(msg.Encode(), RTNLMessage::kModeAdd, AF_INET, RT_TABLE_MAIN,
RTPROT_BOOT, RT_SCOPE_UNIVERSE, RTN_UNICAST, dst, src, 13,
0x1234, 0xffff, 1000, 2000, "fake0");
}
TEST_F(RTNLMessageTest, EncodeLinkDel) {
const int kInterfaceIndex = 0x1234;
RTNLMessage pmsg(RTNLMessage::kTypeLink, RTNLMessage::kModeDelete,
NLM_F_REQUEST, 0, 0, kInterfaceIndex, AF_UNSPEC);
const auto packet = pmsg.Encode();
const auto msg = RTNLMessage::Decode(packet);
EXPECT_TRUE(msg);
EXPECT_EQ(RTNLMessage::kTypeLink, msg->type());
EXPECT_EQ(RTNLMessage::kModeDelete, msg->mode());
EXPECT_EQ(kInterfaceIndex, msg->interface_index());
RTNLMessage::LinkStatus status = msg->link_status();
EXPECT_EQ(0, status.flags);
EXPECT_EQ(0, status.change);
EXPECT_FALSE(msg->HasAttribute(IFLA_ADDRESS));
EXPECT_FALSE(msg->HasAttribute(IFLA_IFNAME));
EXPECT_FALSE(msg->HasAttribute(IFLA_MTU));
EXPECT_FALSE(msg->HasAttribute(IFLA_QDISC));
EXPECT_FALSE(msg->HasAttribute(IFLA_OPERSTATE));
}
TEST_F(RTNLMessageTest, EncodeIflaInfoKind) {
const std::string kLinkKind = "kind";
RTNLMessage pmsg(RTNLMessage::kTypeLink, RTNLMessage::kModeAdd, NLM_F_REQUEST,
0, 0, 0, AF_UNSPEC);
pmsg.SetIflaInfoKind(kLinkKind, {});
const auto packet = pmsg.Encode();
const auto msg = RTNLMessage::Decode(packet);
EXPECT_TRUE(msg);
EXPECT_TRUE(msg->link_status().kind.has_value());
EXPECT_EQ(msg->link_status().kind.value(), kLinkKind);
}
TEST_F(RTNLMessageTest, ToString) {
struct {
const uint8_t* payload;
size_t length;
std::string regexp;
} test_cases[] = {
{kNewLinkMessageWlan0, sizeof(kNewLinkMessageWlan0),
"Add Link: wlan0\\[2\\] type ETHER flags <BROADCAST,LOWER_UP,MULTICAST,"
"RUNNING,UP> change 0"},
{kNewLinkMessageIfb1, sizeof(kNewLinkMessageIfb1),
"Add Link: ifb1\\[17\\] type ETHER flags <BROADCAST,NOARP> change 0 "
"kind ifb"},
{kDelLinkMessageEth0, sizeof(kDelLinkMessageEth0),
"Delete Link: eth0\\[8\\] type ETHER flags <BROADCAST,MULTICAST> change "
"FFFFFFFF"},
// For Address events, the output interface index cannot be converted
// after the fact using if_indextoname(), but can still happen to match an
// unrelated interface on the unit test host. Escape it with \w*.
{kNewAddrIPV4, sizeof(kNewAddrIPV4),
"Add IPv4 Address: 192\\.168\\.10\\.100/24 if \\w*\\[8\\] flags "
"PERMANENT scope 0"},
{kDelAddrIPV6, sizeof(kDelAddrIPV6),
"Delete IPv6 Address: fe80::6a7f:74ff:feba:efc7/64 if \\w*\\[15\\] "
"flags PERMANENT scope 253"},
{kAddRouteIPV4, sizeof(kAddRouteIPV4),
// For routes, the output interface index cannot be converted after the
// fact using if_indextoname(), but can still happen to match an
// unrelated interface on the unit test host. Escape it with \w*.
"Add IPv4 Route: via 192\\.168\\.17\\.254 if \\w*\\[12\\] table 254 "
"priority 9 protocol BOOT type UNICAST"},
{kDelRouteIPV6, sizeof(kDelRouteIPV6),
"Delete IPv6 Route: dst ff02::1:ffa0:688/128 via ff02::1:ffa0:688 if "
"\\w*\\[2\\] table 254 priority 0 protocol UNSPEC type UNICAST"},
{kAddNeighborMessage, sizeof(kAddNeighborMessage),
"Add IPv4 Neighbor: NeighborStatus state 2 flags 0 type 1"},
{kNdRdnssMessage, sizeof(kNdRdnssMessage),
"Add IPv6 Rdnss: RdnssOption lifetime -1"},
{kRuleMessage1, sizeof(kRuleMessage1),
"Add IPv4 Rule: src 100\\.87\\.84\\.110/24 table 1002 priority 10 "
"action TO_TBL flags 0"},
{kRuleMessage2, sizeof(kRuleMessage2),
"Delete IPv4 Rule: iif eth0 table 1002 priority 10 action TO_TBL flags "
"0"},
{kRuleMessage3, sizeof(kRuleMessage3),
"Add IPv4 Rule: fwmark 0x1234/0xFFFF table 1002 priority 8 action "
"TO_TBL flags 0"},
{kRuleMessage4, sizeof(kRuleMessage4),
"Add IPv6 Rule: table 255 priority 0 action TO_TBL flags 0"},
};
for (const auto& tt : test_cases) {
const auto msg = RTNLMessage::Decode({tt.payload, tt.length});
EXPECT_TRUE(msg);
EXPECT_TRUE(RE2::FullMatch(msg->ToString(), tt.regexp))
<< '"' << msg->ToString() << "\" did not match regex \"" << tt.regexp
<< '"';
}
}
TEST_F(RTNLMessageTest, GetUint32Attribute) {
// Attribute not found
auto msg = CreateFakeMessage();
EXPECT_EQ(0, msg.GetUint32Attribute(4));
// Attribute found
msg.SetAttribute(5, net_base::byte_utils::ToBytes<uint32_t>(1234));
EXPECT_EQ(1234, msg.GetUint32Attribute(5));
}
TEST_F(RTNLMessageTest, GetStringAttribute) {
const std::string attr = "attribute";
// Attribute not found
auto msg = CreateFakeMessage();
EXPECT_EQ("", msg.GetStringAttribute(4));
// Valid c string attribute found
msg.SetAttribute(5, net_base::byte_utils::StringToCStringBytes(attr));
EXPECT_EQ(attr, msg.GetStringAttribute(5));
// Non null-terminated c string attribute found
msg.SetAttribute(6, net_base::byte_utils::ByteStringToBytes(attr));
EXPECT_EQ(attr, msg.GetStringAttribute(6));
// Non text attribute
const uint8_t not_text[] = {0xff, 0xff, 0xff, 0xff};
msg.SetAttribute(8, not_text);
EXPECT_EQ("\xff\xff\xff\xff", msg.GetStringAttribute(8));
}
TEST_F(RTNLMessageTest, EncodeGetMessageLength) {
// The message length of kModeGet should be correct: when there is no
// attribute, it should be a nlmsg header plus a specific struct for the given
// RTNL message type.
RTNLMessage msg_link(RTNLMessage::kTypeLink, RTNLMessage::kModeGet, 0, 0, 0,
0, AF_INET);
EXPECT_EQ(NLMSG_LENGTH(sizeof(struct ifinfomsg)), msg_link.Encode().size());
RTNLMessage msg_address(RTNLMessage::kTypeAddress, RTNLMessage::kModeGet, 0,
0, 0, 0, AF_INET);
EXPECT_EQ(NLMSG_LENGTH(sizeof(struct ifaddrmsg)),
msg_address.Encode().size());
RTNLMessage msg_route(RTNLMessage::kTypeRoute, RTNLMessage::kModeGet, 0, 0, 0,
0, AF_INET);
EXPECT_EQ(NLMSG_LENGTH(sizeof(struct rtmsg)), msg_route.Encode().size());
RTNLMessage msg_rule(RTNLMessage::kTypeRule, RTNLMessage::kModeGet, 0, 0, 0,
0, AF_INET);
EXPECT_EQ(NLMSG_LENGTH(sizeof(struct rtmsg)), msg_rule.Encode().size());
RTNLMessage msg_neighor(RTNLMessage::kTypeNeighbor, RTNLMessage::kModeGet, 0,
0, 0, 0, AF_INET);
EXPECT_EQ(NLMSG_LENGTH(sizeof(struct ndmsg)), msg_neighor.Encode().size());
}
TEST_F(RTNLMessageTest, DnsslOptionsStringWithoutPIIs) {
const auto msg = RTNLMessage::Decode(kNdDnsslMessage);
ASSERT_NE(nullptr, msg);
const RTNLMessage::DnsslOption& dnssl = msg->dnssl_option();
std::vector<std::string> expected_domains = {"foo.bar", "foo.2.bar"};
EXPECT_EQ(expected_domains, dnssl.domains);
std::string output = dnssl.ToString();
for (const auto& expected : expected_domains) {
EXPECT_EQ(output.find(expected), std::string::npos)
<< "DnsslOption string must not contain \"" << expected
<< "\", but was: " << output;
}
}
} // namespace net_base