blob: a76a7d58cf085b1890f66cd2ed733549faba4786 [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>
8#include <net/if.h>
9
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
25TEST(ParseNeighbor, NotNeighborType)
26{
27 nlmsghdr hdr{};
28 hdr.nlmsg_type = RTM_NEWLINK;
29
30 std::vector<NeighborInfo> neighbors;
31 EXPECT_THROW(parseNeighbor(hdr, "", neighbors), std::runtime_error);
32 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";
40
41 std::vector<NeighborInfo> neighbors;
42 EXPECT_THROW(parseNeighbor(hdr, data, neighbors), std::runtime_error);
43 EXPECT_EQ(0, neighbors.size());
44}
45
46TEST(ParseNeighbor, BadIf)
47{
48 nlmsghdr hdr{};
49 hdr.nlmsg_type = RTM_NEWNEIGH;
50 ndmsg msg{};
51 std::string data;
52 data.append(reinterpret_cast<char*>(&msg), sizeof(msg));
53
54 std::vector<NeighborInfo> neighbors;
55 EXPECT_THROW(parseNeighbor(hdr, data, neighbors), std::system_error);
56 EXPECT_EQ(0, neighbors.size());
57}
58
59TEST(ParseNeighbor, NoAttrs)
60{
61 nlmsghdr hdr{};
62 hdr.nlmsg_type = RTM_NEWNEIGH;
63 ndmsg msg{};
64 msg.ndm_ifindex = if_nametoindex("lo");
65 ASSERT_NE(0, msg.ndm_ifindex);
66 std::string data;
67 data.append(reinterpret_cast<char*>(&msg), sizeof(msg));
68
69 std::vector<NeighborInfo> neighbors;
70 EXPECT_THROW(parseNeighbor(hdr, data, neighbors), std::runtime_error);
71 EXPECT_EQ(0, neighbors.size());
72}
73
74TEST(ParseNeighbor, NoAddress)
75{
76 nlmsghdr hdr{};
77 hdr.nlmsg_type = RTM_NEWNEIGH;
78 ndmsg msg{};
79 msg.ndm_ifindex = if_nametoindex("lo");
80 ASSERT_NE(0, msg.ndm_ifindex);
81 ether_addr mac = {{0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa}};
82 rtattr lladdr{};
83 lladdr.rta_len = RTA_LENGTH(sizeof(mac));
84 lladdr.rta_type = NDA_LLADDR;
85 char lladdrbuf[RTA_ALIGN(lladdr.rta_len)];
86 std::memset(lladdrbuf, '\0', sizeof(lladdrbuf));
87 std::memcpy(lladdrbuf, &lladdr, sizeof(lladdr));
88 std::memcpy(RTA_DATA(lladdrbuf), &mac, sizeof(mac));
89 std::string data;
90 data.append(reinterpret_cast<char*>(&msg), sizeof(msg));
91 data.append(reinterpret_cast<char*>(&lladdrbuf), sizeof(lladdrbuf));
92
93 std::vector<NeighborInfo> neighbors;
94 EXPECT_THROW(parseNeighbor(hdr, data, neighbors), std::runtime_error);
95 EXPECT_EQ(0, neighbors.size());
96}
97
98TEST(ParseNeighbor, NoMAC)
99{
100 constexpr auto ifstr = "lo";
101 nlmsghdr hdr{};
102 hdr.nlmsg_type = RTM_NEWNEIGH;
103 ndmsg msg{};
104 msg.ndm_family = AF_INET;
105 msg.ndm_state = NUD_PERMANENT;
106 msg.ndm_ifindex = if_nametoindex(ifstr);
107 ASSERT_NE(0, msg.ndm_ifindex);
108 in_addr addr;
109 ASSERT_EQ(1, inet_pton(msg.ndm_family, "192.168.10.1", &addr));
110 rtattr dst{};
111 dst.rta_len = RTA_LENGTH(sizeof(addr));
112 dst.rta_type = NDA_DST;
113 char dstbuf[RTA_ALIGN(dst.rta_len)];
114 std::memset(dstbuf, '\0', sizeof(dstbuf));
115 std::memcpy(dstbuf, &dst, sizeof(dst));
116 std::memcpy(RTA_DATA(dstbuf), &addr, sizeof(addr));
117 std::string data;
118 data.append(reinterpret_cast<char*>(&msg), sizeof(msg));
119 data.append(reinterpret_cast<char*>(&dstbuf), sizeof(dstbuf));
120
121 std::vector<NeighborInfo> neighbors;
122 parseNeighbor(hdr, data, neighbors);
123 EXPECT_EQ(1, neighbors.size());
124 EXPECT_EQ(ifstr, neighbors[0].interface);
125 EXPECT_TRUE(neighbors[0].permanent);
126 EXPECT_FALSE(neighbors[0].mac);
127 EXPECT_TRUE(equal(addr, std::get<in_addr>(neighbors[0].address)));
128}
129
130TEST(ParseNeighbor, Full)
131{
132 constexpr auto ifstr = "lo";
133 nlmsghdr hdr{};
134 hdr.nlmsg_type = RTM_NEWNEIGH;
135 ndmsg msg{};
136 msg.ndm_family = AF_INET6;
137 msg.ndm_state = NUD_NOARP;
138 msg.ndm_ifindex = if_nametoindex(ifstr);
139 ether_addr mac = {{0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa}};
140 rtattr lladdr{};
141 lladdr.rta_len = RTA_LENGTH(sizeof(mac));
142 lladdr.rta_type = NDA_LLADDR;
143 char lladdrbuf[RTA_ALIGN(lladdr.rta_len)];
144 std::memset(lladdrbuf, '\0', sizeof(lladdrbuf));
145 std::memcpy(lladdrbuf, &lladdr, sizeof(lladdr));
146 std::memcpy(RTA_DATA(lladdrbuf), &mac, sizeof(mac));
147 in6_addr addr;
148 ASSERT_EQ(1, inet_pton(msg.ndm_family, "fd00::1", &addr));
149 rtattr dst{};
150 dst.rta_len = RTA_LENGTH(sizeof(addr));
151 dst.rta_type = NDA_DST;
152 char dstbuf[RTA_ALIGN(dst.rta_len)];
153 std::memset(dstbuf, '\0', sizeof(dstbuf));
154 std::memcpy(dstbuf, &dst, sizeof(dst));
155 std::memcpy(RTA_DATA(dstbuf), &addr, sizeof(addr));
156 std::string data;
157 data.append(reinterpret_cast<char*>(&msg), sizeof(msg));
158 data.append(reinterpret_cast<char*>(&lladdrbuf), sizeof(lladdrbuf));
159 data.append(reinterpret_cast<char*>(&dstbuf), sizeof(dstbuf));
160
161 std::vector<NeighborInfo> neighbors;
162 parseNeighbor(hdr, data, neighbors);
163 EXPECT_EQ(1, neighbors.size());
164 EXPECT_EQ(ifstr, neighbors[0].interface);
165 EXPECT_FALSE(neighbors[0].permanent);
166 EXPECT_TRUE(neighbors[0].mac);
167 EXPECT_EQ(0, std::memcmp(&mac, neighbors[0].mac->data(), sizeof(mac)));
168 EXPECT_TRUE(equal(addr, std::get<in6_addr>(neighbors[0].address)));
169}
170
171} // namespace detail
172} // namespace network
173} // namespace phosphor