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 { 31 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 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 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 69 bool RTNLMessage::Decode(const ByteString& msg) { 70 bool ret = DecodeInternal(msg); 71 if (!ret) { 72 Reset(); 73 } 74 return ret; 75 } 76 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 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 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 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 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 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 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 326 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 413 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 437 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 461 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 488 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 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