1 //
2 // Copyright (C) 2012 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16
17 #include "shill/net/rtnl_message.h"
18
19 #include <linux/netlink.h>
20 #include <linux/rtnetlink.h>
21 #include <netinet/in.h>
22 #include <sys/socket.h>
23
24 #include <base/logging.h>
25
26 #include "shill/net/ndisc.h"
27
28 namespace shill {
29
30 struct RTNLHeader {
RTNLHeadershill::RTNLHeader31 RTNLHeader() {
32 memset(this, 0, sizeof(*this));
33 }
34 struct nlmsghdr hdr;
35 union {
36 struct ifinfomsg ifi;
37 struct ifaddrmsg ifa;
38 struct rtmsg rtm;
39 struct rtgenmsg gen;
40 struct nduseroptmsg nd_user_opt;
41 struct ndmsg ndm;
42 };
43 };
44
RTNLMessage()45 RTNLMessage::RTNLMessage()
46 : type_(kTypeUnknown),
47 mode_(kModeUnknown),
48 flags_(0),
49 seq_(0),
50 pid_(0),
51 interface_index_(0),
52 family_(IPAddress::kFamilyUnknown) {}
53
RTNLMessage(Type type,Mode mode,unsigned int flags,uint32_t seq,uint32_t pid,int interface_index,IPAddress::Family family)54 RTNLMessage::RTNLMessage(Type type,
55 Mode mode,
56 unsigned int flags,
57 uint32_t seq,
58 uint32_t pid,
59 int interface_index,
60 IPAddress::Family family)
61 : type_(type),
62 mode_(mode),
63 flags_(flags),
64 seq_(seq),
65 pid_(pid),
66 interface_index_(interface_index),
67 family_(family) {}
68
Decode(const ByteString & msg)69 bool RTNLMessage::Decode(const ByteString& msg) {
70 bool ret = DecodeInternal(msg);
71 if (!ret) {
72 Reset();
73 }
74 return ret;
75 }
76
DecodeInternal(const ByteString & msg)77 bool RTNLMessage::DecodeInternal(const ByteString& msg) {
78 const RTNLHeader* hdr =
79 reinterpret_cast<const RTNLHeader*>(msg.GetConstData());
80
81 if (msg.GetLength() < sizeof(hdr->hdr) ||
82 msg.GetLength() < hdr->hdr.nlmsg_len)
83 return false;
84
85 Mode mode = kModeUnknown;
86 switch (hdr->hdr.nlmsg_type) {
87 case RTM_NEWLINK:
88 case RTM_NEWADDR:
89 case RTM_NEWROUTE:
90 case RTM_NEWNDUSEROPT:
91 case RTM_NEWNEIGH:
92 mode = kModeAdd;
93 break;
94
95 case RTM_DELLINK:
96 case RTM_DELADDR:
97 case RTM_DELROUTE:
98 case RTM_DELNEIGH:
99 mode = kModeDelete;
100 break;
101
102 default:
103 return false;
104 }
105
106 rtattr* attr_data = nullptr;
107 int attr_length = 0;
108
109 switch (hdr->hdr.nlmsg_type) {
110 case RTM_NEWLINK:
111 case RTM_DELLINK:
112 if (!DecodeLink(hdr, mode, &attr_data, &attr_length))
113 return false;
114 break;
115
116 case RTM_NEWADDR:
117 case RTM_DELADDR:
118 if (!DecodeAddress(hdr, mode, &attr_data, &attr_length))
119 return false;
120 break;
121
122 case RTM_NEWROUTE:
123 case RTM_DELROUTE:
124 if (!DecodeRoute(hdr, mode, &attr_data, &attr_length))
125 return false;
126 break;
127
128 case RTM_NEWNDUSEROPT:
129 if (!DecodeNdUserOption(hdr, mode, &attr_data, &attr_length))
130 return false;
131 break;
132
133 case RTM_NEWNEIGH:
134 case RTM_DELNEIGH:
135 if (!DecodeNeighbor(hdr, mode, &attr_data, &attr_length))
136 return false;
137 break;
138
139 default:
140 NOTREACHED();
141 }
142
143 flags_ = hdr->hdr.nlmsg_flags;
144 seq_ = hdr->hdr.nlmsg_seq;
145 pid_ = hdr->hdr.nlmsg_pid;
146
147 while (attr_data && RTA_OK(attr_data, attr_length)) {
148 SetAttribute(
149 attr_data->rta_type,
150 ByteString(reinterpret_cast<unsigned char*>(RTA_DATA(attr_data)),
151 RTA_PAYLOAD(attr_data)));
152 attr_data = RTA_NEXT(attr_data, attr_length);
153 }
154
155 if (attr_length) {
156 // We hit a parse error while going through the attributes
157 attributes_.clear();
158 return false;
159 }
160
161 return true;
162 }
163
DecodeLink(const RTNLHeader * hdr,Mode mode,rtattr ** attr_data,int * attr_length)164 bool RTNLMessage::DecodeLink(const RTNLHeader* hdr,
165 Mode mode,
166 rtattr** attr_data,
167 int* attr_length) {
168 if (hdr->hdr.nlmsg_len < NLMSG_LENGTH(sizeof(hdr->ifi))) {
169 return false;
170 }
171
172 mode_ = mode;
173 *attr_data = IFLA_RTA(NLMSG_DATA(&hdr->hdr));
174 *attr_length = IFLA_PAYLOAD(&hdr->hdr);
175
176 type_ = kTypeLink;
177 family_ = hdr->ifi.ifi_family;
178 interface_index_ = hdr->ifi.ifi_index;
179 set_link_status(LinkStatus(hdr->ifi.ifi_type,
180 hdr->ifi.ifi_flags,
181 hdr->ifi.ifi_change));
182 return true;
183 }
184
DecodeAddress(const RTNLHeader * hdr,Mode mode,rtattr ** attr_data,int * attr_length)185 bool RTNLMessage::DecodeAddress(const RTNLHeader* hdr,
186 Mode mode,
187 rtattr** attr_data,
188 int* attr_length) {
189 if (hdr->hdr.nlmsg_len < NLMSG_LENGTH(sizeof(hdr->ifa))) {
190 return false;
191 }
192 mode_ = mode;
193 *attr_data = IFA_RTA(NLMSG_DATA(&hdr->hdr));
194 *attr_length = IFA_PAYLOAD(&hdr->hdr);
195
196 type_ = kTypeAddress;
197 family_ = hdr->ifa.ifa_family;
198 interface_index_ = hdr->ifa.ifa_index;
199 set_address_status(AddressStatus(hdr->ifa.ifa_prefixlen,
200 hdr->ifa.ifa_flags,
201 hdr->ifa.ifa_scope));
202 return true;
203 }
204
DecodeRoute(const RTNLHeader * hdr,Mode mode,rtattr ** attr_data,int * attr_length)205 bool RTNLMessage::DecodeRoute(const RTNLHeader* hdr,
206 Mode mode,
207 rtattr** attr_data,
208 int* attr_length) {
209 if (hdr->hdr.nlmsg_len < NLMSG_LENGTH(sizeof(hdr->rtm))) {
210 return false;
211 }
212 mode_ = mode;
213 *attr_data = RTM_RTA(NLMSG_DATA(&hdr->hdr));
214 *attr_length = RTM_PAYLOAD(&hdr->hdr);
215
216 type_ = kTypeRoute;
217 family_ = hdr->rtm.rtm_family;
218 set_route_status(RouteStatus(hdr->rtm.rtm_dst_len,
219 hdr->rtm.rtm_src_len,
220 hdr->rtm.rtm_table,
221 hdr->rtm.rtm_protocol,
222 hdr->rtm.rtm_scope,
223 hdr->rtm.rtm_type,
224 hdr->rtm.rtm_flags));
225 return true;
226 }
227
DecodeNdUserOption(const RTNLHeader * hdr,Mode mode,rtattr ** attr_data,int * attr_length)228 bool RTNLMessage::DecodeNdUserOption(const RTNLHeader* hdr,
229 Mode mode,
230 rtattr** attr_data,
231 int* attr_length) {
232 if (hdr->hdr.nlmsg_len < NLMSG_LENGTH(sizeof(hdr->nd_user_opt))) {
233 return false;
234 }
235
236 mode_ = mode;
237 interface_index_ = hdr->nd_user_opt.nduseropt_ifindex;
238 family_ = hdr->nd_user_opt.nduseropt_family;
239
240 // Verify IP family.
241 if (family_ != IPAddress::kFamilyIPv6) {
242 return false;
243 }
244 // Verify message must at-least contain the option header.
245 if (hdr->nd_user_opt.nduseropt_opts_len < sizeof(NDUserOptionHeader)) {
246 return false;
247 }
248
249 // Parse the option header.
250 const NDUserOptionHeader* nd_user_option_header =
251 reinterpret_cast<const NDUserOptionHeader*>(
252 reinterpret_cast<const uint8_t*>(&hdr->nd_user_opt) +
253 sizeof(struct nduseroptmsg));
254 uint32_t lifetime = ntohl(nd_user_option_header->lifetime);
255
256 // Verify option length.
257 // The length field in the header is in units of 8 octets.
258 int opt_len = static_cast<int>(nd_user_option_header->length) * 8;
259 if (opt_len != hdr->nd_user_opt.nduseropt_opts_len) {
260 return false;
261 }
262
263 // Determine option data pointer and data length.
264 const uint8_t* option_data =
265 reinterpret_cast<const uint8_t*>(nd_user_option_header + 1);
266 int data_len = opt_len - sizeof(NDUserOptionHeader);
267
268 if (nd_user_option_header->type == ND_OPT_DNSSL) {
269 // TODO(zqiu): Parse DNSSL (DNS Search List) option.
270 type_ = kTypeDnssl;
271 return true;
272 } else if (nd_user_option_header->type == ND_OPT_RDNSS) {
273 // Parse RNDSS (Recursive DNS Server) option.
274 type_ = kTypeRdnss;
275 return ParseRdnssOption(option_data, data_len, lifetime);
276 }
277
278 return false;
279 }
280
ParseRdnssOption(const uint8_t * data,int length,uint32_t lifetime)281 bool RTNLMessage::ParseRdnssOption(const uint8_t* data,
282 int length,
283 uint32_t lifetime) {
284 const int addr_length = IPAddress::GetAddressLength(IPAddress::kFamilyIPv6);
285
286 // Verify data size are multiple of individual address size.
287 if (length % addr_length != 0) {
288 return false;
289 }
290
291 // Parse the DNS server addresses.
292 std::vector<IPAddress> dns_server_addresses;
293 while (length > 0) {
294 dns_server_addresses.push_back(
295 IPAddress(IPAddress::kFamilyIPv6,
296 ByteString(data, addr_length)));
297 length -= addr_length;
298 data += addr_length;
299 }
300 set_rdnss_option(RdnssOption(lifetime, dns_server_addresses));
301 return true;
302 }
303
DecodeNeighbor(const RTNLHeader * hdr,Mode mode,rtattr ** attr_data,int * attr_length)304 bool RTNLMessage::DecodeNeighbor(const RTNLHeader* hdr,
305 Mode mode,
306 rtattr** attr_data,
307 int* attr_length) {
308 if (hdr->hdr.nlmsg_len < NLMSG_LENGTH(sizeof(hdr->ndm))) {
309 return false;
310 }
311
312 mode_ = mode;
313 interface_index_ = hdr->ndm.ndm_ifindex;
314 family_ = hdr->ndm.ndm_family;
315 type_ = kTypeNeighbor;
316
317 *attr_data = RTM_RTA(NLMSG_DATA(&hdr->hdr));
318 *attr_length = RTM_PAYLOAD(&hdr->hdr);
319
320 set_neighbor_status(NeighborStatus(hdr->ndm.ndm_state,
321 hdr->ndm.ndm_flags,
322 hdr->ndm.ndm_type));
323 return true;
324 }
325
Encode() const326 ByteString RTNLMessage::Encode() const {
327 if (type_ != kTypeLink &&
328 type_ != kTypeAddress &&
329 type_ != kTypeRoute &&
330 type_ != kTypeNeighbor) {
331 return ByteString();
332 }
333
334 RTNLHeader hdr;
335 hdr.hdr.nlmsg_flags = flags_;
336 hdr.hdr.nlmsg_seq = seq_;
337 hdr.hdr.nlmsg_pid = pid_;
338
339 if (mode_ == kModeGet) {
340 if (type_ == kTypeLink) {
341 hdr.hdr.nlmsg_type = RTM_GETLINK;
342 } else if (type_ == kTypeAddress) {
343 hdr.hdr.nlmsg_type = RTM_GETADDR;
344 } else if (type_ == kTypeRoute) {
345 hdr.hdr.nlmsg_type = RTM_GETROUTE;
346 } else if (type_ == kTypeNeighbor) {
347 hdr.hdr.nlmsg_type = RTM_GETNEIGH;
348 } else {
349 NOTIMPLEMENTED();
350 return ByteString();
351 }
352 hdr.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(hdr.gen));
353 hdr.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
354 hdr.gen.rtgen_family = family_;
355 } else {
356 switch (type_) {
357 case kTypeLink:
358 if (!EncodeLink(&hdr)) {
359 return ByteString();
360 }
361 break;
362
363 case kTypeAddress:
364 if (!EncodeAddress(&hdr)) {
365 return ByteString();
366 }
367 break;
368
369 case kTypeRoute:
370 if (!EncodeRoute(&hdr)) {
371 return ByteString();
372 }
373 break;
374
375 case kTypeNeighbor:
376 if (!EncodeNeighbor(&hdr)) {
377 return ByteString();
378 }
379 break;
380
381 default:
382 NOTREACHED();
383 }
384 }
385
386 size_t header_length = hdr.hdr.nlmsg_len;
387 ByteString attributes;
388
389 for (auto attr = attributes_.begin(); attr != attributes_.end(); ++attr) {
390 size_t len = RTA_LENGTH(attr->second.GetLength());
391 hdr.hdr.nlmsg_len = NLMSG_ALIGN(hdr.hdr.nlmsg_len) + RTA_ALIGN(len);
392
393 struct rtattr rt_attr = {
394 static_cast<unsigned short>(len), // NOLINT(runtime/int)
395 attr->first
396 };
397 ByteString attr_header(reinterpret_cast<unsigned char*>(&rt_attr),
398 sizeof(rt_attr));
399 attr_header.Resize(RTA_ALIGN(attr_header.GetLength()));
400 attributes.Append(attr_header);
401
402 ByteString attr_data(attr->second);
403 attr_data.Resize(RTA_ALIGN(attr_data.GetLength()));
404 attributes.Append(attr_data);
405 }
406
407 ByteString packet(reinterpret_cast<unsigned char*>(&hdr), header_length);
408 packet.Append(attributes);
409
410 return packet;
411 }
412
EncodeLink(RTNLHeader * hdr) const413 bool RTNLMessage::EncodeLink(RTNLHeader* hdr) const {
414 switch (mode_) {
415 case kModeAdd:
416 hdr->hdr.nlmsg_type = RTM_NEWLINK;
417 break;
418 case kModeDelete:
419 hdr->hdr.nlmsg_type = RTM_DELLINK;
420 break;
421 case kModeQuery:
422 hdr->hdr.nlmsg_type = RTM_GETLINK;
423 break;
424 default:
425 NOTIMPLEMENTED();
426 return false;
427 }
428 hdr->hdr.nlmsg_len = NLMSG_LENGTH(sizeof(hdr->ifi));
429 hdr->ifi.ifi_family = family_;
430 hdr->ifi.ifi_index = interface_index_;
431 hdr->ifi.ifi_type = link_status_.type;
432 hdr->ifi.ifi_flags = link_status_.flags;
433 hdr->ifi.ifi_change = link_status_.change;
434 return true;
435 }
436
EncodeAddress(RTNLHeader * hdr) const437 bool RTNLMessage::EncodeAddress(RTNLHeader* hdr) const {
438 switch (mode_) {
439 case kModeAdd:
440 hdr->hdr.nlmsg_type = RTM_NEWADDR;
441 break;
442 case kModeDelete:
443 hdr->hdr.nlmsg_type = RTM_DELADDR;
444 break;
445 case kModeQuery:
446 hdr->hdr.nlmsg_type = RTM_GETADDR;
447 break;
448 default:
449 NOTIMPLEMENTED();
450 return false;
451 }
452 hdr->hdr.nlmsg_len = NLMSG_LENGTH(sizeof(hdr->ifa));
453 hdr->ifa.ifa_family = family_;
454 hdr->ifa.ifa_prefixlen = address_status_.prefix_len;
455 hdr->ifa.ifa_flags = address_status_.flags;
456 hdr->ifa.ifa_scope = address_status_.scope;
457 hdr->ifa.ifa_index = interface_index_;
458 return true;
459 }
460
EncodeRoute(RTNLHeader * hdr) const461 bool RTNLMessage::EncodeRoute(RTNLHeader* hdr) const {
462 switch (mode_) {
463 case kModeAdd:
464 hdr->hdr.nlmsg_type = RTM_NEWROUTE;
465 break;
466 case kModeDelete:
467 hdr->hdr.nlmsg_type = RTM_DELROUTE;
468 break;
469 case kModeQuery:
470 hdr->hdr.nlmsg_type = RTM_GETROUTE;
471 break;
472 default:
473 NOTIMPLEMENTED();
474 return false;
475 }
476 hdr->hdr.nlmsg_len = NLMSG_LENGTH(sizeof(hdr->rtm));
477 hdr->rtm.rtm_family = family_;
478 hdr->rtm.rtm_dst_len = route_status_.dst_prefix;
479 hdr->rtm.rtm_src_len = route_status_.src_prefix;
480 hdr->rtm.rtm_table = route_status_.table;
481 hdr->rtm.rtm_protocol = route_status_.protocol;
482 hdr->rtm.rtm_scope = route_status_.scope;
483 hdr->rtm.rtm_type = route_status_.type;
484 hdr->rtm.rtm_flags = route_status_.flags;
485 return true;
486 }
487
EncodeNeighbor(RTNLHeader * hdr) const488 bool RTNLMessage::EncodeNeighbor(RTNLHeader* hdr) const {
489 switch (mode_) {
490 case kModeAdd:
491 hdr->hdr.nlmsg_type = RTM_NEWNEIGH;
492 break;
493 case kModeDelete:
494 hdr->hdr.nlmsg_type = RTM_DELNEIGH;
495 break;
496 case kModeQuery:
497 hdr->hdr.nlmsg_type = RTM_GETNEIGH;
498 break;
499 default:
500 NOTIMPLEMENTED();
501 return false;
502 }
503 hdr->hdr.nlmsg_len = NLMSG_LENGTH(sizeof(hdr->ndm));
504 hdr->ndm.ndm_family = family_;
505 hdr->ndm.ndm_ifindex = interface_index_;
506 hdr->ndm.ndm_state = neighbor_status_.state;
507 hdr->ndm.ndm_flags = neighbor_status_.flags;
508 hdr->ndm.ndm_type = neighbor_status_.type;
509 return true;
510 }
511
Reset()512 void RTNLMessage::Reset() {
513 mode_ = kModeUnknown;
514 type_ = kTypeUnknown;
515 flags_ = 0;
516 seq_ = 0;
517 pid_ = 0;
518 interface_index_ = 0;
519 family_ = IPAddress::kFamilyUnknown;
520 link_status_ = LinkStatus();
521 address_status_ = AddressStatus();
522 route_status_ = RouteStatus();
523 attributes_.clear();
524 }
525
526 } // namespace shill
527