blob: 0f0abc433beaf098315bc000c441499a33870ca3 [file] [log] [blame]
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -07001#include "neighbor.hpp"
2#include "util.hpp"
3
4#include <arpa/inet.h>
5#include <linux/netlink.h>
6#include <linux/rtnetlink.h>
7#include <net/ethernet.h>
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -07008
9#include <cstring>
10#include <stdexcept>
William A. Kennington III12beaad2020-06-13 19:30:41 -070011#include <stdplus/raw.hpp>
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070012#include <string>
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070013#include <vector>
14
15#include <gtest/gtest.h>
16
17namespace phosphor
18{
19namespace network
20{
21namespace detail
22{
23
24TEST(ParseNeighbor, NotNeighborType)
25{
26 nlmsghdr hdr{};
27 hdr.nlmsg_type = RTM_NEWLINK;
William A. Kennington IIId7946a72019-04-19 14:24:09 -070028 NeighborFilter filter;
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070029
30 std::vector<NeighborInfo> neighbors;
William A. Kennington IIId7946a72019-04-19 14:24:09 -070031 EXPECT_THROW(parseNeighbor(filter, hdr, "", neighbors), std::runtime_error);
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070032 EXPECT_EQ(0, neighbors.size());
33}
34
35TEST(ParseNeighbor, SmallMsg)
36{
37 nlmsghdr hdr{};
38 hdr.nlmsg_type = RTM_NEWNEIGH;
39 std::string data = "1";
William A. Kennington IIId7946a72019-04-19 14:24:09 -070040 NeighborFilter filter;
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070041
42 std::vector<NeighborInfo> neighbors;
William A. Kennington IIId7946a72019-04-19 14:24:09 -070043 EXPECT_THROW(parseNeighbor(filter, hdr, data, neighbors),
44 std::runtime_error);
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070045 EXPECT_EQ(0, neighbors.size());
46}
47
48TEST(ParseNeighbor, NoAttrs)
49{
50 nlmsghdr hdr{};
51 hdr.nlmsg_type = RTM_NEWNEIGH;
52 ndmsg msg{};
William A. Kennington IIId7946a72019-04-19 14:24:09 -070053 msg.ndm_ifindex = 1;
54 msg.ndm_state = NUD_REACHABLE;
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070055 std::string data;
56 data.append(reinterpret_cast<char*>(&msg), sizeof(msg));
William A. Kennington IIId7946a72019-04-19 14:24:09 -070057 NeighborFilter filter;
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070058
59 std::vector<NeighborInfo> neighbors;
William A. Kennington IIId7946a72019-04-19 14:24:09 -070060 EXPECT_THROW(parseNeighbor(filter, hdr, data, neighbors),
61 std::runtime_error);
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070062 EXPECT_EQ(0, neighbors.size());
63}
64
65TEST(ParseNeighbor, NoAddress)
66{
67 nlmsghdr hdr{};
68 hdr.nlmsg_type = RTM_NEWNEIGH;
69 ndmsg msg{};
William A. Kennington IIId7946a72019-04-19 14:24:09 -070070 msg.ndm_ifindex = 1;
71 msg.ndm_state = NUD_REACHABLE;
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070072 ether_addr mac = {{0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa}};
73 rtattr lladdr{};
William A. Kennington IIIa19558e2021-05-13 18:56:51 -070074 constexpr size_t len = RTA_LENGTH(sizeof(mac));
75 lladdr.rta_len = len;
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070076 lladdr.rta_type = NDA_LLADDR;
William A. Kennington IIIa19558e2021-05-13 18:56:51 -070077 char lladdrbuf[RTA_ALIGN(len)];
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070078 std::memset(lladdrbuf, '\0', sizeof(lladdrbuf));
79 std::memcpy(lladdrbuf, &lladdr, sizeof(lladdr));
80 std::memcpy(RTA_DATA(lladdrbuf), &mac, sizeof(mac));
81 std::string data;
82 data.append(reinterpret_cast<char*>(&msg), sizeof(msg));
83 data.append(reinterpret_cast<char*>(&lladdrbuf), sizeof(lladdrbuf));
William A. Kennington IIId7946a72019-04-19 14:24:09 -070084 NeighborFilter filter;
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070085
86 std::vector<NeighborInfo> neighbors;
William A. Kennington IIId7946a72019-04-19 14:24:09 -070087 EXPECT_THROW(parseNeighbor(filter, hdr, data, neighbors),
88 std::runtime_error);
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070089 EXPECT_EQ(0, neighbors.size());
90}
91
92TEST(ParseNeighbor, NoMAC)
93{
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070094 nlmsghdr hdr{};
95 hdr.nlmsg_type = RTM_NEWNEIGH;
96 ndmsg msg{};
97 msg.ndm_family = AF_INET;
98 msg.ndm_state = NUD_PERMANENT;
William A. Kennington IIId7946a72019-04-19 14:24:09 -070099 msg.ndm_ifindex = 1;
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -0700100 in_addr addr;
101 ASSERT_EQ(1, inet_pton(msg.ndm_family, "192.168.10.1", &addr));
102 rtattr dst{};
William A. Kennington IIIa19558e2021-05-13 18:56:51 -0700103 constexpr size_t len = RTA_LENGTH(sizeof(addr));
104 dst.rta_len = len;
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -0700105 dst.rta_type = NDA_DST;
William A. Kennington IIIa19558e2021-05-13 18:56:51 -0700106 char dstbuf[RTA_ALIGN(len)];
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -0700107 std::memset(dstbuf, '\0', sizeof(dstbuf));
108 std::memcpy(dstbuf, &dst, sizeof(dst));
109 std::memcpy(RTA_DATA(dstbuf), &addr, sizeof(addr));
110 std::string data;
111 data.append(reinterpret_cast<char*>(&msg), sizeof(msg));
112 data.append(reinterpret_cast<char*>(&dstbuf), sizeof(dstbuf));
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700113 NeighborFilter filter;
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -0700114
115 std::vector<NeighborInfo> neighbors;
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700116 parseNeighbor(filter, hdr, data, neighbors);
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -0700117 EXPECT_EQ(1, neighbors.size());
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700118 EXPECT_EQ(msg.ndm_ifindex, neighbors[0].interface);
119 EXPECT_EQ(msg.ndm_state, neighbors[0].state);
120 EXPECT_FALSE(neighbors[0].mac);
William A. Kennington III12beaad2020-06-13 19:30:41 -0700121 EXPECT_TRUE(
122 stdplus::raw::equal(addr, std::get<in_addr>(neighbors[0].address)));
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700123}
124
125TEST(ParseNeighbor, FilterInterface)
126{
127 nlmsghdr hdr{};
128 hdr.nlmsg_type = RTM_NEWNEIGH;
129 ndmsg msg{};
130 msg.ndm_family = AF_INET;
131 msg.ndm_state = NUD_PERMANENT;
132 msg.ndm_ifindex = 2;
133 in_addr addr;
134 ASSERT_EQ(1, inet_pton(msg.ndm_family, "192.168.10.1", &addr));
135 rtattr dst{};
William A. Kennington IIIa19558e2021-05-13 18:56:51 -0700136 constexpr size_t len = RTA_LENGTH(sizeof(addr));
137 dst.rta_len = len;
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700138 dst.rta_type = NDA_DST;
William A. Kennington IIIa19558e2021-05-13 18:56:51 -0700139 char dstbuf[RTA_ALIGN(len)];
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700140 std::memset(dstbuf, '\0', sizeof(dstbuf));
141 std::memcpy(dstbuf, &dst, sizeof(dst));
142 std::memcpy(RTA_DATA(dstbuf), &addr, sizeof(addr));
143 std::string data;
144 data.append(reinterpret_cast<char*>(&msg), sizeof(msg));
145 data.append(reinterpret_cast<char*>(&dstbuf), sizeof(dstbuf));
146 NeighborFilter filter;
147
148 std::vector<NeighborInfo> neighbors;
149 filter.interface = 1;
150 parseNeighbor(filter, hdr, data, neighbors);
151 EXPECT_EQ(0, neighbors.size());
152 filter.interface = 2;
153 parseNeighbor(filter, hdr, data, neighbors);
154 EXPECT_EQ(1, neighbors.size());
155 EXPECT_EQ(msg.ndm_ifindex, neighbors[0].interface);
156 EXPECT_EQ(msg.ndm_state, neighbors[0].state);
157 EXPECT_FALSE(neighbors[0].mac);
William A. Kennington III12beaad2020-06-13 19:30:41 -0700158 EXPECT_TRUE(
159 stdplus::raw::equal(addr, std::get<in_addr>(neighbors[0].address)));
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700160}
161
162TEST(ParseNeighbor, FilterState)
163{
164 nlmsghdr hdr{};
165 hdr.nlmsg_type = RTM_NEWNEIGH;
166 ndmsg msg{};
167 msg.ndm_family = AF_INET;
168 msg.ndm_state = NUD_PERMANENT;
169 msg.ndm_ifindex = 2;
170 in_addr addr;
171 ASSERT_EQ(1, inet_pton(msg.ndm_family, "192.168.10.1", &addr));
172 rtattr dst{};
William A. Kennington IIIa19558e2021-05-13 18:56:51 -0700173 constexpr size_t len = RTA_LENGTH(sizeof(addr));
174 dst.rta_len = len;
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700175 dst.rta_type = NDA_DST;
William A. Kennington IIIa19558e2021-05-13 18:56:51 -0700176 char dstbuf[RTA_ALIGN(len)];
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700177 std::memset(dstbuf, '\0', sizeof(dstbuf));
178 std::memcpy(dstbuf, &dst, sizeof(dst));
179 std::memcpy(RTA_DATA(dstbuf), &addr, sizeof(addr));
180 std::string data;
181 data.append(reinterpret_cast<char*>(&msg), sizeof(msg));
182 data.append(reinterpret_cast<char*>(&dstbuf), sizeof(dstbuf));
183 NeighborFilter filter;
184
185 std::vector<NeighborInfo> neighbors;
186 filter.state = NUD_NOARP;
187 parseNeighbor(filter, hdr, data, neighbors);
188 EXPECT_EQ(0, neighbors.size());
189 filter.state = NUD_PERMANENT | NUD_NOARP;
190 parseNeighbor(filter, hdr, data, neighbors);
191 EXPECT_EQ(1, neighbors.size());
192 EXPECT_EQ(msg.ndm_ifindex, neighbors[0].interface);
193 EXPECT_EQ(msg.ndm_state, neighbors[0].state);
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -0700194 EXPECT_FALSE(neighbors[0].mac);
William A. Kennington III12beaad2020-06-13 19:30:41 -0700195 EXPECT_TRUE(
196 stdplus::raw::equal(addr, std::get<in_addr>(neighbors[0].address)));
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -0700197}
198
199TEST(ParseNeighbor, Full)
200{
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -0700201 nlmsghdr hdr{};
202 hdr.nlmsg_type = RTM_NEWNEIGH;
203 ndmsg msg{};
204 msg.ndm_family = AF_INET6;
205 msg.ndm_state = NUD_NOARP;
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700206 msg.ndm_ifindex = 1;
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -0700207 ether_addr mac = {{0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa}};
208 rtattr lladdr{};
William A. Kennington IIIa19558e2021-05-13 18:56:51 -0700209 constexpr size_t lladdr_len = RTA_LENGTH(sizeof(mac));
210 lladdr.rta_len = lladdr_len;
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -0700211 lladdr.rta_type = NDA_LLADDR;
William A. Kennington IIIa19558e2021-05-13 18:56:51 -0700212 char lladdrbuf[RTA_ALIGN(lladdr_len)];
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -0700213 std::memset(lladdrbuf, '\0', sizeof(lladdrbuf));
214 std::memcpy(lladdrbuf, &lladdr, sizeof(lladdr));
215 std::memcpy(RTA_DATA(lladdrbuf), &mac, sizeof(mac));
216 in6_addr addr;
217 ASSERT_EQ(1, inet_pton(msg.ndm_family, "fd00::1", &addr));
218 rtattr dst{};
William A. Kennington IIIa19558e2021-05-13 18:56:51 -0700219 constexpr size_t dst_len = RTA_LENGTH(sizeof(addr));
220 dst.rta_len = dst_len;
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -0700221 dst.rta_type = NDA_DST;
William A. Kennington IIIa19558e2021-05-13 18:56:51 -0700222 char dstbuf[RTA_ALIGN(dst_len)];
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -0700223 std::memset(dstbuf, '\0', sizeof(dstbuf));
224 std::memcpy(dstbuf, &dst, sizeof(dst));
225 std::memcpy(RTA_DATA(dstbuf), &addr, sizeof(addr));
226 std::string data;
227 data.append(reinterpret_cast<char*>(&msg), sizeof(msg));
228 data.append(reinterpret_cast<char*>(&lladdrbuf), sizeof(lladdrbuf));
229 data.append(reinterpret_cast<char*>(&dstbuf), sizeof(dstbuf));
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700230 NeighborFilter filter;
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -0700231
232 std::vector<NeighborInfo> neighbors;
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700233 parseNeighbor(filter, hdr, data, neighbors);
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -0700234 EXPECT_EQ(1, neighbors.size());
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700235 EXPECT_EQ(msg.ndm_ifindex, neighbors[0].interface);
236 EXPECT_EQ(msg.ndm_state, neighbors[0].state);
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -0700237 EXPECT_TRUE(neighbors[0].mac);
William A. Kennington III12beaad2020-06-13 19:30:41 -0700238 EXPECT_TRUE(stdplus::raw::equal(mac, *neighbors[0].mac));
239 EXPECT_TRUE(
240 stdplus::raw::equal(addr, std::get<in6_addr>(neighbors[0].address)));
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -0700241}
242
243} // namespace detail
244} // namespace network
245} // namespace phosphor