108b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz/*
208b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz * Copyright (C) 2017 The Android Open Source Project
308b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz *
408b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz * Licensed under the Apache License, Version 2.0 (the "License");
508b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz * you may not use this file except in compliance with the License.
608b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz * You may obtain a copy of the License at
708b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz *
808b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz *      http://www.apache.org/licenses/LICENSE-2.0
908b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz *
1008b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz * Unless required by applicable law or agreed to in writing, software
1108b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz * distributed under the License is distributed on an "AS IS" BASIS,
1208b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1308b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz * See the License for the specific language governing permissions and
1408b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz * limitations under the License.
1508b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz */
1608b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz
1708b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz#include <linux/netfilter/nfnetlink_log.h>
1808b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz
19e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi#include <arpa/inet.h>
20e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi#include <sys/socket.h>
21e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi#include <netinet/in.h>
22e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi#include <netinet/ip.h>
23e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi#include <netinet/tcp.h>
24e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi
2508b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz#include <gmock/gmock.h>
2608b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz#include <gtest/gtest.h>
2708b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz
2808b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz#include "NetlinkManager.h"
2908b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz#include "WakeupController.h"
3008b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz
3108b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelzusing ::testing::StrictMock;
3208b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelzusing ::testing::Test;
3308b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelzusing ::testing::DoAll;
3408b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelzusing ::testing::SaveArg;
3508b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelzusing ::testing::Return;
3608b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelzusing ::testing::_;
3708b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz
3808b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelznamespace android {
3908b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelznamespace net {
4008b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz
41e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichiconst uint32_t kDefaultPacketCopyRange = WakeupController::kDefaultPacketCopyRange;
42e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi
4308b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelzusing netdutils::status::ok;
4408b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz
4508b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelzclass MockNetdEventListener {
4608b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz  public:
47e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi    MOCK_METHOD10(onWakeupEvent, void(
48e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi            const std::string& prefix, int uid, int ether, int ipNextHeader,
49e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi            std::vector<uint8_t> dstHw, const std::string& srcIp, const std::string& dstIp,
50e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi            int srcPort, int dstPort, uint64_t timestampNs));
5108b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz};
5208b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz
5308b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelzclass MockIptablesRestore : public IptablesRestoreInterface {
5408b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz  public:
5508b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    ~MockIptablesRestore() override = default;
5608b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    MOCK_METHOD3(execute, int(const IptablesTarget target, const std::string& commands,
5708b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz                              std::string* output));
5808b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz};
5908b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz
6008b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelzclass MockNFLogListener : public NFLogListenerInterface {
6108b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz  public:
6208b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    ~MockNFLogListener() override = default;
6308b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    MOCK_METHOD2(subscribe, netdutils::Status(uint16_t nfLogGroup, const DispatchFn& fn));
64e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi    MOCK_METHOD3(subscribe,
65e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi            netdutils::Status(uint16_t nfLogGroup, uint32_t copyRange, const DispatchFn& fn));
6608b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    MOCK_METHOD1(unsubscribe, netdutils::Status(uint16_t nfLogGroup));
6708b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz};
6808b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz
6908b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelzclass WakeupControllerTest : public Test {
7008b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz  protected:
7108b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    WakeupControllerTest() {
72e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi        EXPECT_CALL(mListener,
73e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi            subscribe(NetlinkManager::NFLOG_WAKEUP_GROUP, kDefaultPacketCopyRange, _))
74e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi            .WillOnce(DoAll(SaveArg<2>(&mMessageHandler), Return(ok)));
75e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi        EXPECT_CALL(mListener,
76e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi            unsubscribe(NetlinkManager::NFLOG_WAKEUP_GROUP)).WillOnce(Return(ok));
7708b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz        mController.init(&mListener);
7808b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    }
7908b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz
8008b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    StrictMock<MockNetdEventListener> mEventListener;
8108b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    StrictMock<MockIptablesRestore> mIptables;
8208b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    StrictMock<MockNFLogListener> mListener;
8308b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    WakeupController mController{
84e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi        [this](const WakeupController::ReportArgs& args) {
85e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi            mEventListener.onWakeupEvent(args.prefix, args.uid, args.ethertype, args.ipNextHeader,
86e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi                                         args.dstHw, args.srcIp, args.dstIp, args.srcPort,
87e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi                                         args.dstPort, args.timestampNs);
8808b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz        },
8908b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz        &mIptables};
9008b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    NFLogListenerInterface::DispatchFn mMessageHandler;
9108b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz};
9208b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz
93e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo BenichiTEST_F(WakeupControllerTest, msgHandlerWithPartialAttributes) {
9408b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    const char kPrefix[] = "test:prefix";
9508b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    const uid_t kUid = 8734;
9608b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    const gid_t kGid = 2222;
9708b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    const uint64_t kNsPerS = 1000000000ULL;
9808b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    const uint64_t kTsNs = 9999 + (34 * kNsPerS);
9908b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz
10008b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    struct Msg {
10108b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz        nlmsghdr nlmsg;
10208b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz        nfgenmsg nfmsg;
10308b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz        nlattr uidAttr;
10408b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz        uid_t uid;
10508b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz        nlattr gidAttr;
10608b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz        gid_t gid;
10708b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz        nlattr tsAttr;
10808b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz        timespec ts;
10908b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz        nlattr prefixAttr;
11008b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz        char prefix[sizeof(kPrefix)];
11108b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    } msg = {};
11208b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz
11308b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    msg.uidAttr.nla_type = NFULA_UID;
11408b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    msg.uidAttr.nla_len = sizeof(msg.uidAttr) + sizeof(msg.uid);
115e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi    msg.uid = htonl(kUid);
11608b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz
11708b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    msg.gidAttr.nla_type = NFULA_GID;
11808b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    msg.gidAttr.nla_len = sizeof(msg.gidAttr) + sizeof(msg.gid);
119e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi    msg.gid = htonl(kGid);
12008b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz
12108b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    msg.tsAttr.nla_type = NFULA_TIMESTAMP;
12208b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    msg.tsAttr.nla_len = sizeof(msg.tsAttr) + sizeof(msg.ts);
123e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi    msg.ts.tv_sec = htonl(kTsNs / kNsPerS);
124e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi    msg.ts.tv_nsec = htonl(kTsNs % kNsPerS);
125e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi
126e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi    msg.prefixAttr.nla_type = NFULA_PREFIX;
127e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi    msg.prefixAttr.nla_len = sizeof(msg.prefixAttr) + sizeof(msg.prefix);
128e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi    memcpy(msg.prefix, kPrefix, sizeof(kPrefix));
129e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi
130e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi    auto payload = drop(netdutils::makeSlice(msg), offsetof(Msg, uidAttr));
131e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi    EXPECT_CALL(mEventListener,
132e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi            onWakeupEvent(kPrefix, kUid, -1, -1, std::vector<uint8_t>(), "", "", -1, -1, kTsNs));
133e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi    mMessageHandler(msg.nlmsg, msg.nfmsg, payload);
134e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi}
135e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi
136e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo BenichiTEST_F(WakeupControllerTest, msgHandler) {
137e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi    const char kPrefix[] = "test:prefix";
138e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi    const uid_t kUid = 8734;
139e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi    const gid_t kGid = 2222;
140e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi    const std::vector<uint8_t> kMacAddr = {11, 22, 33, 44, 55, 66};
141e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi    const char* kSrcIpAddr = "192.168.2.1";
142e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi    const char* kDstIpAddr = "192.168.2.23";
143e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi    const uint16_t kEthertype = 0x800;
144e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi    const uint8_t kIpNextHeader = 6;
145e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi    const uint16_t kSrcPort = 1238;
146e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi    const uint16_t kDstPort = 4567;
147e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi    const uint64_t kNsPerS = 1000000000ULL;
148e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi    const uint64_t kTsNs = 9999 + (34 * kNsPerS);
149e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi
150e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi    struct Msg {
151e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi        nlmsghdr nlmsg;
152e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi        nfgenmsg nfmsg;
153e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi        nlattr uidAttr;
154e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi        uid_t uid;
155e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi        nlattr gidAttr;
156e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi        gid_t gid;
157e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi        nlattr tsAttr;
158e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi        timespec ts;
159e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi        nlattr prefixAttr;
160e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi        char prefix[sizeof(kPrefix)];
161e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi        nlattr packetHeaderAttr;
162e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi        struct nfulnl_msg_packet_hdr packetHeader;
163e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi        nlattr hardwareAddrAttr;
164e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi        struct nfulnl_msg_packet_hw hardwareAddr;
165e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi        nlattr packetPayloadAttr;
166e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi        struct iphdr ipHeader;
167e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi        struct tcphdr tcpHeader;
168e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi    } msg = {};
16908b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz
17008b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    msg.prefixAttr.nla_type = NFULA_PREFIX;
17108b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    msg.prefixAttr.nla_len = sizeof(msg.prefixAttr) + sizeof(msg.prefix);
17208b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    memcpy(msg.prefix, kPrefix, sizeof(kPrefix));
17308b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz
174e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi    msg.uidAttr.nla_type = NFULA_UID;
175e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi    msg.uidAttr.nla_len = sizeof(msg.uidAttr) + sizeof(msg.uid);
176e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi    msg.uid = htonl(kUid);
177e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi
178e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi    msg.gidAttr.nla_type = NFULA_GID;
179e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi    msg.gidAttr.nla_len = sizeof(msg.gidAttr) + sizeof(msg.gid);
180e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi    msg.gid = htonl(kGid);
181e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi
182e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi    msg.tsAttr.nla_type = NFULA_TIMESTAMP;
183e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi    msg.tsAttr.nla_len = sizeof(msg.tsAttr) + sizeof(msg.ts);
184e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi    msg.ts.tv_sec = htonl(kTsNs / kNsPerS);
185e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi    msg.ts.tv_nsec = htonl(kTsNs % kNsPerS);
186e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi
187e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi    msg.packetHeaderAttr.nla_type = NFULA_PACKET_HDR;
188e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi    msg.packetHeaderAttr.nla_len = sizeof(msg.packetHeaderAttr) + sizeof(msg.packetHeader);
189e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi    msg.packetHeader.hw_protocol = htons(kEthertype);
190e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi
191e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi    msg.hardwareAddrAttr.nla_type = NFULA_HWADDR;
192e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi    msg.hardwareAddrAttr.nla_len = sizeof(msg.hardwareAddrAttr) + sizeof(msg.hardwareAddr);
193e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi    msg.hardwareAddr.hw_addrlen = htons(kMacAddr.size());
194e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi    std::copy(kMacAddr.begin(), kMacAddr.end(), msg.hardwareAddr.hw_addr);
195e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi
196e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi    msg.packetPayloadAttr.nla_type = NFULA_PAYLOAD;
197e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi    msg.packetPayloadAttr.nla_len =
198e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi            sizeof(msg.packetPayloadAttr) + sizeof(msg.ipHeader) + sizeof(msg.tcpHeader);
199e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi    msg.ipHeader.protocol = IPPROTO_TCP;
200e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi    msg.ipHeader.ihl = sizeof(msg.ipHeader) / 4; // ipv4 IHL counts 32 bit words.
201e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi    inet_pton(AF_INET, kSrcIpAddr, &msg.ipHeader.saddr);
202e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi    inet_pton(AF_INET, kDstIpAddr, &msg.ipHeader.daddr);
203e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi    msg.tcpHeader.th_sport = htons(kSrcPort);
204e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi    msg.tcpHeader.th_dport = htons(kDstPort);
205e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi
20608b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    auto payload = drop(netdutils::makeSlice(msg), offsetof(Msg, uidAttr));
207e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi    EXPECT_CALL(mEventListener, onWakeupEvent(kPrefix, kUid, kEthertype, kIpNextHeader, kMacAddr,
208e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi                                              kSrcIpAddr, kDstIpAddr, kSrcPort, kDstPort, kTsNs));
20908b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    mMessageHandler(msg.nlmsg, msg.nfmsg, payload);
21008b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz}
21108b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz
21208b84cd0d223ae3059ce7d4d55b389fdea187580Joel ScherpelzTEST_F(WakeupControllerTest, badAttr) {
21308b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    const char kPrefix[] = "test:prefix";
21408b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    const uid_t kUid = 8734;
21508b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    const gid_t kGid = 2222;
21608b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    const uint64_t kNsPerS = 1000000000ULL;
21708b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    const uint64_t kTsNs = 9999 + (34 * kNsPerS);
21808b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz
21908b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    struct Msg {
22008b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz        nlmsghdr nlmsg;
22108b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz        nfgenmsg nfmsg;
22208b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz        nlattr uidAttr;
22308b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz        uid_t uid;
22408b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz        nlattr invalid0;
22508b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz        nlattr invalid1;
22608b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz        nlattr gidAttr;
22708b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz        gid_t gid;
22808b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz        nlattr tsAttr;
22908b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz        timespec ts;
23008b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz        nlattr prefixAttr;
23108b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz        char prefix[sizeof(kPrefix)];
23208b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    } msg = {};
23308b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz
23408b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    msg.uidAttr.nla_type = 999;
23508b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    msg.uidAttr.nla_len = sizeof(msg.uidAttr) + sizeof(msg.uid);
236e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi    msg.uid = htonl(kUid);
23708b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz
23808b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    msg.invalid0.nla_type = 0;
23908b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    msg.invalid0.nla_len = 0;
24008b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    msg.invalid1.nla_type = 0;
24108b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    msg.invalid1.nla_len = 1;
24208b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz
24308b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    msg.gidAttr.nla_type = NFULA_GID;
24408b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    msg.gidAttr.nla_len = sizeof(msg.gidAttr) + sizeof(msg.gid);
245e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi    msg.gid = htonl(kGid);
24608b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz
24708b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    msg.tsAttr.nla_type = NFULA_TIMESTAMP;
24808b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    msg.tsAttr.nla_len = sizeof(msg.tsAttr) - 2;
249e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi    msg.ts.tv_sec = htonl(kTsNs / kNsPerS);
250e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi    msg.ts.tv_nsec = htonl(kTsNs % kNsPerS);
25108b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz
25208b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    msg.prefixAttr.nla_type = NFULA_UID;
25308b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    msg.prefixAttr.nla_len = sizeof(msg.prefixAttr) + sizeof(msg.prefix);
25408b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    memcpy(msg.prefix, kPrefix, sizeof(kPrefix));
25508b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz
25608b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    auto payload = drop(netdutils::makeSlice(msg), offsetof(Msg, uidAttr));
257e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi    EXPECT_CALL(mEventListener,
258e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi            onWakeupEvent("", 1952805748, -1, -1, std::vector<uint8_t>(), "", "", -1, -1, 0));
25908b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    mMessageHandler(msg.nlmsg, msg.nfmsg, payload);
26008b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz}
26108b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz
26208b84cd0d223ae3059ce7d4d55b389fdea187580Joel ScherpelzTEST_F(WakeupControllerTest, unterminatedString) {
26308b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    char ones[20] = {};
26408b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    memset(ones, 1, sizeof(ones));
26508b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz
26608b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    struct Msg {
26708b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz        nlmsghdr nlmsg;
26808b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz        nfgenmsg nfmsg;
26908b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz        nlattr prefixAttr;
27008b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz        char prefix[sizeof(ones)];
27108b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    } msg = {};
27208b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz
27308b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    msg.prefixAttr.nla_type = NFULA_PREFIX;
27408b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    msg.prefixAttr.nla_len = sizeof(msg.prefixAttr) + sizeof(msg.prefix);
27508b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    memcpy(msg.prefix, ones, sizeof(ones));
27608b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz
27708b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    const auto expected = std::string(ones, sizeof(ones) - 1);
27808b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    auto payload = drop(netdutils::makeSlice(msg), offsetof(Msg, prefixAttr));
279e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi    EXPECT_CALL(mEventListener,
280e874b7f00ce5bd34a750ed1eb021f50679c6535dHugo Benichi            onWakeupEvent(expected, -1, -1, -1, std::vector<uint8_t>(), "", "", -1, -1, 0));
28108b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    mMessageHandler(msg.nlmsg, msg.nfmsg, payload);
28208b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz}
28308b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz
28408b84cd0d223ae3059ce7d4d55b389fdea187580Joel ScherpelzTEST_F(WakeupControllerTest, addInterface) {
28508b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    const char kPrefix[] = "test:prefix";
28608b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    const char kIfName[] = "wlan8";
28708b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    const uint32_t kMark = 0x12345678;
28808b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    const uint32_t kMask = 0x0F0F0F0F;
28908b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    const char kExpected[] =
29008b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz        "*mangle\n-A wakeupctrl_mangle_INPUT -i test:prefix"
29108b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz        " -j NFLOG --nflog-prefix wlan8 --nflog-group 3 --nflog-threshold 8"
29277660392eb3e9aa287cc02307c443ee64b5fc570Hugo Benichi        " -m mark --mark 0x12345678/0x0f0f0f0f -m limit --limit 10/s\nCOMMIT\n";
29308b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    EXPECT_CALL(mIptables, execute(V4V6, kExpected, _)).WillOnce(Return(0));
29408b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    mController.addInterface(kPrefix, kIfName, kMark, kMask);
29508b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz}
29608b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz
29708b84cd0d223ae3059ce7d4d55b389fdea187580Joel ScherpelzTEST_F(WakeupControllerTest, delInterface) {
29808b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    const char kPrefix[] = "test:prefix";
29908b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    const char kIfName[] = "wlan8";
30008b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    const uint32_t kMark = 0x12345678;
30108b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    const uint32_t kMask = 0xF0F0F0F0;
30208b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    const char kExpected[] =
30308b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz        "*mangle\n-D wakeupctrl_mangle_INPUT -i test:prefix"
30408b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz        " -j NFLOG --nflog-prefix wlan8 --nflog-group 3 --nflog-threshold 8"
30577660392eb3e9aa287cc02307c443ee64b5fc570Hugo Benichi        " -m mark --mark 0x12345678/0xf0f0f0f0 -m limit --limit 10/s\nCOMMIT\n";
30608b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    EXPECT_CALL(mIptables, execute(V4V6, kExpected, _)).WillOnce(Return(0));
30708b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz    mController.delInterface(kPrefix, kIfName, kMark, kMask);
30808b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz}
30908b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz
31008b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz}  // namespace net
31108b84cd0d223ae3059ce7d4d55b389fdea187580Joel Scherpelz}  // namespace android
312