xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/qbone/platform/rtnetlink_message_test.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright (c) 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "quiche/quic/qbone/platform/rtnetlink_message.h"
6 
7 #include <net/if_arp.h>
8 
9 #include "quiche/quic/platform/api/quic_ip_address.h"
10 #include "quiche/quic/platform/api/quic_test.h"
11 
12 namespace quic {
13 namespace {
14 
15 using ::testing::StrEq;
16 
TEST(RtnetlinkMessageTest,LinkMessageCanBeCreatedForGetOperation)17 TEST(RtnetlinkMessageTest, LinkMessageCanBeCreatedForGetOperation) {
18   uint16_t flags = NLM_F_REQUEST | NLM_F_ROOT | NLM_F_MATCH;
19   uint32_t seq = 42;
20   uint32_t pid = 7;
21   auto message = LinkMessage::New(RtnetlinkMessage::Operation::GET, flags, seq,
22                                   pid, nullptr);
23 
24   // No rtattr appended.
25   EXPECT_EQ(1, message.IoVecSize());
26 
27   // nlmsghdr is built properly.
28   auto iov = message.BuildIoVec();
29   EXPECT_EQ(NLMSG_SPACE(sizeof(struct rtgenmsg)), iov[0].iov_len);
30   auto* netlink_message = reinterpret_cast<struct nlmsghdr*>(iov[0].iov_base);
31   EXPECT_EQ(NLMSG_LENGTH(sizeof(struct rtgenmsg)), netlink_message->nlmsg_len);
32   EXPECT_EQ(RTM_GETLINK, netlink_message->nlmsg_type);
33   EXPECT_EQ(flags, netlink_message->nlmsg_flags);
34   EXPECT_EQ(seq, netlink_message->nlmsg_seq);
35   EXPECT_EQ(pid, netlink_message->nlmsg_pid);
36 
37   // We actually included rtgenmsg instead of the passed in ifinfomsg since this
38   // is a GET operation.
39   EXPECT_EQ(NLMSG_LENGTH(sizeof(struct rtgenmsg)), netlink_message->nlmsg_len);
40 }
41 
TEST(RtnetlinkMessageTest,LinkMessageCanBeCreatedForNewOperation)42 TEST(RtnetlinkMessageTest, LinkMessageCanBeCreatedForNewOperation) {
43   struct ifinfomsg interface_info_header = {AF_INET, /* pad */ 0, ARPHRD_TUNNEL,
44                                             3,       0,           0xffffffff};
45   uint16_t flags = NLM_F_REQUEST | NLM_F_ROOT | NLM_F_MATCH;
46   uint32_t seq = 42;
47   uint32_t pid = 7;
48   auto message = LinkMessage::New(RtnetlinkMessage::Operation::NEW, flags, seq,
49                                   pid, &interface_info_header);
50 
51   std::string device_name = "device0";
52   message.AppendAttribute(IFLA_IFNAME, device_name.c_str(), device_name.size());
53 
54   // One rtattr appended.
55   EXPECT_EQ(2, message.IoVecSize());
56 
57   // nlmsghdr is built properly.
58   auto iov = message.BuildIoVec();
59   EXPECT_EQ(NLMSG_ALIGN(NLMSG_LENGTH(sizeof(struct ifinfomsg))),
60             iov[0].iov_len);
61   auto* netlink_message = reinterpret_cast<struct nlmsghdr*>(iov[0].iov_base);
62   EXPECT_EQ(NLMSG_ALIGN(NLMSG_LENGTH(sizeof(struct ifinfomsg))) +
63                 RTA_LENGTH(device_name.size()),
64             netlink_message->nlmsg_len);
65   EXPECT_EQ(RTM_NEWLINK, netlink_message->nlmsg_type);
66   EXPECT_EQ(flags, netlink_message->nlmsg_flags);
67   EXPECT_EQ(seq, netlink_message->nlmsg_seq);
68   EXPECT_EQ(pid, netlink_message->nlmsg_pid);
69 
70   // ifinfomsg is included properly.
71   auto* parsed_header =
72       reinterpret_cast<struct ifinfomsg*>(NLMSG_DATA(netlink_message));
73   EXPECT_EQ(interface_info_header.ifi_family, parsed_header->ifi_family);
74   EXPECT_EQ(interface_info_header.ifi_type, parsed_header->ifi_type);
75   EXPECT_EQ(interface_info_header.ifi_index, parsed_header->ifi_index);
76   EXPECT_EQ(interface_info_header.ifi_flags, parsed_header->ifi_flags);
77   EXPECT_EQ(interface_info_header.ifi_change, parsed_header->ifi_change);
78 
79   // rtattr is handled properly.
80   EXPECT_EQ(RTA_SPACE(device_name.size()), iov[1].iov_len);
81   auto* rta = reinterpret_cast<struct rtattr*>(iov[1].iov_base);
82   EXPECT_EQ(IFLA_IFNAME, rta->rta_type);
83   EXPECT_EQ(RTA_LENGTH(device_name.size()), rta->rta_len);
84   EXPECT_THAT(device_name,
85               StrEq(std::string(reinterpret_cast<char*>(RTA_DATA(rta)),
86                                 RTA_PAYLOAD(rta))));
87 }
88 
TEST(RtnetlinkMessageTest,AddressMessageCanBeCreatedForGetOperation)89 TEST(RtnetlinkMessageTest, AddressMessageCanBeCreatedForGetOperation) {
90   uint16_t flags = NLM_F_REQUEST | NLM_F_ROOT | NLM_F_MATCH;
91   uint32_t seq = 42;
92   uint32_t pid = 7;
93   auto message = AddressMessage::New(RtnetlinkMessage::Operation::GET, flags,
94                                      seq, pid, nullptr);
95 
96   // No rtattr appended.
97   EXPECT_EQ(1, message.IoVecSize());
98 
99   // nlmsghdr is built properly.
100   auto iov = message.BuildIoVec();
101   EXPECT_EQ(NLMSG_SPACE(sizeof(struct rtgenmsg)), iov[0].iov_len);
102   auto* netlink_message = reinterpret_cast<struct nlmsghdr*>(iov[0].iov_base);
103   EXPECT_EQ(NLMSG_LENGTH(sizeof(struct rtgenmsg)), netlink_message->nlmsg_len);
104   EXPECT_EQ(RTM_GETADDR, netlink_message->nlmsg_type);
105   EXPECT_EQ(flags, netlink_message->nlmsg_flags);
106   EXPECT_EQ(seq, netlink_message->nlmsg_seq);
107   EXPECT_EQ(pid, netlink_message->nlmsg_pid);
108 
109   // We actually included rtgenmsg instead of the passed in ifinfomsg since this
110   // is a GET operation.
111   EXPECT_EQ(NLMSG_LENGTH(sizeof(struct rtgenmsg)), netlink_message->nlmsg_len);
112 }
113 
TEST(RtnetlinkMessageTest,AddressMessageCanBeCreatedForNewOperation)114 TEST(RtnetlinkMessageTest, AddressMessageCanBeCreatedForNewOperation) {
115   struct ifaddrmsg interface_address_header = {AF_INET,
116                                                /* prefixlen */ 24,
117                                                /* flags */ 0,
118                                                /* scope */ RT_SCOPE_LINK,
119                                                /* index */ 4};
120   uint16_t flags = NLM_F_REQUEST | NLM_F_ROOT | NLM_F_MATCH;
121   uint32_t seq = 42;
122   uint32_t pid = 7;
123   auto message = AddressMessage::New(RtnetlinkMessage::Operation::NEW, flags,
124                                      seq, pid, &interface_address_header);
125 
126   QuicIpAddress ip;
127   QUICHE_CHECK(ip.FromString("10.0.100.3"));
128   message.AppendAttribute(IFA_ADDRESS, ip.ToPackedString().c_str(),
129                           ip.ToPackedString().size());
130 
131   // One rtattr is appended.
132   EXPECT_EQ(2, message.IoVecSize());
133 
134   // nlmsghdr is built properly.
135   auto iov = message.BuildIoVec();
136   EXPECT_EQ(NLMSG_ALIGN(NLMSG_LENGTH(sizeof(struct ifaddrmsg))),
137             iov[0].iov_len);
138   auto* netlink_message = reinterpret_cast<struct nlmsghdr*>(iov[0].iov_base);
139   EXPECT_EQ(NLMSG_ALIGN(NLMSG_LENGTH(sizeof(struct ifaddrmsg))) +
140                 RTA_LENGTH(ip.ToPackedString().size()),
141             netlink_message->nlmsg_len);
142   EXPECT_EQ(RTM_NEWADDR, netlink_message->nlmsg_type);
143   EXPECT_EQ(flags, netlink_message->nlmsg_flags);
144   EXPECT_EQ(seq, netlink_message->nlmsg_seq);
145   EXPECT_EQ(pid, netlink_message->nlmsg_pid);
146 
147   // ifaddrmsg is included properly.
148   auto* parsed_header =
149       reinterpret_cast<struct ifaddrmsg*>(NLMSG_DATA(netlink_message));
150   EXPECT_EQ(interface_address_header.ifa_family, parsed_header->ifa_family);
151   EXPECT_EQ(interface_address_header.ifa_prefixlen,
152             parsed_header->ifa_prefixlen);
153   EXPECT_EQ(interface_address_header.ifa_flags, parsed_header->ifa_flags);
154   EXPECT_EQ(interface_address_header.ifa_scope, parsed_header->ifa_scope);
155   EXPECT_EQ(interface_address_header.ifa_index, parsed_header->ifa_index);
156 
157   // rtattr is handled properly.
158   EXPECT_EQ(RTA_SPACE(ip.ToPackedString().size()), iov[1].iov_len);
159   auto* rta = reinterpret_cast<struct rtattr*>(iov[1].iov_base);
160   EXPECT_EQ(IFA_ADDRESS, rta->rta_type);
161   EXPECT_EQ(RTA_LENGTH(ip.ToPackedString().size()), rta->rta_len);
162   EXPECT_THAT(ip.ToPackedString(),
163               StrEq(std::string(reinterpret_cast<char*>(RTA_DATA(rta)),
164                                 RTA_PAYLOAD(rta))));
165 }
166 
TEST(RtnetlinkMessageTest,RouteMessageCanBeCreatedFromNewOperation)167 TEST(RtnetlinkMessageTest, RouteMessageCanBeCreatedFromNewOperation) {
168   struct rtmsg route_message_header = {AF_INET6,
169                                        /* rtm_dst_len */ 48,
170                                        /* rtm_src_len */ 0,
171                                        /* rtm_tos */ 0,
172                                        /* rtm_table */ RT_TABLE_MAIN,
173                                        /* rtm_protocol */ RTPROT_STATIC,
174                                        /* rtm_scope */ RT_SCOPE_LINK,
175                                        /* rtm_type */ RTN_LOCAL,
176                                        /* rtm_flags */ 0};
177   uint16_t flags = NLM_F_REQUEST | NLM_F_ROOT | NLM_F_MATCH;
178   uint32_t seq = 42;
179   uint32_t pid = 7;
180   auto message = RouteMessage::New(RtnetlinkMessage::Operation::NEW, flags, seq,
181                                    pid, &route_message_header);
182 
183   QuicIpAddress preferred_source;
184   QUICHE_CHECK(preferred_source.FromString("ff80::1"));
185   message.AppendAttribute(RTA_PREFSRC,
186                           preferred_source.ToPackedString().c_str(),
187                           preferred_source.ToPackedString().size());
188 
189   // One rtattr is appended.
190   EXPECT_EQ(2, message.IoVecSize());
191 
192   // nlmsghdr is built properly
193   auto iov = message.BuildIoVec();
194   EXPECT_EQ(NLMSG_ALIGN(NLMSG_LENGTH(sizeof(struct rtmsg))), iov[0].iov_len);
195   auto* netlink_message = reinterpret_cast<struct nlmsghdr*>(iov[0].iov_base);
196   EXPECT_EQ(NLMSG_ALIGN(NLMSG_LENGTH(sizeof(struct rtmsg))) +
197                 RTA_LENGTH(preferred_source.ToPackedString().size()),
198             netlink_message->nlmsg_len);
199   EXPECT_EQ(RTM_NEWROUTE, netlink_message->nlmsg_type);
200   EXPECT_EQ(flags, netlink_message->nlmsg_flags);
201   EXPECT_EQ(seq, netlink_message->nlmsg_seq);
202   EXPECT_EQ(pid, netlink_message->nlmsg_pid);
203 
204   // rtmsg is included properly.
205   auto* parsed_header =
206       reinterpret_cast<struct rtmsg*>(NLMSG_DATA(netlink_message));
207   EXPECT_EQ(route_message_header.rtm_family, parsed_header->rtm_family);
208   EXPECT_EQ(route_message_header.rtm_dst_len, parsed_header->rtm_dst_len);
209   EXPECT_EQ(route_message_header.rtm_src_len, parsed_header->rtm_src_len);
210   EXPECT_EQ(route_message_header.rtm_tos, parsed_header->rtm_tos);
211   EXPECT_EQ(route_message_header.rtm_table, parsed_header->rtm_table);
212   EXPECT_EQ(route_message_header.rtm_protocol, parsed_header->rtm_protocol);
213   EXPECT_EQ(route_message_header.rtm_scope, parsed_header->rtm_scope);
214   EXPECT_EQ(route_message_header.rtm_type, parsed_header->rtm_type);
215   EXPECT_EQ(route_message_header.rtm_flags, parsed_header->rtm_flags);
216 
217   // rtattr is handled properly.
218   EXPECT_EQ(RTA_SPACE(preferred_source.ToPackedString().size()),
219             iov[1].iov_len);
220   auto* rta = reinterpret_cast<struct rtattr*>(iov[1].iov_base);
221   EXPECT_EQ(RTA_PREFSRC, rta->rta_type);
222   EXPECT_EQ(RTA_LENGTH(preferred_source.ToPackedString().size()), rta->rta_len);
223   EXPECT_THAT(preferred_source.ToPackedString(),
224               StrEq(std::string(reinterpret_cast<char*>(RTA_DATA(rta)),
225                                 RTA_PAYLOAD(rta))));
226 }
227 
228 }  // namespace
229 }  // namespace quic
230