blob: c7d926e9a422e197c5fdc4d65b359832fac9beec [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>
11#include <string>
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070012#include <vector>
13
14#include <gtest/gtest.h>
15
16namespace phosphor
17{
18namespace network
19{
20namespace detail
21{
22
23TEST(ParseNeighbor, NotNeighborType)
24{
25 nlmsghdr hdr{};
26 hdr.nlmsg_type = RTM_NEWLINK;
William A. Kennington IIId7946a72019-04-19 14:24:09 -070027 NeighborFilter filter;
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070028
29 std::vector<NeighborInfo> neighbors;
William A. Kennington IIId7946a72019-04-19 14:24:09 -070030 EXPECT_THROW(parseNeighbor(filter, hdr, "", neighbors), std::runtime_error);
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070031 EXPECT_EQ(0, neighbors.size());
32}
33
34TEST(ParseNeighbor, SmallMsg)
35{
36 nlmsghdr hdr{};
37 hdr.nlmsg_type = RTM_NEWNEIGH;
38 std::string data = "1";
William A. Kennington IIId7946a72019-04-19 14:24:09 -070039 NeighborFilter filter;
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070040
41 std::vector<NeighborInfo> neighbors;
William A. Kennington IIId7946a72019-04-19 14:24:09 -070042 EXPECT_THROW(parseNeighbor(filter, hdr, data, neighbors),
43 std::runtime_error);
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070044 EXPECT_EQ(0, neighbors.size());
45}
46
47TEST(ParseNeighbor, NoAttrs)
48{
49 nlmsghdr hdr{};
50 hdr.nlmsg_type = RTM_NEWNEIGH;
51 ndmsg msg{};
William A. Kennington IIId7946a72019-04-19 14:24:09 -070052 msg.ndm_ifindex = 1;
53 msg.ndm_state = NUD_REACHABLE;
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070054 std::string data;
55 data.append(reinterpret_cast<char*>(&msg), sizeof(msg));
William A. Kennington IIId7946a72019-04-19 14:24:09 -070056 NeighborFilter filter;
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070057
58 std::vector<NeighborInfo> neighbors;
William A. Kennington IIId7946a72019-04-19 14:24:09 -070059 EXPECT_THROW(parseNeighbor(filter, hdr, data, neighbors),
60 std::runtime_error);
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070061 EXPECT_EQ(0, neighbors.size());
62}
63
64TEST(ParseNeighbor, NoAddress)
65{
66 nlmsghdr hdr{};
67 hdr.nlmsg_type = RTM_NEWNEIGH;
68 ndmsg msg{};
William A. Kennington IIId7946a72019-04-19 14:24:09 -070069 msg.ndm_ifindex = 1;
70 msg.ndm_state = NUD_REACHABLE;
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070071 ether_addr mac = {{0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa}};
72 rtattr lladdr{};
73 lladdr.rta_len = RTA_LENGTH(sizeof(mac));
74 lladdr.rta_type = NDA_LLADDR;
75 char lladdrbuf[RTA_ALIGN(lladdr.rta_len)];
76 std::memset(lladdrbuf, '\0', sizeof(lladdrbuf));
77 std::memcpy(lladdrbuf, &lladdr, sizeof(lladdr));
78 std::memcpy(RTA_DATA(lladdrbuf), &mac, sizeof(mac));
79 std::string data;
80 data.append(reinterpret_cast<char*>(&msg), sizeof(msg));
81 data.append(reinterpret_cast<char*>(&lladdrbuf), sizeof(lladdrbuf));
William A. Kennington IIId7946a72019-04-19 14:24:09 -070082 NeighborFilter filter;
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070083
84 std::vector<NeighborInfo> neighbors;
William A. Kennington IIId7946a72019-04-19 14:24:09 -070085 EXPECT_THROW(parseNeighbor(filter, hdr, data, neighbors),
86 std::runtime_error);
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070087 EXPECT_EQ(0, neighbors.size());
88}
89
90TEST(ParseNeighbor, NoMAC)
91{
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070092 nlmsghdr hdr{};
93 hdr.nlmsg_type = RTM_NEWNEIGH;
94 ndmsg msg{};
95 msg.ndm_family = AF_INET;
96 msg.ndm_state = NUD_PERMANENT;
William A. Kennington IIId7946a72019-04-19 14:24:09 -070097 msg.ndm_ifindex = 1;
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -070098 in_addr addr;
99 ASSERT_EQ(1, inet_pton(msg.ndm_family, "192.168.10.1", &addr));
100 rtattr dst{};
101 dst.rta_len = RTA_LENGTH(sizeof(addr));
102 dst.rta_type = NDA_DST;
103 char dstbuf[RTA_ALIGN(dst.rta_len)];
104 std::memset(dstbuf, '\0', sizeof(dstbuf));
105 std::memcpy(dstbuf, &dst, sizeof(dst));
106 std::memcpy(RTA_DATA(dstbuf), &addr, sizeof(addr));
107 std::string data;
108 data.append(reinterpret_cast<char*>(&msg), sizeof(msg));
109 data.append(reinterpret_cast<char*>(&dstbuf), sizeof(dstbuf));
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700110 NeighborFilter filter;
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -0700111
112 std::vector<NeighborInfo> neighbors;
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700113 parseNeighbor(filter, hdr, data, neighbors);
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -0700114 EXPECT_EQ(1, neighbors.size());
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700115 EXPECT_EQ(msg.ndm_ifindex, neighbors[0].interface);
116 EXPECT_EQ(msg.ndm_state, neighbors[0].state);
117 EXPECT_FALSE(neighbors[0].mac);
118 EXPECT_TRUE(equal(addr, std::get<in_addr>(neighbors[0].address)));
119}
120
121TEST(ParseNeighbor, FilterInterface)
122{
123 nlmsghdr hdr{};
124 hdr.nlmsg_type = RTM_NEWNEIGH;
125 ndmsg msg{};
126 msg.ndm_family = AF_INET;
127 msg.ndm_state = NUD_PERMANENT;
128 msg.ndm_ifindex = 2;
129 in_addr addr;
130 ASSERT_EQ(1, inet_pton(msg.ndm_family, "192.168.10.1", &addr));
131 rtattr dst{};
132 dst.rta_len = RTA_LENGTH(sizeof(addr));
133 dst.rta_type = NDA_DST;
134 char dstbuf[RTA_ALIGN(dst.rta_len)];
135 std::memset(dstbuf, '\0', sizeof(dstbuf));
136 std::memcpy(dstbuf, &dst, sizeof(dst));
137 std::memcpy(RTA_DATA(dstbuf), &addr, sizeof(addr));
138 std::string data;
139 data.append(reinterpret_cast<char*>(&msg), sizeof(msg));
140 data.append(reinterpret_cast<char*>(&dstbuf), sizeof(dstbuf));
141 NeighborFilter filter;
142
143 std::vector<NeighborInfo> neighbors;
144 filter.interface = 1;
145 parseNeighbor(filter, hdr, data, neighbors);
146 EXPECT_EQ(0, neighbors.size());
147 filter.interface = 2;
148 parseNeighbor(filter, hdr, data, neighbors);
149 EXPECT_EQ(1, neighbors.size());
150 EXPECT_EQ(msg.ndm_ifindex, neighbors[0].interface);
151 EXPECT_EQ(msg.ndm_state, neighbors[0].state);
152 EXPECT_FALSE(neighbors[0].mac);
153 EXPECT_TRUE(equal(addr, std::get<in_addr>(neighbors[0].address)));
154}
155
156TEST(ParseNeighbor, FilterState)
157{
158 nlmsghdr hdr{};
159 hdr.nlmsg_type = RTM_NEWNEIGH;
160 ndmsg msg{};
161 msg.ndm_family = AF_INET;
162 msg.ndm_state = NUD_PERMANENT;
163 msg.ndm_ifindex = 2;
164 in_addr addr;
165 ASSERT_EQ(1, inet_pton(msg.ndm_family, "192.168.10.1", &addr));
166 rtattr dst{};
167 dst.rta_len = RTA_LENGTH(sizeof(addr));
168 dst.rta_type = NDA_DST;
169 char dstbuf[RTA_ALIGN(dst.rta_len)];
170 std::memset(dstbuf, '\0', sizeof(dstbuf));
171 std::memcpy(dstbuf, &dst, sizeof(dst));
172 std::memcpy(RTA_DATA(dstbuf), &addr, sizeof(addr));
173 std::string data;
174 data.append(reinterpret_cast<char*>(&msg), sizeof(msg));
175 data.append(reinterpret_cast<char*>(&dstbuf), sizeof(dstbuf));
176 NeighborFilter filter;
177
178 std::vector<NeighborInfo> neighbors;
179 filter.state = NUD_NOARP;
180 parseNeighbor(filter, hdr, data, neighbors);
181 EXPECT_EQ(0, neighbors.size());
182 filter.state = NUD_PERMANENT | NUD_NOARP;
183 parseNeighbor(filter, hdr, data, neighbors);
184 EXPECT_EQ(1, neighbors.size());
185 EXPECT_EQ(msg.ndm_ifindex, neighbors[0].interface);
186 EXPECT_EQ(msg.ndm_state, neighbors[0].state);
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -0700187 EXPECT_FALSE(neighbors[0].mac);
188 EXPECT_TRUE(equal(addr, std::get<in_addr>(neighbors[0].address)));
189}
190
191TEST(ParseNeighbor, Full)
192{
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -0700193 nlmsghdr hdr{};
194 hdr.nlmsg_type = RTM_NEWNEIGH;
195 ndmsg msg{};
196 msg.ndm_family = AF_INET6;
197 msg.ndm_state = NUD_NOARP;
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700198 msg.ndm_ifindex = 1;
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -0700199 ether_addr mac = {{0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa}};
200 rtattr lladdr{};
201 lladdr.rta_len = RTA_LENGTH(sizeof(mac));
202 lladdr.rta_type = NDA_LLADDR;
203 char lladdrbuf[RTA_ALIGN(lladdr.rta_len)];
204 std::memset(lladdrbuf, '\0', sizeof(lladdrbuf));
205 std::memcpy(lladdrbuf, &lladdr, sizeof(lladdr));
206 std::memcpy(RTA_DATA(lladdrbuf), &mac, sizeof(mac));
207 in6_addr addr;
208 ASSERT_EQ(1, inet_pton(msg.ndm_family, "fd00::1", &addr));
209 rtattr dst{};
210 dst.rta_len = RTA_LENGTH(sizeof(addr));
211 dst.rta_type = NDA_DST;
212 char dstbuf[RTA_ALIGN(dst.rta_len)];
213 std::memset(dstbuf, '\0', sizeof(dstbuf));
214 std::memcpy(dstbuf, &dst, sizeof(dst));
215 std::memcpy(RTA_DATA(dstbuf), &addr, sizeof(addr));
216 std::string data;
217 data.append(reinterpret_cast<char*>(&msg), sizeof(msg));
218 data.append(reinterpret_cast<char*>(&lladdrbuf), sizeof(lladdrbuf));
219 data.append(reinterpret_cast<char*>(&dstbuf), sizeof(dstbuf));
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700220 NeighborFilter filter;
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -0700221
222 std::vector<NeighborInfo> neighbors;
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700223 parseNeighbor(filter, hdr, data, neighbors);
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -0700224 EXPECT_EQ(1, neighbors.size());
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700225 EXPECT_EQ(msg.ndm_ifindex, neighbors[0].interface);
226 EXPECT_EQ(msg.ndm_state, neighbors[0].state);
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -0700227 EXPECT_TRUE(neighbors[0].mac);
William A. Kennington III6ca08d82019-04-20 16:04:18 -0700228 EXPECT_TRUE(equal(mac, *neighbors[0].mac));
William A. Kennington IIIc920bdb2019-04-19 14:23:06 -0700229 EXPECT_TRUE(equal(addr, std::get<in6_addr>(neighbors[0].address)));
230}
231
232} // namespace detail
233} // namespace network
234} // namespace phosphor