blob: ecde3510ff3b08e4d61e32a6772eecc67e07e354 [file] [log] [blame]
William A. Kennington IIIebb1ad02019-04-21 18:02:49 -07001#include "mock_syscall.hpp"
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -07002#include "neighbor.hpp"
3#include "util.hpp"
4
5#include <arpa/inet.h>
6#include <linux/netlink.h>
7#include <linux/rtnetlink.h>
8#include <net/ethernet.h>
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -07009
10#include <cstring>
11#include <stdexcept>
12#include <string>
13#include <system_error>
14#include <vector>
15
16#include <gtest/gtest.h>
17
18namespace phosphor
19{
20namespace network
21{
22namespace detail
23{
24
William A. Kennington IIIebb1ad02019-04-21 18:02:49 -070025constexpr auto ifStr = "eth0";
26constexpr auto ifIdx = 1;
27
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070028TEST(ParseNeighbor, NotNeighborType)
29{
30 nlmsghdr hdr{};
31 hdr.nlmsg_type = RTM_NEWLINK;
32
33 std::vector<NeighborInfo> neighbors;
34 EXPECT_THROW(parseNeighbor(hdr, "", neighbors), std::runtime_error);
35 EXPECT_EQ(0, neighbors.size());
36}
37
38TEST(ParseNeighbor, SmallMsg)
39{
40 nlmsghdr hdr{};
41 hdr.nlmsg_type = RTM_NEWNEIGH;
42 std::string data = "1";
43
44 std::vector<NeighborInfo> neighbors;
45 EXPECT_THROW(parseNeighbor(hdr, data, neighbors), std::runtime_error);
46 EXPECT_EQ(0, neighbors.size());
47}
48
49TEST(ParseNeighbor, BadIf)
50{
51 nlmsghdr hdr{};
52 hdr.nlmsg_type = RTM_NEWNEIGH;
53 ndmsg msg{};
54 std::string data;
55 data.append(reinterpret_cast<char*>(&msg), sizeof(msg));
56
57 std::vector<NeighborInfo> neighbors;
58 EXPECT_THROW(parseNeighbor(hdr, data, neighbors), std::system_error);
59 EXPECT_EQ(0, neighbors.size());
60}
61
62TEST(ParseNeighbor, NoAttrs)
63{
William A. Kennington III862275a2019-04-22 20:37:08 -070064 mock_clear();
William A. Kennington IIIebb1ad02019-04-21 18:02:49 -070065 mock_addIF(ifStr, ifIdx);
66
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070067 nlmsghdr hdr{};
68 hdr.nlmsg_type = RTM_NEWNEIGH;
69 ndmsg msg{};
William A. Kennington IIIebb1ad02019-04-21 18:02:49 -070070 msg.ndm_ifindex = ifIdx;
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070071 ASSERT_NE(0, msg.ndm_ifindex);
72 std::string data;
73 data.append(reinterpret_cast<char*>(&msg), sizeof(msg));
74
75 std::vector<NeighborInfo> neighbors;
76 EXPECT_THROW(parseNeighbor(hdr, data, neighbors), std::runtime_error);
77 EXPECT_EQ(0, neighbors.size());
78}
79
80TEST(ParseNeighbor, NoAddress)
81{
William A. Kennington III862275a2019-04-22 20:37:08 -070082 mock_clear();
William A. Kennington IIIebb1ad02019-04-21 18:02:49 -070083 mock_addIF(ifStr, ifIdx);
84
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070085 nlmsghdr hdr{};
86 hdr.nlmsg_type = RTM_NEWNEIGH;
87 ndmsg msg{};
William A. Kennington IIIebb1ad02019-04-21 18:02:49 -070088 msg.ndm_ifindex = ifIdx;
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070089 ASSERT_NE(0, msg.ndm_ifindex);
90 ether_addr mac = {{0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa}};
91 rtattr lladdr{};
92 lladdr.rta_len = RTA_LENGTH(sizeof(mac));
93 lladdr.rta_type = NDA_LLADDR;
94 char lladdrbuf[RTA_ALIGN(lladdr.rta_len)];
95 std::memset(lladdrbuf, '\0', sizeof(lladdrbuf));
96 std::memcpy(lladdrbuf, &lladdr, sizeof(lladdr));
97 std::memcpy(RTA_DATA(lladdrbuf), &mac, sizeof(mac));
98 std::string data;
99 data.append(reinterpret_cast<char*>(&msg), sizeof(msg));
100 data.append(reinterpret_cast<char*>(&lladdrbuf), sizeof(lladdrbuf));
101
102 std::vector<NeighborInfo> neighbors;
103 EXPECT_THROW(parseNeighbor(hdr, data, neighbors), std::runtime_error);
104 EXPECT_EQ(0, neighbors.size());
105}
106
107TEST(ParseNeighbor, NoMAC)
108{
William A. Kennington III862275a2019-04-22 20:37:08 -0700109 mock_clear();
William A. Kennington IIIebb1ad02019-04-21 18:02:49 -0700110 mock_addIF(ifStr, ifIdx);
111
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -0700112 nlmsghdr hdr{};
113 hdr.nlmsg_type = RTM_NEWNEIGH;
114 ndmsg msg{};
115 msg.ndm_family = AF_INET;
116 msg.ndm_state = NUD_PERMANENT;
William A. Kennington IIIebb1ad02019-04-21 18:02:49 -0700117 msg.ndm_ifindex = ifIdx;
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -0700118 ASSERT_NE(0, msg.ndm_ifindex);
119 in_addr addr;
120 ASSERT_EQ(1, inet_pton(msg.ndm_family, "192.168.10.1", &addr));
121 rtattr dst{};
122 dst.rta_len = RTA_LENGTH(sizeof(addr));
123 dst.rta_type = NDA_DST;
124 char dstbuf[RTA_ALIGN(dst.rta_len)];
125 std::memset(dstbuf, '\0', sizeof(dstbuf));
126 std::memcpy(dstbuf, &dst, sizeof(dst));
127 std::memcpy(RTA_DATA(dstbuf), &addr, sizeof(addr));
128 std::string data;
129 data.append(reinterpret_cast<char*>(&msg), sizeof(msg));
130 data.append(reinterpret_cast<char*>(&dstbuf), sizeof(dstbuf));
131
132 std::vector<NeighborInfo> neighbors;
133 parseNeighbor(hdr, data, neighbors);
134 EXPECT_EQ(1, neighbors.size());
William A. Kennington IIIebb1ad02019-04-21 18:02:49 -0700135 EXPECT_EQ(ifStr, neighbors[0].interface);
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -0700136 EXPECT_TRUE(neighbors[0].permanent);
137 EXPECT_FALSE(neighbors[0].mac);
138 EXPECT_TRUE(equal(addr, std::get<in_addr>(neighbors[0].address)));
139}
140
141TEST(ParseNeighbor, Full)
142{
William A. Kennington III862275a2019-04-22 20:37:08 -0700143 mock_clear();
William A. Kennington IIIebb1ad02019-04-21 18:02:49 -0700144 mock_addIF(ifStr, ifIdx);
145
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -0700146 nlmsghdr hdr{};
147 hdr.nlmsg_type = RTM_NEWNEIGH;
148 ndmsg msg{};
149 msg.ndm_family = AF_INET6;
150 msg.ndm_state = NUD_NOARP;
William A. Kennington IIIebb1ad02019-04-21 18:02:49 -0700151 msg.ndm_ifindex = ifIdx;
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -0700152 ether_addr mac = {{0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa}};
153 rtattr lladdr{};
154 lladdr.rta_len = RTA_LENGTH(sizeof(mac));
155 lladdr.rta_type = NDA_LLADDR;
156 char lladdrbuf[RTA_ALIGN(lladdr.rta_len)];
157 std::memset(lladdrbuf, '\0', sizeof(lladdrbuf));
158 std::memcpy(lladdrbuf, &lladdr, sizeof(lladdr));
159 std::memcpy(RTA_DATA(lladdrbuf), &mac, sizeof(mac));
160 in6_addr addr;
161 ASSERT_EQ(1, inet_pton(msg.ndm_family, "fd00::1", &addr));
162 rtattr dst{};
163 dst.rta_len = RTA_LENGTH(sizeof(addr));
164 dst.rta_type = NDA_DST;
165 char dstbuf[RTA_ALIGN(dst.rta_len)];
166 std::memset(dstbuf, '\0', sizeof(dstbuf));
167 std::memcpy(dstbuf, &dst, sizeof(dst));
168 std::memcpy(RTA_DATA(dstbuf), &addr, sizeof(addr));
169 std::string data;
170 data.append(reinterpret_cast<char*>(&msg), sizeof(msg));
171 data.append(reinterpret_cast<char*>(&lladdrbuf), sizeof(lladdrbuf));
172 data.append(reinterpret_cast<char*>(&dstbuf), sizeof(dstbuf));
173
174 std::vector<NeighborInfo> neighbors;
175 parseNeighbor(hdr, data, neighbors);
176 EXPECT_EQ(1, neighbors.size());
William A. Kennington IIIebb1ad02019-04-21 18:02:49 -0700177 EXPECT_EQ(ifStr, neighbors[0].interface);
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -0700178 EXPECT_FALSE(neighbors[0].permanent);
179 EXPECT_TRUE(neighbors[0].mac);
William A. Kennington III6ca08d82019-04-20 16:04:18 -0700180 EXPECT_TRUE(equal(mac, *neighbors[0].mac));
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -0700181 EXPECT_TRUE(equal(addr, std::get<in6_addr>(neighbors[0].address)));
182}
183
184} // namespace detail
185} // namespace network
186} // namespace phosphor