blob: 045fdeb1d30b70060692939975b299778d4616fe [file] [log] [blame]
// Copyright (c) 2014 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 <linux/nl80211.h>
#include <netlink/netlink.h>
#include <set>
#include <string>
#include <utility>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "shill/byte_string.h"
#include "shill/error.h"
#include "shill/event_dispatcher.h"
#include "shill/ip_address.h"
#include "shill/ip_address_store.h"
#include "shill/logging.h"
#include "shill/mock_glib.h"
#include "shill/mock_log.h"
#include "shill/mock_manager.h"
#include "shill/mock_metrics.h"
#include "shill/mock_netlink_manager.h"
#include "shill/netlink_message_matchers.h"
#include "shill/nice_mock_control.h"
#include "shill/nl80211_message.h"
#include "shill/testing.h"
#include "shill/wake_on_wifi.h"
using std::set;
using std::string;
using testing::_;
using ::testing::AnyNumber;
using ::testing::EndsWith;
using ::testing::Return;
namespace shill {
namespace {
const uint16_t kNl80211FamilyId = 0x13;
// Zero-byte pattern prefixes to match the offsetting bytes in the Ethernet
// frame that lie before the source IP address field.
const uint8_t kIPV4PatternPrefix[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00};
const uint8_t kIPV6PatternPrefix[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
// These masks have bits set to 1 to match bytes in an IP address pattern that
// represent the source IP address of the frame. They are padded with zero
// bits in front to ignore the frame offset and at the end to byte-align the
// mask itself.
const uint8_t kIPV4MaskBytes[] = {0x00, 0x00, 0x00, 0x3c};
const uint8_t kIPV6MaskBytes[] = {0x00, 0x00, 0xc0, 0xff, 0x3f};
const char kIPV4Address0[] = "192.168.10.20";
const uint8_t kIPV4Address0Bytes[] = {0xc0, 0xa8, 0x0a, 0x14};
const char kIPV4Address1[] = "1.2.3.4";
const uint8_t kIPV4Address1Bytes[] = {0x01, 0x02, 0x03, 0x04};
const char kIPV6Address0[] = "FEDC:BA98:7654:3210:FEDC:BA98:7654:3210";
const uint8_t kIPV6Address0Bytes[] = {0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54,
0x32, 0x10, 0xfe, 0xdc, 0xba, 0x98,
0x76, 0x54, 0x32, 0x10};
const char kIPV6Address1[] = "1080:0:0:0:8:800:200C:417A";
const uint8_t kIPV6Address1Bytes[] = {0x10, 0x80, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x08, 0x08, 0x00,
0x20, 0x0c, 0x41, 0x7a};
const char kIPV6Address2[] = "1080::8:800:200C:417A";
const uint8_t kIPV6Address2Bytes[] = {0x10, 0x80, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x08, 0x08, 0x00,
0x20, 0x0c, 0x41, 0x7a};
const char kIPV6Address3[] = "FF01::101";
const uint8_t kIPV6Address3Bytes[] = {0xff, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x01};
const char kIPV6Address4[] = "::1";
const uint8_t kIPV6Address4Bytes[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01};
const char kIPV6Address5[] = "::";
const uint8_t kIPV6Address5Bytes[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00};
const char kIPV6Address6[] = "0:0:0:0:0:FFFF:129.144.52.38";
const uint8_t kIPV6Address6Bytes[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
0x81, 0x90, 0x34, 0x26};
const char kIPV6Address7[] = "::DEDE:190.144.52.38";
const uint8_t kIPV6Address7Bytes[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xde, 0xde,
0xbe, 0x90, 0x34, 0x26};
// These blobs represent NL80211 messages from the kernel reporting the NIC's
// wake-on-packet settings, sent in response to NL80211_CMD_GET_WOWLAN requests.
const uint8_t kResponseNoIPAddresses[] = {
0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x01, 0x00, 0x01, 0x00,
0x00, 0x00, 0x57, 0x40, 0x00, 0x00, 0x49, 0x01, 0x00, 0x00};
const uint8_t kResponseIPV40[] = {
0x4C, 0x00, 0x00, 0x00, 0x14, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00,
0x00, 0x57, 0x40, 0x00, 0x00, 0x49, 0x01, 0x00, 0x00, 0x38, 0x00,
0x75, 0x00, 0x34, 0x00, 0x04, 0x00, 0x30, 0x00, 0x01, 0x00, 0x08,
0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x22, 0x00, 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, 0xC0, 0xA8, 0x0A, 0x14, 0x00, 0x00};
const uint8_t kResponseIPV40WakeOnDisconnect[] = {
0x50, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x57, 0x40, 0x00, 0x00, 0x49, 0x01, 0x00, 0x00, 0x3C, 0x00, 0x75, 0x00,
0x04, 0x00, 0x02, 0x00, 0x34, 0x00, 0x04, 0x00, 0x30, 0x00, 0x01, 0x00,
0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x22, 0x00, 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, 0xC0, 0xA8, 0x0A, 0x14, 0x00, 0x00};
const uint8_t kResponseIPV401[] = {
0x7C, 0x00, 0x00, 0x00, 0x14, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
0x57, 0x40, 0x00, 0x00, 0x49, 0x01, 0x00, 0x00, 0x68, 0x00, 0x75, 0x00,
0x64, 0x00, 0x04, 0x00, 0x30, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00,
0x00, 0x00, 0x00, 0x3C, 0x22, 0x00, 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, 0x01, 0x02,
0x03, 0x04, 0x00, 0x00, 0x30, 0x00, 0x02, 0x00, 0x08, 0x00, 0x01, 0x00,
0x00, 0x00, 0x00, 0x3C, 0x22, 0x00, 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, 0xC0, 0xA8,
0x0A, 0x14, 0x00, 0x00};
const uint8_t kResponseIPV401IPV60[] = {
0xB8, 0x00, 0x00, 0x00, 0x14, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
0x57, 0x40, 0x00, 0x00, 0x49, 0x01, 0x00, 0x00, 0xA4, 0x00, 0x75, 0x00,
0xA0, 0x00, 0x04, 0x00, 0x30, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00,
0x00, 0x00, 0x00, 0x3C, 0x22, 0x00, 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, 0x01, 0x02,
0x03, 0x04, 0x00, 0x00, 0x30, 0x00, 0x02, 0x00, 0x08, 0x00, 0x01, 0x00,
0x00, 0x00, 0x00, 0x3C, 0x22, 0x00, 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, 0xC0, 0xA8,
0x0A, 0x14, 0x00, 0x00, 0x3C, 0x00, 0x03, 0x00, 0x09, 0x00, 0x01, 0x00,
0x00, 0x00, 0xC0, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x02, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xDC,
0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54,
0x32, 0x10, 0x00, 0x00};
const uint8_t kResponseIPV401IPV601[] = {
0xF4, 0x00, 0x00, 0x00, 0x14, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
0x57, 0x40, 0x00, 0x00, 0x49, 0x01, 0x00, 0x00, 0xE0, 0x00, 0x75, 0x00,
0xDC, 0x00, 0x04, 0x00, 0x30, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00,
0x00, 0x00, 0x00, 0x3C, 0x22, 0x00, 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, 0x01, 0x02,
0x03, 0x04, 0x00, 0x00, 0x3C, 0x00, 0x02, 0x00, 0x09, 0x00, 0x01, 0x00,
0x00, 0x00, 0xC0, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x02, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x80,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x20, 0x0C,
0x41, 0x7A, 0x00, 0x00, 0x30, 0x00, 0x03, 0x00, 0x08, 0x00, 0x01, 0x00,
0x00, 0x00, 0x00, 0x3C, 0x22, 0x00, 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, 0xC0, 0xA8,
0x0A, 0x14, 0x00, 0x00, 0x3C, 0x00, 0x04, 0x00, 0x09, 0x00, 0x01, 0x00,
0x00, 0x00, 0xC0, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x02, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xDC,
0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54,
0x32, 0x10, 0x00, 0x00};
// Bytes representing a NL80211_CMD_NEW_WIPHY reporting the wifi capabilities
// of a NIC with wiphy index |kNewWiphyNlMsg_WiphyIndex|. This message reports
// that the NIC can wake on up to |kNewWiphyNlMsg_MaxPatterns| registered
// patterns, and supports both wake on disconnect and wake on pattern.
const uint8_t kNewWiphyNlMsg[] = {
0xc4, 0x0d, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0xdf, 0x49, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00,
0x02, 0x00, 0x00, 0x00, 0x09, 0x00, 0x02, 0x00, 0x70, 0x68, 0x79, 0x30,
0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x2e, 0x00, 0x01, 0x00, 0x00, 0x00,
0x05, 0x00, 0x3d, 0x00, 0x07, 0x00, 0x00, 0x00, 0x05, 0x00, 0x3e, 0x00,
0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x3f, 0x00, 0xff, 0xff, 0xff, 0xff,
0x08, 0x00, 0x40, 0x00, 0xff, 0xff, 0xff, 0xff, 0x05, 0x00, 0x59, 0x00,
0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x2b, 0x00, 0x14, 0x00, 0x00, 0x00,
0x05, 0x00, 0x7b, 0x00, 0x14, 0x00, 0x00, 0x00, 0x06, 0x00, 0x38, 0x00,
0x89, 0x01, 0x00, 0x00, 0x06, 0x00, 0x7c, 0x00, 0xe6, 0x01, 0x00, 0x00,
0x05, 0x00, 0x85, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x04, 0x00, 0x68, 0x00,
0x04, 0x00, 0x82, 0x00, 0x1c, 0x00, 0x39, 0x00, 0x04, 0xac, 0x0f, 0x00,
0x02, 0xac, 0x0f, 0x00, 0x01, 0xac, 0x0f, 0x00, 0x05, 0xac, 0x0f, 0x00,
0x06, 0xac, 0x0f, 0x00, 0x01, 0x72, 0x14, 0x00, 0x05, 0x00, 0x56, 0x00,
0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x66, 0x00, 0x08, 0x00, 0x71, 0x00,
0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00,
0x24, 0x00, 0x20, 0x00, 0x04, 0x00, 0x01, 0x00, 0x04, 0x00, 0x02, 0x00,
0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x06, 0x00,
0x04, 0x00, 0x08, 0x00, 0x04, 0x00, 0x09, 0x00, 0x04, 0x00, 0x0a, 0x00,
0xa8, 0x05, 0x16, 0x00, 0xf0, 0x01, 0x00, 0x00, 0x14, 0x00, 0x03, 0x00,
0xff, 0xff, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x01,
0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x04, 0x00, 0xe2, 0x11, 0x00, 0x00,
0x05, 0x00, 0x05, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00,
0x05, 0x00, 0x00, 0x00, 0x20, 0x01, 0x01, 0x00, 0x14, 0x00, 0x00, 0x00,
0x08, 0x00, 0x01, 0x00, 0x6c, 0x09, 0x00, 0x00, 0x08, 0x00, 0x06, 0x00,
0x40, 0x06, 0x00, 0x00, 0x14, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00,
0x71, 0x09, 0x00, 0x00, 0x08, 0x00, 0x06, 0x00, 0x40, 0x06, 0x00, 0x00,
0x14, 0x00, 0x02, 0x00, 0x08, 0x00, 0x01, 0x00, 0x76, 0x09, 0x00, 0x00,
0x08, 0x00, 0x06, 0x00, 0x40, 0x06, 0x00, 0x00, 0x14, 0x00, 0x03, 0x00,
0x08, 0x00, 0x01, 0x00, 0x7b, 0x09, 0x00, 0x00, 0x08, 0x00, 0x06, 0x00,
0x40, 0x06, 0x00, 0x00, 0x14, 0x00, 0x04, 0x00, 0x08, 0x00, 0x01, 0x00,
0x80, 0x09, 0x00, 0x00, 0x08, 0x00, 0x06, 0x00, 0x40, 0x06, 0x00, 0x00,
0x14, 0x00, 0x05, 0x00, 0x08, 0x00, 0x01, 0x00, 0x85, 0x09, 0x00, 0x00,
0x08, 0x00, 0x06, 0x00, 0x40, 0x06, 0x00, 0x00, 0x14, 0x00, 0x06, 0x00,
0x08, 0x00, 0x01, 0x00, 0x8a, 0x09, 0x00, 0x00, 0x08, 0x00, 0x06, 0x00,
0x40, 0x06, 0x00, 0x00, 0x14, 0x00, 0x07, 0x00, 0x08, 0x00, 0x01, 0x00,
0x8f, 0x09, 0x00, 0x00, 0x08, 0x00, 0x06, 0x00, 0x40, 0x06, 0x00, 0x00,
0x14, 0x00, 0x08, 0x00, 0x08, 0x00, 0x01, 0x00, 0x94, 0x09, 0x00, 0x00,
0x08, 0x00, 0x06, 0x00, 0x40, 0x06, 0x00, 0x00, 0x14, 0x00, 0x09, 0x00,
0x08, 0x00, 0x01, 0x00, 0x99, 0x09, 0x00, 0x00, 0x08, 0x00, 0x06, 0x00,
0x40, 0x06, 0x00, 0x00, 0x14, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x01, 0x00,
0x9e, 0x09, 0x00, 0x00, 0x08, 0x00, 0x06, 0x00, 0x40, 0x06, 0x00, 0x00,
0x20, 0x00, 0x0b, 0x00, 0x08, 0x00, 0x01, 0x00, 0xa3, 0x09, 0x00, 0x00,
0x04, 0x00, 0x02, 0x00, 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x00,
0x08, 0x00, 0x06, 0x00, 0x40, 0x06, 0x00, 0x00, 0x20, 0x00, 0x0c, 0x00,
0x08, 0x00, 0x01, 0x00, 0xa8, 0x09, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00,
0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x00, 0x08, 0x00, 0x06, 0x00,
0x40, 0x06, 0x00, 0x00, 0xa0, 0x00, 0x02, 0x00, 0x0c, 0x00, 0x00, 0x00,
0x08, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
0x08, 0x00, 0x01, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00,
0x10, 0x00, 0x02, 0x00, 0x08, 0x00, 0x01, 0x00, 0x37, 0x00, 0x00, 0x00,
0x04, 0x00, 0x02, 0x00, 0x10, 0x00, 0x03, 0x00, 0x08, 0x00, 0x01, 0x00,
0x6e, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x0c, 0x00, 0x04, 0x00,
0x08, 0x00, 0x01, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x05, 0x00,
0x08, 0x00, 0x01, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x06, 0x00,
0x08, 0x00, 0x01, 0x00, 0x78, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x07, 0x00,
0x08, 0x00, 0x01, 0x00, 0xb4, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00,
0x08, 0x00, 0x01, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x09, 0x00,
0x08, 0x00, 0x01, 0x00, 0x68, 0x01, 0x00, 0x00, 0x0c, 0x00, 0x0a, 0x00,
0x08, 0x00, 0x01, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x0c, 0x00, 0x0b, 0x00,
0x08, 0x00, 0x01, 0x00, 0x1c, 0x02, 0x00, 0x00, 0xb4, 0x03, 0x01, 0x00,
0x14, 0x00, 0x03, 0x00, 0xff, 0xff, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x2c, 0x01, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x04, 0x00,
0xe2, 0x11, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x03, 0x00, 0x00, 0x00,
0x05, 0x00, 0x06, 0x00, 0x05, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x07, 0x00,
0xfa, 0xff, 0x00, 0x00, 0xfa, 0xff, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00,
0xa0, 0x71, 0x80, 0x03, 0x0c, 0x03, 0x01, 0x00, 0x1c, 0x00, 0x00, 0x00,
0x08, 0x00, 0x01, 0x00, 0x3c, 0x14, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00,
0x04, 0x00, 0x03, 0x00, 0x08, 0x00, 0x06, 0x00, 0x40, 0x06, 0x00, 0x00,
0x1c, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x50, 0x14, 0x00, 0x00,
0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x00, 0x08, 0x00, 0x06, 0x00,
0x40, 0x06, 0x00, 0x00, 0x1c, 0x00, 0x02, 0x00, 0x08, 0x00, 0x01, 0x00,
0x64, 0x14, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x00,
0x08, 0x00, 0x06, 0x00, 0x40, 0x06, 0x00, 0x00, 0x1c, 0x00, 0x03, 0x00,
0x08, 0x00, 0x01, 0x00, 0x78, 0x14, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00,
0x04, 0x00, 0x03, 0x00, 0x08, 0x00, 0x06, 0x00, 0x40, 0x06, 0x00, 0x00,
0x20, 0x00, 0x04, 0x00, 0x08, 0x00, 0x01, 0x00, 0x8c, 0x14, 0x00, 0x00,
0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00,
0x08, 0x00, 0x06, 0x00, 0x40, 0x06, 0x00, 0x00, 0x20, 0x00, 0x05, 0x00,
0x08, 0x00, 0x01, 0x00, 0xa0, 0x14, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00,
0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x08, 0x00, 0x06, 0x00,
0x40, 0x06, 0x00, 0x00, 0x20, 0x00, 0x06, 0x00, 0x08, 0x00, 0x01, 0x00,
0xb4, 0x14, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x00,
0x04, 0x00, 0x05, 0x00, 0x08, 0x00, 0x06, 0x00, 0x40, 0x06, 0x00, 0x00,
0x20, 0x00, 0x07, 0x00, 0x08, 0x00, 0x01, 0x00, 0xc8, 0x14, 0x00, 0x00,
0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00,
0x08, 0x00, 0x06, 0x00, 0x40, 0x06, 0x00, 0x00, 0x20, 0x00, 0x08, 0x00,
0x08, 0x00, 0x01, 0x00, 0x7c, 0x15, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00,
0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x08, 0x00, 0x06, 0x00,
0x40, 0x06, 0x00, 0x00, 0x20, 0x00, 0x09, 0x00, 0x08, 0x00, 0x01, 0x00,
0x90, 0x15, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x00,
0x04, 0x00, 0x05, 0x00, 0x08, 0x00, 0x06, 0x00, 0x40, 0x06, 0x00, 0x00,
0x20, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x01, 0x00, 0xa4, 0x15, 0x00, 0x00,
0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00,
0x08, 0x00, 0x06, 0x00, 0x40, 0x06, 0x00, 0x00, 0x20, 0x00, 0x0b, 0x00,
0x08, 0x00, 0x01, 0x00, 0xb8, 0x15, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00,
0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x08, 0x00, 0x06, 0x00,
0x40, 0x06, 0x00, 0x00, 0x20, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x01, 0x00,
0xcc, 0x15, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x00,
0x04, 0x00, 0x05, 0x00, 0x08, 0x00, 0x06, 0x00, 0x40, 0x06, 0x00, 0x00,
0x24, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x01, 0x00, 0xe0, 0x15, 0x00, 0x00,
0x04, 0x00, 0x02, 0x00, 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x00,
0x04, 0x00, 0x05, 0x00, 0x08, 0x00, 0x06, 0x00, 0x40, 0x06, 0x00, 0x00,
0x24, 0x00, 0x0e, 0x00, 0x08, 0x00, 0x01, 0x00, 0xf4, 0x15, 0x00, 0x00,
0x04, 0x00, 0x02, 0x00, 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x00,
0x04, 0x00, 0x05, 0x00, 0x08, 0x00, 0x06, 0x00, 0x40, 0x06, 0x00, 0x00,
0x24, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x01, 0x00, 0x08, 0x16, 0x00, 0x00,
0x04, 0x00, 0x02, 0x00, 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x00,
0x04, 0x00, 0x05, 0x00, 0x08, 0x00, 0x06, 0x00, 0x40, 0x06, 0x00, 0x00,
0x20, 0x00, 0x10, 0x00, 0x08, 0x00, 0x01, 0x00, 0x1c, 0x16, 0x00, 0x00,
0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00,
0x08, 0x00, 0x06, 0x00, 0x40, 0x06, 0x00, 0x00, 0x20, 0x00, 0x11, 0x00,
0x08, 0x00, 0x01, 0x00, 0x30, 0x16, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00,
0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x08, 0x00, 0x06, 0x00,
0x40, 0x06, 0x00, 0x00, 0x20, 0x00, 0x12, 0x00, 0x08, 0x00, 0x01, 0x00,
0x44, 0x16, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x00,
0x04, 0x00, 0x05, 0x00, 0x08, 0x00, 0x06, 0x00, 0x40, 0x06, 0x00, 0x00,
0x20, 0x00, 0x13, 0x00, 0x08, 0x00, 0x01, 0x00, 0x58, 0x16, 0x00, 0x00,
0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00,
0x08, 0x00, 0x06, 0x00, 0x40, 0x06, 0x00, 0x00, 0x1c, 0x00, 0x14, 0x00,
0x08, 0x00, 0x01, 0x00, 0x71, 0x16, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00,
0x04, 0x00, 0x03, 0x00, 0x08, 0x00, 0x06, 0x00, 0x40, 0x06, 0x00, 0x00,
0x1c, 0x00, 0x15, 0x00, 0x08, 0x00, 0x01, 0x00, 0x85, 0x16, 0x00, 0x00,
0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x00, 0x08, 0x00, 0x06, 0x00,
0x40, 0x06, 0x00, 0x00, 0x1c, 0x00, 0x16, 0x00, 0x08, 0x00, 0x01, 0x00,
0x99, 0x16, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x00,
0x08, 0x00, 0x06, 0x00, 0x40, 0x06, 0x00, 0x00, 0x1c, 0x00, 0x17, 0x00,
0x08, 0x00, 0x01, 0x00, 0xad, 0x16, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00,
0x04, 0x00, 0x03, 0x00, 0x08, 0x00, 0x06, 0x00, 0x40, 0x06, 0x00, 0x00,
0x1c, 0x00, 0x18, 0x00, 0x08, 0x00, 0x01, 0x00, 0xc1, 0x16, 0x00, 0x00,
0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x00, 0x08, 0x00, 0x06, 0x00,
0x40, 0x06, 0x00, 0x00, 0x64, 0x00, 0x02, 0x00, 0x0c, 0x00, 0x00, 0x00,
0x08, 0x00, 0x01, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x01, 0x00,
0x08, 0x00, 0x01, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x02, 0x00,
0x08, 0x00, 0x01, 0x00, 0x78, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x03, 0x00,
0x08, 0x00, 0x01, 0x00, 0xb4, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x04, 0x00,
0x08, 0x00, 0x01, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x05, 0x00,
0x08, 0x00, 0x01, 0x00, 0x68, 0x01, 0x00, 0x00, 0x0c, 0x00, 0x06, 0x00,
0x08, 0x00, 0x01, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x0c, 0x00, 0x07, 0x00,
0x08, 0x00, 0x01, 0x00, 0x1c, 0x02, 0x00, 0x00, 0xdc, 0x00, 0x32, 0x00,
0x08, 0x00, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00,
0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x03, 0x00, 0x0b, 0x00, 0x00, 0x00,
0x08, 0x00, 0x04, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x08, 0x00, 0x05, 0x00,
0x13, 0x00, 0x00, 0x00, 0x08, 0x00, 0x06, 0x00, 0x19, 0x00, 0x00, 0x00,
0x08, 0x00, 0x07, 0x00, 0x25, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00,
0x26, 0x00, 0x00, 0x00, 0x08, 0x00, 0x09, 0x00, 0x27, 0x00, 0x00, 0x00,
0x08, 0x00, 0x0a, 0x00, 0x28, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0b, 0x00,
0x2b, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x37, 0x00, 0x00, 0x00,
0x08, 0x00, 0x0d, 0x00, 0x39, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0e, 0x00,
0x3b, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0f, 0x00, 0x43, 0x00, 0x00, 0x00,
0x08, 0x00, 0x10, 0x00, 0x31, 0x00, 0x00, 0x00, 0x08, 0x00, 0x11, 0x00,
0x41, 0x00, 0x00, 0x00, 0x08, 0x00, 0x12, 0x00, 0x42, 0x00, 0x00, 0x00,
0x08, 0x00, 0x13, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x08, 0x00, 0x14, 0x00,
0x54, 0x00, 0x00, 0x00, 0x08, 0x00, 0x15, 0x00, 0x57, 0x00, 0x00, 0x00,
0x08, 0x00, 0x16, 0x00, 0x55, 0x00, 0x00, 0x00, 0x08, 0x00, 0x17, 0x00,
0x59, 0x00, 0x00, 0x00, 0x08, 0x00, 0x18, 0x00, 0x5c, 0x00, 0x00, 0x00,
0x08, 0x00, 0x19, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x08, 0x00, 0x1a, 0x00,
0x2e, 0x00, 0x00, 0x00, 0x08, 0x00, 0x1b, 0x00, 0x30, 0x00, 0x00, 0x00,
0x08, 0x00, 0x6f, 0x00, 0x10, 0x27, 0x00, 0x00, 0x04, 0x00, 0x6c, 0x00,
0x30, 0x04, 0x63, 0x00, 0x04, 0x00, 0x00, 0x00, 0x84, 0x00, 0x01, 0x00,
0x06, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x20, 0x00, 0x00, 0x00,
0x06, 0x00, 0x65, 0x00, 0x30, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
0x40, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x50, 0x00, 0x00, 0x00,
0x06, 0x00, 0x65, 0x00, 0x60, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
0x70, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x80, 0x00, 0x00, 0x00,
0x06, 0x00, 0x65, 0x00, 0x90, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
0xa0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xb0, 0x00, 0x00, 0x00,
0x06, 0x00, 0x65, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
0xd0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xe0, 0x00, 0x00, 0x00,
0x06, 0x00, 0x65, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x84, 0x00, 0x02, 0x00,
0x06, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x20, 0x00, 0x00, 0x00,
0x06, 0x00, 0x65, 0x00, 0x30, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
0x40, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x50, 0x00, 0x00, 0x00,
0x06, 0x00, 0x65, 0x00, 0x60, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
0x70, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x80, 0x00, 0x00, 0x00,
0x06, 0x00, 0x65, 0x00, 0x90, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
0xa0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xb0, 0x00, 0x00, 0x00,
0x06, 0x00, 0x65, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
0xd0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xe0, 0x00, 0x00, 0x00,
0x06, 0x00, 0x65, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x84, 0x00, 0x03, 0x00,
0x06, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x20, 0x00, 0x00, 0x00,
0x06, 0x00, 0x65, 0x00, 0x30, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
0x40, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x50, 0x00, 0x00, 0x00,
0x06, 0x00, 0x65, 0x00, 0x60, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
0x70, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x80, 0x00, 0x00, 0x00,
0x06, 0x00, 0x65, 0x00, 0x90, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
0xa0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xb0, 0x00, 0x00, 0x00,
0x06, 0x00, 0x65, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
0xd0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xe0, 0x00, 0x00, 0x00,
0x06, 0x00, 0x65, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x84, 0x00, 0x04, 0x00,
0x06, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x20, 0x00, 0x00, 0x00,
0x06, 0x00, 0x65, 0x00, 0x30, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
0x40, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x50, 0x00, 0x00, 0x00,
0x06, 0x00, 0x65, 0x00, 0x60, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
0x70, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x80, 0x00, 0x00, 0x00,
0x06, 0x00, 0x65, 0x00, 0x90, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
0xa0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xb0, 0x00, 0x00, 0x00,
0x06, 0x00, 0x65, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
0xd0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xe0, 0x00, 0x00, 0x00,
0x06, 0x00, 0x65, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x04, 0x00, 0x05, 0x00,
0x04, 0x00, 0x06, 0x00, 0x84, 0x00, 0x07, 0x00, 0x06, 0x00, 0x65, 0x00,
0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x10, 0x00, 0x00, 0x00,
0x06, 0x00, 0x65, 0x00, 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
0x30, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x40, 0x00, 0x00, 0x00,
0x06, 0x00, 0x65, 0x00, 0x50, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
0x60, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x70, 0x00, 0x00, 0x00,
0x06, 0x00, 0x65, 0x00, 0x80, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
0x90, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xa0, 0x00, 0x00, 0x00,
0x06, 0x00, 0x65, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
0xc0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xd0, 0x00, 0x00, 0x00,
0x06, 0x00, 0x65, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
0xf0, 0x00, 0x00, 0x00, 0x84, 0x00, 0x08, 0x00, 0x06, 0x00, 0x65, 0x00,
0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x10, 0x00, 0x00, 0x00,
0x06, 0x00, 0x65, 0x00, 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
0x30, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x40, 0x00, 0x00, 0x00,
0x06, 0x00, 0x65, 0x00, 0x50, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
0x60, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x70, 0x00, 0x00, 0x00,
0x06, 0x00, 0x65, 0x00, 0x80, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
0x90, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xa0, 0x00, 0x00, 0x00,
0x06, 0x00, 0x65, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
0xc0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xd0, 0x00, 0x00, 0x00,
0x06, 0x00, 0x65, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
0xf0, 0x00, 0x00, 0x00, 0x84, 0x00, 0x09, 0x00, 0x06, 0x00, 0x65, 0x00,
0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x10, 0x00, 0x00, 0x00,
0x06, 0x00, 0x65, 0x00, 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
0x30, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x40, 0x00, 0x00, 0x00,
0x06, 0x00, 0x65, 0x00, 0x50, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
0x60, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x70, 0x00, 0x00, 0x00,
0x06, 0x00, 0x65, 0x00, 0x80, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
0x90, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xa0, 0x00, 0x00, 0x00,
0x06, 0x00, 0x65, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
0xc0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xd0, 0x00, 0x00, 0x00,
0x06, 0x00, 0x65, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
0xf0, 0x00, 0x00, 0x00, 0x84, 0x00, 0x0a, 0x00, 0x06, 0x00, 0x65, 0x00,
0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x10, 0x00, 0x00, 0x00,
0x06, 0x00, 0x65, 0x00, 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
0x30, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x40, 0x00, 0x00, 0x00,
0x06, 0x00, 0x65, 0x00, 0x50, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
0x60, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x70, 0x00, 0x00, 0x00,
0x06, 0x00, 0x65, 0x00, 0x80, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
0x90, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xa0, 0x00, 0x00, 0x00,
0x06, 0x00, 0x65, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
0xc0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xd0, 0x00, 0x00, 0x00,
0x06, 0x00, 0x65, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
0xf0, 0x00, 0x00, 0x00, 0x40, 0x01, 0x64, 0x00, 0x04, 0x00, 0x00, 0x00,
0x24, 0x00, 0x01, 0x00, 0x06, 0x00, 0x65, 0x00, 0x40, 0x00, 0x00, 0x00,
0x06, 0x00, 0x65, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
0xc0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xd0, 0x00, 0x00, 0x00,
0x14, 0x00, 0x02, 0x00, 0x06, 0x00, 0x65, 0x00, 0x40, 0x00, 0x00, 0x00,
0x06, 0x00, 0x65, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x03, 0x00,
0x06, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x40, 0x00, 0x00, 0x00,
0x06, 0x00, 0x65, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
0xb0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xc0, 0x00, 0x00, 0x00,
0x06, 0x00, 0x65, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x04, 0x00,
0x06, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x40, 0x00, 0x00, 0x00,
0x06, 0x00, 0x65, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
0xb0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xc0, 0x00, 0x00, 0x00,
0x06, 0x00, 0x65, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x04, 0x00, 0x05, 0x00,
0x04, 0x00, 0x06, 0x00, 0x1c, 0x00, 0x07, 0x00, 0x06, 0x00, 0x65, 0x00,
0xb0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xc0, 0x00, 0x00, 0x00,
0x06, 0x00, 0x65, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x14, 0x00, 0x08, 0x00,
0x06, 0x00, 0x65, 0x00, 0x40, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
0xd0, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x09, 0x00, 0x06, 0x00, 0x65, 0x00,
0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0x20, 0x00, 0x00, 0x00,
0x06, 0x00, 0x65, 0x00, 0x40, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
0xa0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xb0, 0x00, 0x00, 0x00,
0x06, 0x00, 0x65, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00,
0xd0, 0x00, 0x00, 0x00, 0x14, 0x00, 0x0a, 0x00, 0x06, 0x00, 0x65, 0x00,
0x40, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0x00, 0xd0, 0x00, 0x00, 0x00,
0x34, 0x00, 0x76, 0x00, 0x04, 0x00, 0x02, 0x00, 0x04, 0x00, 0x03, 0x00,
0x04, 0x00, 0x05, 0x00, 0x04, 0x00, 0x06, 0x00, 0x04, 0x00, 0x07, 0x00,
0x04, 0x00, 0x08, 0x00, 0x04, 0x00, 0x09, 0x00, 0x14, 0x00, 0x04, 0x00,
0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x79, 0x00, 0x04, 0x00, 0x04, 0x00,
0x04, 0x00, 0x06, 0x00, 0x60, 0x00, 0x78, 0x00, 0x5c, 0x00, 0x01, 0x00,
0x48, 0x00, 0x01, 0x00, 0x14, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00,
0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x04, 0x00, 0x02, 0x00,
0x1c, 0x00, 0x02, 0x00, 0x08, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
0x10, 0x00, 0x02, 0x00, 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x08, 0x00,
0x04, 0x00, 0x09, 0x00, 0x14, 0x00, 0x03, 0x00, 0x08, 0x00, 0x01, 0x00,
0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x04, 0x00, 0x0a, 0x00,
0x08, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00,
0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x8f, 0x00, 0xe3, 0x1a, 0x00, 0x00,
0x1e, 0x00, 0x94, 0x00, 0x62, 0x08, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0xa9, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x0c, 0x00, 0xaa, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40};
const uint32_t kNewWiphyNlMsg_WiphyIndex = 2;
const uint32_t kNewWiphyNlMsg_MaxPatterns = 20;
const int kNewWiphyNlMsg_Nl80211AttrWiphyOffset = 20;
const int kNewWiphyNlMsg_PattSupportOffset = 3336;
const int kNewWiphyNlMsg_WowlanTrigDisconnectAttributeOffset = 3304;
} // namespace
class WakeOnWiFiTest : public ::testing::Test {
public:
WakeOnWiFiTest()
: metrics_(nullptr),
manager_(&control_interface_, nullptr, &metrics_, &glib_),
wake_on_wifi_(
new WakeOnWiFi(&netlink_manager_, &dispatcher_, &manager_)) {}
virtual ~WakeOnWiFiTest() {}
virtual void SetUp() {
// Assume our NIC has reported its wiphy index, and that it supports wake
// on IP address patterns and disconnects. Necessary to pass error checks in
// WakeOnWiFi::ApplyWakeOnWiFiSettings so that the function will execute.
wake_on_wifi_->wiphy_index_received_ = true;
wake_on_wifi_->wake_on_wifi_triggers_supported_.insert(
WakeOnWiFi::kIPAddress);
wake_on_wifi_->wake_on_wifi_triggers_supported_.insert(
WakeOnWiFi::kDisconnect);
ON_CALL(netlink_manager_, SendNl80211Message(_, _, _, _))
.WillByDefault(Return(true));
}
void AddWakeOnPacketConnection(const IPAddress &ip_endpoint, Error *error) {
wake_on_wifi_->AddWakeOnPacketConnection(ip_endpoint, error);
}
void RemoveWakeOnPacketConnection(const IPAddress &ip_endpoint,
Error *error) {
wake_on_wifi_->RemoveWakeOnPacketConnection(ip_endpoint, error);
}
void RemoveAllWakeOnPacketConnections(Error *error) {
wake_on_wifi_->RemoveAllWakeOnPacketConnections(error);
}
bool CreateIPAddressPatternAndMask(const IPAddress &ip_addr,
ByteString *pattern, ByteString *mask) {
return WakeOnWiFi::CreateIPAddressPatternAndMask(ip_addr, pattern, mask);
}
bool ConfigureWiphyIndex(Nl80211Message *msg, int32_t index) {
return WakeOnWiFi::ConfigureWiphyIndex(msg, index);
}
bool ConfigureDisableWakeOnWiFiMessage(SetWakeOnPacketConnMessage *msg,
uint32_t wiphy_index, Error *error) {
return WakeOnWiFi::ConfigureDisableWakeOnWiFiMessage(msg, wiphy_index,
error);
}
bool WakeOnWiFiSettingsMatch(const Nl80211Message &msg,
const set<WakeOnWiFi::WakeOnWiFiTrigger> &trigs,
const IPAddressStore &addrs) {
return WakeOnWiFi::WakeOnWiFiSettingsMatch(msg, trigs, addrs);
}
bool ConfigureSetWakeOnWiFiSettingsMessage(
SetWakeOnPacketConnMessage *msg,
const set<WakeOnWiFi::WakeOnWiFiTrigger> &trigs,
const IPAddressStore &addrs, uint32_t wiphy_index, Error *error) {
return WakeOnWiFi::ConfigureSetWakeOnWiFiSettingsMessage(
msg, trigs, addrs, wiphy_index, error);
}
void RequestWakeOnPacketSettings() {
wake_on_wifi_->RequestWakeOnPacketSettings();
}
void VerifyWakeOnWiFiSettings(const Nl80211Message &nl80211_message) {
wake_on_wifi_->VerifyWakeOnWiFiSettings(nl80211_message);
}
size_t GetWakeOnWiFiMaxPatterns() {
return wake_on_wifi_->wake_on_wifi_max_patterns_;
}
void SetWakeOnWiFiMaxPatterns(size_t max_patterns) {
wake_on_wifi_->wake_on_wifi_max_patterns_ = max_patterns;
}
void ApplyWakeOnWiFiSettings() { wake_on_wifi_->ApplyWakeOnWiFiSettings(); }
set<WakeOnWiFi::WakeOnWiFiTrigger> *GetWakeOnWiFiTriggers() {
return &wake_on_wifi_->wake_on_wifi_triggers_;
}
set<WakeOnWiFi::WakeOnWiFiTrigger> *GetWakeOnWiFiTriggersSupported() {
return &wake_on_wifi_->wake_on_wifi_triggers_supported_;
}
void ClearWakeOnWiFiTriggersSupported() {
wake_on_wifi_->wake_on_wifi_triggers_supported_.clear();
}
IPAddressStore *GetWakeOnPacketConnections() {
return &wake_on_wifi_->wake_on_packet_connections_;
}
void RetrySetWakeOnPacketConnections() {
wake_on_wifi_->RetrySetWakeOnPacketConnections();
}
void SetSuspendActionsDoneCallback() {
wake_on_wifi_->suspend_actions_done_callback_ =
base::Bind(&WakeOnWiFiTest::SuspendCallback, base::Unretained(this));
}
bool SuspendActionsCallbackIsNull() {
return wake_on_wifi_->suspend_actions_done_callback_.is_null();
}
int GetNumSetWakeOnPacketRetries() {
return wake_on_wifi_->num_set_wake_on_packet_retries_;
}
void SetNumSetWakeOnPacketRetries(int retries) {
wake_on_wifi_->num_set_wake_on_packet_retries_ = retries;
}
void OnBeforeSuspend() {
ResultCallback callback(
base::Bind(&WakeOnWiFiTest::SuspendCallback, base::Unretained(this)));
wake_on_wifi_->OnBeforeSuspend(callback);
}
void OnAfterResume() { wake_on_wifi_->OnAfterResume(); }
void SetWiphyIndexReceivedToFalse() {
wake_on_wifi_->wiphy_index_received_ = false;
}
uint32_t GetWiphyIndex() { return wake_on_wifi_->wiphy_index_; }
bool GetWiphyIndexReceived() { return wake_on_wifi_->wiphy_index_received_; }
void ParseWiphyIndex(const Nl80211Message &nl80211_message) {
wake_on_wifi_->ParseWiphyIndex(nl80211_message);
}
void ParseWakeOnWiFiCapabilities(const Nl80211Message &nl80211_message) {
wake_on_wifi_->ParseWakeOnWiFiCapabilities(nl80211_message);
}
MOCK_METHOD1(SuspendCallback, void(const Error &error));
protected:
NiceMockControl control_interface_;
MockMetrics metrics_;
MockGLib glib_;
EventDispatcher dispatcher_;
MockNetlinkManager netlink_manager_;
MockManager manager_;
std::unique_ptr<WakeOnWiFi> wake_on_wifi_;
};
ByteString CreatePattern(const unsigned char *prefix, size_t prefix_len,
const unsigned char *addr, size_t addr_len) {
ByteString result(prefix, prefix_len);
result.Append(ByteString(addr, addr_len));
return result;
}
TEST_F(WakeOnWiFiTest, CreateIPAddressPatternAndMask) {
ByteString pattern;
ByteString mask;
ByteString expected_pattern;
CreateIPAddressPatternAndMask(IPAddress(kIPV4Address0), &pattern, &mask);
expected_pattern =
CreatePattern(kIPV4PatternPrefix, sizeof(kIPV4PatternPrefix),
kIPV4Address0Bytes, sizeof(kIPV4Address0Bytes));
EXPECT_TRUE(pattern.Equals(expected_pattern));
EXPECT_TRUE(mask.Equals(ByteString(kIPV4MaskBytes, sizeof(kIPV4MaskBytes))));
pattern.Clear();
expected_pattern.Clear();
mask.Clear();
CreateIPAddressPatternAndMask(IPAddress(kIPV4Address1), &pattern, &mask);
expected_pattern =
CreatePattern(kIPV4PatternPrefix, sizeof(kIPV4PatternPrefix),
kIPV4Address1Bytes, sizeof(kIPV4Address1Bytes));
EXPECT_TRUE(pattern.Equals(expected_pattern));
EXPECT_TRUE(mask.Equals(ByteString(kIPV4MaskBytes, sizeof(kIPV4MaskBytes))));
pattern.Clear();
expected_pattern.Clear();
mask.Clear();
CreateIPAddressPatternAndMask(IPAddress(kIPV6Address0), &pattern, &mask);
expected_pattern =
CreatePattern(kIPV6PatternPrefix, sizeof(kIPV6PatternPrefix),
kIPV6Address0Bytes, sizeof(kIPV6Address0Bytes));
EXPECT_TRUE(pattern.Equals(expected_pattern));
EXPECT_TRUE(mask.Equals(ByteString(kIPV6MaskBytes, sizeof(kIPV6MaskBytes))));
pattern.Clear();
expected_pattern.Clear();
mask.Clear();
CreateIPAddressPatternAndMask(IPAddress(kIPV6Address1), &pattern, &mask);
expected_pattern =
CreatePattern(kIPV6PatternPrefix, sizeof(kIPV6PatternPrefix),
kIPV6Address1Bytes, sizeof(kIPV6Address1Bytes));
EXPECT_TRUE(pattern.Equals(expected_pattern));
EXPECT_TRUE(mask.Equals(ByteString(kIPV6MaskBytes, sizeof(kIPV6MaskBytes))));
pattern.Clear();
expected_pattern.Clear();
mask.Clear();
CreateIPAddressPatternAndMask(IPAddress(kIPV6Address2), &pattern, &mask);
expected_pattern =
CreatePattern(kIPV6PatternPrefix, sizeof(kIPV6PatternPrefix),
kIPV6Address2Bytes, sizeof(kIPV6Address2Bytes));
EXPECT_TRUE(pattern.Equals(expected_pattern));
EXPECT_TRUE(mask.Equals(ByteString(kIPV6MaskBytes, sizeof(kIPV6MaskBytes))));
pattern.Clear();
expected_pattern.Clear();
mask.Clear();
CreateIPAddressPatternAndMask(IPAddress(kIPV6Address3), &pattern, &mask);
expected_pattern =
CreatePattern(kIPV6PatternPrefix, sizeof(kIPV6PatternPrefix),
kIPV6Address3Bytes, sizeof(kIPV6Address3Bytes));
EXPECT_TRUE(pattern.Equals(expected_pattern));
EXPECT_TRUE(mask.Equals(ByteString(kIPV6MaskBytes, sizeof(kIPV6MaskBytes))));
pattern.Clear();
expected_pattern.Clear();
mask.Clear();
CreateIPAddressPatternAndMask(IPAddress(kIPV6Address4), &pattern, &mask);
expected_pattern =
CreatePattern(kIPV6PatternPrefix, sizeof(kIPV6PatternPrefix),
kIPV6Address4Bytes, sizeof(kIPV6Address4Bytes));
EXPECT_TRUE(pattern.Equals(expected_pattern));
EXPECT_TRUE(mask.Equals(ByteString(kIPV6MaskBytes, sizeof(kIPV6MaskBytes))));
pattern.Clear();
expected_pattern.Clear();
mask.Clear();
CreateIPAddressPatternAndMask(IPAddress(kIPV6Address5), &pattern, &mask);
expected_pattern =
CreatePattern(kIPV6PatternPrefix, sizeof(kIPV6PatternPrefix),
kIPV6Address5Bytes, sizeof(kIPV6Address5Bytes));
EXPECT_TRUE(pattern.Equals(expected_pattern));
EXPECT_TRUE(mask.Equals(ByteString(kIPV6MaskBytes, sizeof(kIPV6MaskBytes))));
pattern.Clear();
expected_pattern.Clear();
mask.Clear();
CreateIPAddressPatternAndMask(IPAddress(kIPV6Address6), &pattern, &mask);
expected_pattern =
CreatePattern(kIPV6PatternPrefix, sizeof(kIPV6PatternPrefix),
kIPV6Address6Bytes, sizeof(kIPV6Address6Bytes));
EXPECT_TRUE(pattern.Equals(expected_pattern));
EXPECT_TRUE(mask.Equals(ByteString(kIPV6MaskBytes, sizeof(kIPV6MaskBytes))));
pattern.Clear();
expected_pattern.Clear();
mask.Clear();
CreateIPAddressPatternAndMask(IPAddress(kIPV6Address7), &pattern, &mask);
expected_pattern =
CreatePattern(kIPV6PatternPrefix, sizeof(kIPV6PatternPrefix),
kIPV6Address7Bytes, sizeof(kIPV6Address7Bytes));
EXPECT_TRUE(pattern.Equals(expected_pattern));
EXPECT_TRUE(mask.Equals(ByteString(kIPV6MaskBytes, sizeof(kIPV6MaskBytes))));
}
TEST_F(WakeOnWiFiTest, ConfigureWiphyIndex) {
SetWakeOnPacketConnMessage msg;
uint32_t value;
EXPECT_FALSE(
msg.attributes()->GetU32AttributeValue(NL80211_ATTR_WIPHY, &value));
ConfigureWiphyIndex(&msg, 137);
EXPECT_TRUE(
msg.attributes()->GetU32AttributeValue(NL80211_ATTR_WIPHY, &value));
EXPECT_EQ(value, 137);
}
TEST_F(WakeOnWiFiTest, ConfigureDisableWakeOnWiFiMessage) {
SetWakeOnPacketConnMessage msg;
Error e;
uint32_t value;
EXPECT_FALSE(
msg.attributes()->GetU32AttributeValue(NL80211_ATTR_WIPHY, &value));
ConfigureDisableWakeOnWiFiMessage(&msg, 57, &e);
EXPECT_EQ(e.type(), Error::Type::kSuccess);
EXPECT_TRUE(
msg.attributes()->GetU32AttributeValue(NL80211_ATTR_WIPHY, &value));
EXPECT_EQ(value, 57);
}
TEST_F(WakeOnWiFiTest, WakeOnWiFiSettingsMatch) {
IPAddressStore all_addresses;
set<WakeOnWiFi::WakeOnWiFiTrigger> trigs;
GetWakeOnPacketConnMessage msg0;
msg0.InitFromNlmsg(
reinterpret_cast<const nlmsghdr *>(kResponseNoIPAddresses));
EXPECT_TRUE(WakeOnWiFiSettingsMatch(msg0, trigs, all_addresses));
trigs.insert(WakeOnWiFi::kIPAddress);
all_addresses.AddUnique(
IPAddress(string(kIPV4Address0, sizeof(kIPV4Address0))));
GetWakeOnPacketConnMessage msg1;
msg1.InitFromNlmsg(reinterpret_cast<const nlmsghdr *>(kResponseIPV40));
EXPECT_TRUE(WakeOnWiFiSettingsMatch(msg1, trigs, all_addresses));
EXPECT_FALSE(WakeOnWiFiSettingsMatch(msg0, trigs, all_addresses));
// Test matching of wake-on-disconnect flag.
trigs.insert(WakeOnWiFi::kDisconnect);
GetWakeOnPacketConnMessage msg2;
msg2.InitFromNlmsg(
reinterpret_cast<const nlmsghdr *>(kResponseIPV40WakeOnDisconnect));
EXPECT_TRUE(WakeOnWiFiSettingsMatch(msg2, trigs, all_addresses));
EXPECT_FALSE(WakeOnWiFiSettingsMatch(msg1, trigs, all_addresses));
EXPECT_FALSE(WakeOnWiFiSettingsMatch(msg0, trigs, all_addresses));
trigs.erase(WakeOnWiFi::kDisconnect);
all_addresses.AddUnique(
IPAddress(string(kIPV4Address1, sizeof(kIPV4Address1))));
GetWakeOnPacketConnMessage msg3;
msg3.InitFromNlmsg(reinterpret_cast<const nlmsghdr *>(kResponseIPV401));
EXPECT_TRUE(WakeOnWiFiSettingsMatch(msg3, trigs, all_addresses));
EXPECT_FALSE(WakeOnWiFiSettingsMatch(msg2, trigs, all_addresses));
EXPECT_FALSE(WakeOnWiFiSettingsMatch(msg1, trigs, all_addresses));
EXPECT_FALSE(WakeOnWiFiSettingsMatch(msg0, trigs, all_addresses));
all_addresses.AddUnique(
IPAddress(string(kIPV6Address0, sizeof(kIPV6Address0))));
GetWakeOnPacketConnMessage msg4;
msg4.InitFromNlmsg(reinterpret_cast<const nlmsghdr *>(kResponseIPV401IPV60));
EXPECT_TRUE(WakeOnWiFiSettingsMatch(msg4, trigs, all_addresses));
EXPECT_FALSE(WakeOnWiFiSettingsMatch(msg3, trigs, all_addresses));
EXPECT_FALSE(WakeOnWiFiSettingsMatch(msg2, trigs, all_addresses));
EXPECT_FALSE(WakeOnWiFiSettingsMatch(msg1, trigs, all_addresses));
EXPECT_FALSE(WakeOnWiFiSettingsMatch(msg0, trigs, all_addresses));
all_addresses.AddUnique(
IPAddress(string(kIPV6Address1, sizeof(kIPV6Address1))));
GetWakeOnPacketConnMessage msg5;
msg5.InitFromNlmsg(reinterpret_cast<const nlmsghdr *>(kResponseIPV401IPV601));
EXPECT_TRUE(WakeOnWiFiSettingsMatch(msg5, trigs, all_addresses));
EXPECT_FALSE(WakeOnWiFiSettingsMatch(msg4, trigs, all_addresses));
EXPECT_FALSE(WakeOnWiFiSettingsMatch(msg3, trigs, all_addresses));
EXPECT_FALSE(WakeOnWiFiSettingsMatch(msg2, trigs, all_addresses));
EXPECT_FALSE(WakeOnWiFiSettingsMatch(msg1, trigs, all_addresses));
EXPECT_FALSE(WakeOnWiFiSettingsMatch(msg0, trigs, all_addresses));
}
TEST_F(WakeOnWiFiTest, ConfigureSetWakeOnWiFiSettingsMessage) {
IPAddressStore all_addresses;
set<WakeOnWiFi::WakeOnWiFiTrigger> trigs;
int index = 1; // wiphy device number
SetWakeOnPacketConnMessage msg0;
Error e;
trigs.insert(WakeOnWiFi::kIPAddress);
all_addresses.AddUnique(
IPAddress(string(kIPV4Address0, sizeof(kIPV4Address0))));
ByteString expected_mask = ByteString(kIPV4MaskBytes, sizeof(kIPV4MaskBytes));
ByteString expected_pattern =
CreatePattern(kIPV4PatternPrefix, sizeof(kIPV4PatternPrefix),
kIPV4Address0Bytes, sizeof(kIPV4Address0Bytes));
ConfigureSetWakeOnWiFiSettingsMessage(&msg0, trigs, all_addresses, index, &e);
EXPECT_TRUE(WakeOnWiFiSettingsMatch(msg0, trigs, all_addresses));
SetWakeOnPacketConnMessage msg1;
all_addresses.AddUnique(
IPAddress(string(kIPV4Address1, sizeof(kIPV4Address1))));
expected_pattern =
CreatePattern(kIPV4PatternPrefix, sizeof(kIPV4PatternPrefix),
kIPV4Address1Bytes, sizeof(kIPV4Address1Bytes));
ConfigureSetWakeOnWiFiSettingsMessage(&msg1, trigs, all_addresses, index, &e);
EXPECT_TRUE(WakeOnWiFiSettingsMatch(msg1, trigs, all_addresses));
SetWakeOnPacketConnMessage msg2;
all_addresses.AddUnique(
IPAddress(string(kIPV6Address0, sizeof(kIPV6Address0))));
expected_mask = ByteString(kIPV6MaskBytes, sizeof(kIPV6MaskBytes));
expected_pattern =
CreatePattern(kIPV6PatternPrefix, sizeof(kIPV6PatternPrefix),
kIPV6Address0Bytes, sizeof(kIPV6Address0Bytes));
ConfigureSetWakeOnWiFiSettingsMessage(&msg2, trigs, all_addresses, index, &e);
EXPECT_TRUE(WakeOnWiFiSettingsMatch(msg2, trigs, all_addresses));
SetWakeOnPacketConnMessage msg3;
all_addresses.AddUnique(
IPAddress(string(kIPV6Address1, sizeof(kIPV6Address1))));
expected_pattern =
CreatePattern(kIPV6PatternPrefix, sizeof(kIPV6PatternPrefix),
kIPV6Address1Bytes, sizeof(kIPV6Address1Bytes));
ConfigureSetWakeOnWiFiSettingsMessage(&msg3, trigs, all_addresses, index, &e);
EXPECT_TRUE(WakeOnWiFiSettingsMatch(msg3, trigs, all_addresses));
SetWakeOnPacketConnMessage msg4;
all_addresses.AddUnique(
IPAddress(string(kIPV6Address2, sizeof(kIPV6Address2))));
expected_pattern =
CreatePattern(kIPV6PatternPrefix, sizeof(kIPV6PatternPrefix),
kIPV6Address2Bytes, sizeof(kIPV6Address2Bytes));
ConfigureSetWakeOnWiFiSettingsMessage(&msg4, trigs, all_addresses, index, &e);
EXPECT_TRUE(WakeOnWiFiSettingsMatch(msg4, trigs, all_addresses));
SetWakeOnPacketConnMessage msg5;
all_addresses.AddUnique(
IPAddress(string(kIPV6Address3, sizeof(kIPV6Address3))));
expected_pattern =
CreatePattern(kIPV6PatternPrefix, sizeof(kIPV6PatternPrefix),
kIPV6Address3Bytes, sizeof(kIPV6Address3Bytes));
ConfigureSetWakeOnWiFiSettingsMessage(&msg5, trigs, all_addresses, index, &e);
EXPECT_TRUE(WakeOnWiFiSettingsMatch(msg5, trigs, all_addresses));
SetWakeOnPacketConnMessage msg6;
all_addresses.AddUnique(
IPAddress(string(kIPV6Address4, sizeof(kIPV6Address4))));
expected_pattern =
CreatePattern(kIPV6PatternPrefix, sizeof(kIPV6PatternPrefix),
kIPV6Address4Bytes, sizeof(kIPV6Address4Bytes));
ConfigureSetWakeOnWiFiSettingsMessage(&msg6, trigs, all_addresses, index, &e);
EXPECT_TRUE(WakeOnWiFiSettingsMatch(msg6, trigs, all_addresses));
SetWakeOnPacketConnMessage msg7;
all_addresses.AddUnique(
IPAddress(string(kIPV6Address5, sizeof(kIPV6Address5))));
expected_pattern =
CreatePattern(kIPV6PatternPrefix, sizeof(kIPV6PatternPrefix),
kIPV6Address5Bytes, sizeof(kIPV6Address5Bytes));
ConfigureSetWakeOnWiFiSettingsMessage(&msg7, trigs, all_addresses, index, &e);
EXPECT_TRUE(WakeOnWiFiSettingsMatch(msg7, trigs, all_addresses));
SetWakeOnPacketConnMessage msg8;
all_addresses.AddUnique(
IPAddress(string(kIPV6Address6, sizeof(kIPV6Address6))));
expected_pattern =
CreatePattern(kIPV6PatternPrefix, sizeof(kIPV6PatternPrefix),
kIPV6Address6Bytes, sizeof(kIPV6Address6Bytes));
ConfigureSetWakeOnWiFiSettingsMessage(&msg8, trigs, all_addresses, index, &e);
EXPECT_TRUE(WakeOnWiFiSettingsMatch(msg8, trigs, all_addresses));
SetWakeOnPacketConnMessage msg9;
all_addresses.AddUnique(
IPAddress(string(kIPV6Address7, sizeof(kIPV6Address7))));
expected_pattern =
CreatePattern(kIPV6PatternPrefix, sizeof(kIPV6PatternPrefix),
kIPV6Address7Bytes, sizeof(kIPV6Address7Bytes));
ConfigureSetWakeOnWiFiSettingsMessage(&msg9, trigs, all_addresses, index, &e);
EXPECT_TRUE(WakeOnWiFiSettingsMatch(msg9, trigs, all_addresses));
}
TEST_F(WakeOnWiFiTest, AddRemoveWakeOnPacketConnection) {
const string ip_string1("192.168.0.19");
const string ip_string2("192.168.0.55");
const string ip_string3("192.168.0.74");
IPAddress ip_addr1(ip_string1);
IPAddress ip_addr2(ip_string2);
IPAddress ip_addr3(ip_string3);
Error e;
// Add and remove operations will fail if WiFi device does not support
// pattern matching.
ClearWakeOnWiFiTriggersSupported();
AddWakeOnPacketConnection(ip_addr1, &e);
EXPECT_EQ(e.type(), Error::kNotSupported);
EXPECT_STREQ(e.message().c_str(),
"Wake on IP address patterns not supported by this WiFi device");
RemoveAllWakeOnPacketConnections(&e);
EXPECT_EQ(e.type(), Error::kNotSupported);
EXPECT_STREQ(e.message().c_str(),
"Wake on IP address patterns not supported by this WiFi device");
RemoveWakeOnPacketConnection(ip_addr2, &e);
EXPECT_EQ(e.type(), Error::kNotSupported);
EXPECT_STREQ(e.message().c_str(),
"Wake on IP address patterns not supported by this WiFi device");
// Add operation will fail if pattern matching is supported but the max number
// of IP address patterns have already been registered.
GetWakeOnWiFiTriggersSupported()->insert(WakeOnWiFi::kIPAddress);
SetWakeOnWiFiMaxPatterns(0);
AddWakeOnPacketConnection(ip_addr1, &e);
EXPECT_EQ(e.type(), Error::kOperationFailed);
EXPECT_STREQ(e.message().c_str(),
"Max number of IP address patterns already registered");
SetWakeOnWiFiMaxPatterns(50);
GetWakeOnPacketConnections()->Clear();
EXPECT_TRUE(GetWakeOnPacketConnections()->Empty());
AddWakeOnPacketConnection(ip_addr1, &e);
EXPECT_EQ(GetWakeOnPacketConnections()->Count(), 1);
EXPECT_TRUE(GetWakeOnPacketConnections()->Contains(ip_addr1));
EXPECT_FALSE(GetWakeOnPacketConnections()->Contains(ip_addr2));
EXPECT_FALSE(GetWakeOnPacketConnections()->Contains(ip_addr3));
AddWakeOnPacketConnection(ip_addr2, &e);
EXPECT_EQ(GetWakeOnPacketConnections()->Count(), 2);
EXPECT_TRUE(GetWakeOnPacketConnections()->Contains(ip_addr1));
EXPECT_TRUE(GetWakeOnPacketConnections()->Contains(ip_addr2));
EXPECT_FALSE(GetWakeOnPacketConnections()->Contains(ip_addr3));
AddWakeOnPacketConnection(ip_addr3, &e);
EXPECT_EQ(GetWakeOnPacketConnections()->Count(), 3);
EXPECT_TRUE(GetWakeOnPacketConnections()->Contains(ip_addr1));
EXPECT_TRUE(GetWakeOnPacketConnections()->Contains(ip_addr2));
EXPECT_TRUE(GetWakeOnPacketConnections()->Contains(ip_addr3));
RemoveWakeOnPacketConnection(ip_addr2, &e);
EXPECT_EQ(GetWakeOnPacketConnections()->Count(), 2);
EXPECT_TRUE(GetWakeOnPacketConnections()->Contains(ip_addr1));
EXPECT_FALSE(GetWakeOnPacketConnections()->Contains(ip_addr2));
EXPECT_TRUE(GetWakeOnPacketConnections()->Contains(ip_addr3));
// Remove fails if no such address is registered.
RemoveWakeOnPacketConnection(ip_addr2, &e);
EXPECT_EQ(e.type(), Error::kNotFound);
EXPECT_STREQ(e.message().c_str(),
"No such IP address match registered to wake device");
EXPECT_EQ(GetWakeOnPacketConnections()->Count(), 2);
RemoveWakeOnPacketConnection(ip_addr1, &e);
EXPECT_EQ(GetWakeOnPacketConnections()->Count(), 1);
EXPECT_FALSE(GetWakeOnPacketConnections()->Contains(ip_addr1));
EXPECT_FALSE(GetWakeOnPacketConnections()->Contains(ip_addr2));
EXPECT_TRUE(GetWakeOnPacketConnections()->Contains(ip_addr3));
AddWakeOnPacketConnection(ip_addr2, &e);
EXPECT_EQ(GetWakeOnPacketConnections()->Count(), 2);
EXPECT_FALSE(GetWakeOnPacketConnections()->Contains(ip_addr1));
EXPECT_TRUE(GetWakeOnPacketConnections()->Contains(ip_addr2));
EXPECT_TRUE(GetWakeOnPacketConnections()->Contains(ip_addr3));
RemoveAllWakeOnPacketConnections(&e);
EXPECT_EQ(GetWakeOnPacketConnections()->Count(), 0);
EXPECT_FALSE(GetWakeOnPacketConnections()->Contains(ip_addr1));
EXPECT_FALSE(GetWakeOnPacketConnections()->Contains(ip_addr2));
EXPECT_FALSE(GetWakeOnPacketConnections()->Contains(ip_addr3));
}
TEST_F(WakeOnWiFiTest, RequestWakeOnPacketSettings) {
EXPECT_CALL(
netlink_manager_,
SendNl80211Message(IsNl80211Command(kNl80211FamilyId,
GetWakeOnPacketConnMessage::kCommand),
_, _, _)).Times(1);
RequestWakeOnPacketSettings();
}
MATCHER_P(ErrorType, type, "") { return arg.type() == type; }
TEST_F(WakeOnWiFiTest, VerifyWakeOnWiFiSettings_NoWakeOnPacketRules) {
ScopedMockLog log;
// Create an Nl80211 response to a NL80211_CMD_GET_WOWLAN request
// indicating that there are no wake-on-packet rules programmed into the NIC.
GetWakeOnPacketConnMessage msg;
msg.InitFromNlmsg(reinterpret_cast<const nlmsghdr *>(kResponseNoIPAddresses));
// Successful verification and consequent invocation of callback.
SetSuspendActionsDoneCallback();
ScopeLogger::GetInstance()->EnableScopesByName("wifi");
ScopeLogger::GetInstance()->set_verbose_level(2);
EXPECT_TRUE(GetWakeOnPacketConnections()->Empty());
EXPECT_FALSE(SuspendActionsCallbackIsNull());
EXPECT_CALL(*this, SuspendCallback(ErrorType(Error::kSuccess))).Times(1);
EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
EXPECT_CALL(log, Log(_, _, EndsWith("successfully verified")));
VerifyWakeOnWiFiSettings(msg);
// Suspend action callback cleared after being invoked.
EXPECT_TRUE(SuspendActionsCallbackIsNull());
ScopeLogger::GetInstance()->EnableScopesByName("-wifi");
ScopeLogger::GetInstance()->set_verbose_level(0);
// Unsuccessful verification if locally stored settings do not match.
GetWakeOnPacketConnections()->AddUnique(IPAddress("1.1.1.1"));
GetWakeOnWiFiTriggers()->insert(WakeOnWiFi::kIPAddress);
EXPECT_CALL(log, Log(logging::LOG_ERROR, _, EndsWith("structure detected")));
VerifyWakeOnWiFiSettings(msg);
}
TEST_F(WakeOnWiFiTest,
VerifyWakeOnWiFiSettings_WakeOnPatternAndDisconnectRules) {
ScopedMockLog log;
// Create a non-trivial Nl80211 response to a NL80211_CMD_GET_WOWLAN request
// indicating that that the NIC wakes on packets from 192.168.10.20 and on
// disconnects.
GetWakeOnPacketConnMessage msg;
msg.InitFromNlmsg(
reinterpret_cast<const nlmsghdr *>(kResponseIPV40WakeOnDisconnect));
// Successful verification and consequent invocation of callback.
SetSuspendActionsDoneCallback();
EXPECT_FALSE(SuspendActionsCallbackIsNull());
GetWakeOnPacketConnections()->AddUnique(IPAddress("192.168.10.20"));
GetWakeOnWiFiTriggers()->insert(WakeOnWiFi::kIPAddress);
GetWakeOnWiFiTriggers()->insert(WakeOnWiFi::kDisconnect);
ScopeLogger::GetInstance()->EnableScopesByName("wifi");
ScopeLogger::GetInstance()->set_verbose_level(2);
EXPECT_CALL(*this, SuspendCallback(ErrorType(Error::kSuccess))).Times(1);
EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
EXPECT_CALL(log, Log(_, _, EndsWith("successfully verified")));
VerifyWakeOnWiFiSettings(msg);
// Suspend action callback cleared after being invoked.
EXPECT_TRUE(SuspendActionsCallbackIsNull());
ScopeLogger::GetInstance()->EnableScopesByName("-wifi");
ScopeLogger::GetInstance()->set_verbose_level(0);
// Unsuccessful verification if locally stored settings do not match.
GetWakeOnWiFiTriggers()->erase(WakeOnWiFi::kDisconnect);
EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
EXPECT_CALL(log, Log(logging::LOG_ERROR, _, EndsWith("structure detected")));
VerifyWakeOnWiFiSettings(msg);
}
TEST_F(WakeOnWiFiTest, VerifyWakeOnWiFiSettingsSuccess_NoSuspendCallback) {
ScopedMockLog log;
// Create an Nl80211 response to a NL80211_CMD_GET_WOWLAN request
// indicating that there are no wake-on-packet rules programmed into the NIC.
GetWakeOnPacketConnMessage msg;
msg.InitFromNlmsg(reinterpret_cast<const nlmsghdr *>(kResponseNoIPAddresses));
// Successful verification, but since there is no suspend action callback
// set, no callback is invoked.
EXPECT_TRUE(SuspendActionsCallbackIsNull());
EXPECT_TRUE(GetWakeOnPacketConnections()->Empty());
ScopeLogger::GetInstance()->EnableScopesByName("wifi");
ScopeLogger::GetInstance()->set_verbose_level(2);
EXPECT_CALL(*this, SuspendCallback(_)).Times(0);
EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
EXPECT_CALL(log, Log(_, _, EndsWith("successfully verified")));
VerifyWakeOnWiFiSettings(msg);
ScopeLogger::GetInstance()->EnableScopesByName("-wifi");
ScopeLogger::GetInstance()->set_verbose_level(0);
}
TEST_F(WakeOnWiFiTest, RetrySetWakeOnPacketConnections_LessThanMaxRetries) {
ScopedMockLog log;
// Max retries not reached yet, so send Nl80211 message to program NIC again.
SetNumSetWakeOnPacketRetries(WakeOnWiFi::kMaxSetWakeOnPacketRetries - 1);
EXPECT_CALL(
netlink_manager_,
SendNl80211Message(IsNl80211Command(kNl80211FamilyId,
SetWakeOnPacketConnMessage::kCommand),
_, _, _)).Times(1);
RetrySetWakeOnPacketConnections();
EXPECT_EQ(GetNumSetWakeOnPacketRetries(),
WakeOnWiFi::kMaxSetWakeOnPacketRetries);
}
TEST_F(WakeOnWiFiTest,
RetrySetWakeOnPacketConnections_MaxAttemptsWithCallbackSet) {
ScopedMockLog log;
// Max retry attempts reached. Suspend actions done callback is set, so it
// is invoked.
SetNumSetWakeOnPacketRetries(WakeOnWiFi::kMaxSetWakeOnPacketRetries);
SetSuspendActionsDoneCallback();
ScopeLogger::GetInstance()->EnableScopesByName("wifi");
ScopeLogger::GetInstance()->set_verbose_level(2);
EXPECT_FALSE(SuspendActionsCallbackIsNull());
EXPECT_CALL(*this, SuspendCallback(ErrorType(Error::kOperationFailed)))
.Times(1);
EXPECT_CALL(netlink_manager_, SendNl80211Message(_, _, _, _)).Times(0);
EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
EXPECT_CALL(log, Log(_, _, EndsWith("max retry attempts reached")));
RetrySetWakeOnPacketConnections();
EXPECT_TRUE(SuspendActionsCallbackIsNull());
EXPECT_EQ(GetNumSetWakeOnPacketRetries(), 0);
ScopeLogger::GetInstance()->EnableScopesByName("-wifi");
ScopeLogger::GetInstance()->set_verbose_level(0);
}
TEST_F(WakeOnWiFiTest,
RetrySetWakeOnPacketConnections_MaxAttemptsCallbackUnset) {
ScopedMockLog log;
// If there is no suspend action callback set, no suspend callback should be
// invoked.
SetNumSetWakeOnPacketRetries(WakeOnWiFi::kMaxSetWakeOnPacketRetries);
ScopeLogger::GetInstance()->EnableScopesByName("wifi");
ScopeLogger::GetInstance()->set_verbose_level(2);
EXPECT_TRUE(SuspendActionsCallbackIsNull());
EXPECT_CALL(*this, SuspendCallback(_)).Times(0);
EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
EXPECT_CALL(log, Log(_, _, EndsWith("max retry attempts reached")));
RetrySetWakeOnPacketConnections();
ScopeLogger::GetInstance()->EnableScopesByName("-wifi");
ScopeLogger::GetInstance()->set_verbose_level(0);
}
TEST_F(WakeOnWiFiTest, ParseWiphyIndex_Success) {
// Verify that the wiphy index in kNewWiphyNlMsg is parsed, and that the flag
// for having the wiphy index is set by ParseWiphyIndex.
SetWiphyIndexReceivedToFalse();
EXPECT_FALSE(GetWiphyIndexReceived());
EXPECT_EQ(GetWiphyIndex(), WakeOnWiFi::kDefaultWiphyIndex);
NewWiphyMessage msg;
msg.InitFromNlmsg(reinterpret_cast<const nlmsghdr *>(kNewWiphyNlMsg));
ParseWiphyIndex(msg);
EXPECT_EQ(GetWiphyIndex(), kNewWiphyNlMsg_WiphyIndex);
EXPECT_TRUE(GetWiphyIndexReceived());
}
TEST_F(WakeOnWiFiTest, ParseWiphyIndex_Failure) {
ScopedMockLog log;
SetWiphyIndexReceivedToFalse();
EXPECT_FALSE(GetWiphyIndexReceived());
// Change the NL80211_ATTR_WIPHY U32 attribute to the NL80211_ATTR_WIPHY_FREQ
// U32 attribute, so that this message no longer contains a wiphy_index to be
// parsed.
NewWiphyMessage msg;
uint8_t message_memory[sizeof(kNewWiphyNlMsg)];
memcpy(message_memory, kNewWiphyNlMsg, sizeof(kNewWiphyNlMsg));
struct nlattr *nl80211_attr_wiphy = reinterpret_cast<struct nlattr *>(
&message_memory[kNewWiphyNlMsg_Nl80211AttrWiphyOffset]);
nl80211_attr_wiphy->nla_type = NL80211_ATTR_WIPHY_FREQ;
msg.InitFromNlmsg(reinterpret_cast<const nlmsghdr *>(message_memory));
EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
EXPECT_CALL(log,
Log(_, _, "NL80211_CMD_NEW_WIPHY had no NL80211_ATTR_WIPHY"));
ParseWiphyIndex(msg);
// Since we failed to find NL80211_ATTR_WIPHY in the message,
// |wiphy_index_received| should remain false.
EXPECT_FALSE(GetWiphyIndexReceived());
}
TEST_F(WakeOnWiFiTest,
ParseWakeOnWiFiCapabilities_DisconnectAndPatternSupported) {
ClearWakeOnWiFiTriggersSupported();
NewWiphyMessage msg;
msg.InitFromNlmsg(reinterpret_cast<const nlmsghdr *>(kNewWiphyNlMsg));
ParseWakeOnWiFiCapabilities(msg);
EXPECT_TRUE(GetWakeOnWiFiTriggersSupported()->find(WakeOnWiFi::kDisconnect) !=
GetWakeOnWiFiTriggersSupported()->end());
EXPECT_TRUE(GetWakeOnWiFiTriggersSupported()->find(WakeOnWiFi::kIPAddress) !=
GetWakeOnWiFiTriggersSupported()->end());
EXPECT_EQ(GetWakeOnWiFiMaxPatterns(), kNewWiphyNlMsg_MaxPatterns);
}
TEST_F(WakeOnWiFiTest, ParseWakeOnWiFiCapabilities_UnsupportedPatternLen) {
ClearWakeOnWiFiTriggersSupported();
NewWiphyMessage msg;
// Modify the range of support pattern lengths to [0-1] bytes, which is less
// than what we need to use our IPV4 (30 bytes) or IPV6 (38 bytes) patterns.
uint8_t message_memory[sizeof(kNewWiphyNlMsg)];
memcpy(message_memory, kNewWiphyNlMsg, sizeof(kNewWiphyNlMsg));
struct nl80211_pattern_support *patt_support =
reinterpret_cast<struct nl80211_pattern_support *>(
&message_memory[kNewWiphyNlMsg_PattSupportOffset]);
patt_support->min_pattern_len = 0;
patt_support->max_pattern_len = 1;
msg.InitFromNlmsg(reinterpret_cast<const nlmsghdr *>(message_memory));
ParseWakeOnWiFiCapabilities(msg);
EXPECT_TRUE(GetWakeOnWiFiTriggersSupported()->find(WakeOnWiFi::kDisconnect) !=
GetWakeOnWiFiTriggersSupported()->end());
// Ensure that ParseWakeOnWiFiCapabilities realizes that our IP address
// patterns cannot be used given the support pattern length range reported.
EXPECT_FALSE(GetWakeOnWiFiTriggersSupported()->find(WakeOnWiFi::kIPAddress) !=
GetWakeOnWiFiTriggersSupported()->end());
}
TEST_F(WakeOnWiFiTest, ParseWakeOnWiFiCapabilities_DisconnectNotSupported) {
ClearWakeOnWiFiTriggersSupported();
NewWiphyMessage msg;
// Change the NL80211_WOWLAN_TRIG_DISCONNECT flag attribute into the
// NL80211_WOWLAN_TRIG_MAGIC_PKT flag attribute, so that this message
// no longer reports wake on disconnect as a supported capability.
uint8_t message_memory[sizeof(kNewWiphyNlMsg)];
memcpy(message_memory, kNewWiphyNlMsg, sizeof(kNewWiphyNlMsg));
struct nlattr *wowlan_trig_disconnect_attr =
reinterpret_cast<struct nlattr *>(
&message_memory[kNewWiphyNlMsg_WowlanTrigDisconnectAttributeOffset]);
wowlan_trig_disconnect_attr->nla_type = NL80211_WOWLAN_TRIG_MAGIC_PKT;
msg.InitFromNlmsg(reinterpret_cast<const nlmsghdr *>(message_memory));
ParseWakeOnWiFiCapabilities(msg);
EXPECT_TRUE(GetWakeOnWiFiTriggersSupported()->find(WakeOnWiFi::kIPAddress) !=
GetWakeOnWiFiTriggersSupported()->end());
// Ensure that ParseWakeOnWiFiCapabilities realizes that wake on disconnect
// is not supported.
EXPECT_FALSE(
GetWakeOnWiFiTriggersSupported()->find(WakeOnWiFi::kDisconnect) !=
GetWakeOnWiFiTriggersSupported()->end());
}
TEST_F(WakeOnWiFiTest, ApplyWakeOnWiFiSettings_WiphyIndexNotReceived) {
// ApplyWakeOnWiFiSettings should return immediately if the wifi interface
// index has not been received when the function is called.
SetWiphyIndexReceivedToFalse();
EXPECT_CALL(netlink_manager_,
SendNl80211Message(IsDisableWakeOnWiFiMsg(), _, _, _)).Times(0);
ApplyWakeOnWiFiSettings();
}
TEST_F(WakeOnWiFiTest, ApplyWakeOnWiFiSettings_WiphyIndexReceived) {
// Disable wake on WiFi if there are no wake on WiFi triggers registered.
EXPECT_CALL(
netlink_manager_,
SendNl80211Message(IsNl80211Command(kNl80211FamilyId,
SetWakeOnPacketConnMessage::kCommand),
_, _, _)).Times(0);
EXPECT_CALL(netlink_manager_,
SendNl80211Message(IsDisableWakeOnWiFiMsg(), _, _, _)).Times(1);
ApplyWakeOnWiFiSettings();
// Otherwise, program the NIC.
IPAddress ip_addr("1.1.1.1");
GetWakeOnPacketConnections()->AddUnique(ip_addr);
GetWakeOnWiFiTriggers()->insert(WakeOnWiFi::kIPAddress);
EXPECT_FALSE(GetWakeOnPacketConnections()->Empty());
EXPECT_CALL(
netlink_manager_,
SendNl80211Message(IsNl80211Command(kNl80211FamilyId,
SetWakeOnPacketConnMessage::kCommand),
_, _, _)).Times(1);
EXPECT_CALL(netlink_manager_,
SendNl80211Message(IsDisableWakeOnWiFiMsg(), _, _, _)).Times(0);
ApplyWakeOnWiFiSettings();
}
TEST_F(WakeOnWiFiTest, WakeOnWiFiSettingsAppliedBeforeSuspend) {
// When wake_on_packet_connections_ is empty, do not program the NIC and
// immediately invoke the callback to report success.
EXPECT_TRUE(GetWakeOnPacketConnections()->Empty());
EXPECT_CALL(*this, SuspendCallback(ErrorType(Error::kSuccess))).Times(1);
EXPECT_CALL(
netlink_manager_,
SendNl80211Message(IsNl80211Command(kNl80211FamilyId,
SetWakeOnPacketConnMessage::kCommand),
_, _, _)).Times(0);
OnBeforeSuspend();
dispatcher_.DispatchPendingEvents();
// When wake_on_packet_connections_ is not empty, program NIC to wake on
// IP address patterns.
IPAddress ip_addr("1.1.1.1");
GetWakeOnPacketConnections()->AddUnique(ip_addr);
EXPECT_CALL(*this, SuspendCallback(_)).Times(0);
EXPECT_CALL(
netlink_manager_,
SendNl80211Message(IsNl80211Command(kNl80211FamilyId,
SetWakeOnPacketConnMessage::kCommand),
_, _, _)).Times(1);
EXPECT_CALL(netlink_manager_,
SendNl80211Message(IsDisableWakeOnWiFiMsg(), _, _, _)).Times(0);
OnBeforeSuspend();
dispatcher_.DispatchPendingEvents();
EXPECT_FALSE(GetWakeOnWiFiTriggers()->empty());
EXPECT_TRUE(GetWakeOnWiFiTriggers()->find(WakeOnWiFi::kIPAddress) !=
GetWakeOnWiFiTriggers()->end());
}
TEST_F(WakeOnWiFiTest, WakeOnWiFiDisabledAfterResume) {
EXPECT_CALL(netlink_manager_,
SendNl80211Message(IsDisableWakeOnWiFiMsg(), _, _, _)).Times(1);
OnAfterResume();
EXPECT_TRUE(GetWakeOnWiFiTriggers()->empty());
}
} // namespace shill