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/netlink_attribute.h" 18 19 #include <linux/genetlink.h> 20 21 #include <cctype> 22 #include <map> 23 #include <memory> 24 #include <string> 25 26 #include <base/format_macros.h> 27 #include <base/logging.h> 28 #include <base/strings/stringprintf.h> 29 30 #include "shill/net/attribute_list.h" 31 #include "shill/net/control_netlink_attribute.h" 32 #include "shill/net/netlink_message.h" 33 #include "shill/net/nl80211_attribute.h" 34 35 using std::map; 36 using std::string; 37 using std::unique_ptr; 38 39 using base::StringAppendF; 40 using base::StringPrintf; 41 42 namespace shill { 43 44 NetlinkAttribute::NetlinkAttribute(int id, 45 const char* id_string, 46 Type datatype, 47 const char* datatype_string) 48 : has_a_value_(false), id_(id), id_string_(id_string), datatype_(datatype), 49 datatype_string_(datatype_string) {} 50 51 // static 52 NetlinkAttribute* NetlinkAttribute::NewNl80211AttributeFromId( 53 NetlinkMessage::MessageContext context, int id) { 54 unique_ptr<NetlinkAttribute> attr; 55 switch (id) { 56 case NL80211_ATTR_BSS: 57 attr.reset(new Nl80211AttributeBss()); 58 break; 59 case NL80211_ATTR_CIPHER_SUITES: 60 attr.reset(new Nl80211AttributeCipherSuites()); 61 break; 62 case NL80211_ATTR_CONTROL_PORT_ETHERTYPE: 63 attr.reset(new Nl80211AttributeControlPortEthertype()); 64 break; 65 case NL80211_ATTR_COOKIE: 66 attr.reset(new Nl80211AttributeCookie()); 67 break; 68 case NL80211_ATTR_CQM: 69 attr.reset(new Nl80211AttributeCqm()); 70 break; 71 case NL80211_ATTR_DEVICE_AP_SME: 72 attr.reset(new Nl80211AttributeDeviceApSme()); 73 break; 74 case NL80211_ATTR_DFS_REGION: 75 attr.reset(new Nl80211AttributeDfsRegion()); 76 break; 77 case NL80211_ATTR_DISCONNECTED_BY_AP: 78 attr.reset(new Nl80211AttributeDisconnectedByAp()); 79 break; 80 case NL80211_ATTR_DURATION: 81 attr.reset(new Nl80211AttributeDuration()); 82 break; 83 case NL80211_ATTR_FEATURE_FLAGS: 84 attr.reset(new Nl80211AttributeFeatureFlags()); 85 break; 86 case NL80211_ATTR_FRAME: 87 attr.reset(new Nl80211AttributeFrame()); 88 break; 89 case NL80211_ATTR_GENERATION: 90 attr.reset(new Nl80211AttributeGeneration()); 91 break; 92 case NL80211_ATTR_HT_CAPABILITY_MASK: 93 attr.reset(new Nl80211AttributeHtCapabilityMask()); 94 break; 95 case NL80211_ATTR_IFINDEX: 96 attr.reset(new Nl80211AttributeIfindex()); 97 break; 98 case NL80211_ATTR_IFTYPE: 99 attr.reset(new Nl80211AttributeIftype()); 100 break; 101 case NL80211_ATTR_KEY_IDX: 102 attr.reset(new Nl80211AttributeKeyIdx()); 103 break; 104 case NL80211_ATTR_KEY_SEQ: 105 attr.reset(new Nl80211AttributeKeySeq()); 106 break; 107 case NL80211_ATTR_KEY_TYPE: 108 attr.reset(new Nl80211AttributeKeyType()); 109 break; 110 case NL80211_ATTR_MAC: 111 attr.reset(new Nl80211AttributeMac()); 112 break; 113 case NL80211_ATTR_MAX_MATCH_SETS: 114 attr.reset(new Nl80211AttributeMaxMatchSets()); 115 break; 116 case NL80211_ATTR_MAX_NUM_PMKIDS: 117 attr.reset(new Nl80211AttributeMaxNumPmkids()); 118 break; 119 case NL80211_ATTR_MAX_NUM_SCAN_SSIDS: 120 attr.reset(new Nl80211AttributeMaxNumScanSsids()); 121 break; 122 case NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS: 123 attr.reset(new Nl80211AttributeMaxNumSchedScanSsids()); 124 break; 125 case NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION: 126 attr.reset(new Nl80211AttributeMaxRemainOnChannelDuration()); 127 break; 128 case NL80211_ATTR_MAX_SCAN_IE_LEN: 129 attr.reset(new Nl80211AttributeMaxScanIeLen()); 130 break; 131 case NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN: 132 attr.reset(new Nl80211AttributeMaxSchedScanIeLen()); 133 break; 134 case NL80211_ATTR_OFFCHANNEL_TX_OK: 135 attr.reset(new Nl80211AttributeOffchannelTxOk()); 136 break; 137 case NL80211_ATTR_PROBE_RESP_OFFLOAD: 138 attr.reset(new Nl80211AttributeProbeRespOffload()); 139 break; 140 case NL80211_ATTR_REASON_CODE: 141 attr.reset(new Nl80211AttributeReasonCode()); 142 break; 143 case NL80211_ATTR_REG_ALPHA2: 144 attr.reset(new Nl80211AttributeRegAlpha2()); 145 break; 146 case NL80211_ATTR_REG_INITIATOR: 147 attr.reset(new Nl80211AttributeRegInitiator()); 148 break; 149 case NL80211_ATTR_REG_RULES: 150 attr.reset(new Nl80211AttributeRegRules()); 151 break; 152 case NL80211_ATTR_REG_TYPE: 153 attr.reset(new Nl80211AttributeRegType()); 154 break; 155 case NL80211_ATTR_RESP_IE: 156 attr.reset(new Nl80211AttributeRespIe()); 157 break; 158 case NL80211_ATTR_ROAM_SUPPORT: 159 attr.reset(new Nl80211AttributeRoamSupport()); 160 break; 161 case NL80211_ATTR_SCAN_FREQUENCIES: 162 attr.reset(new Nl80211AttributeScanFrequencies()); 163 break; 164 case NL80211_ATTR_SCAN_SSIDS: 165 attr.reset(new Nl80211AttributeScanSsids()); 166 break; 167 case NL80211_ATTR_STA_INFO: 168 attr.reset(new Nl80211AttributeStaInfo()); 169 break; 170 case NL80211_ATTR_STATUS_CODE: 171 attr.reset(new Nl80211AttributeStatusCode()); 172 break; 173 case NL80211_ATTR_SUPPORT_AP_UAPSD: 174 attr.reset(new Nl80211AttributeSupportApUapsd()); 175 break; 176 case NL80211_ATTR_SUPPORT_IBSS_RSN: 177 attr.reset(new Nl80211AttributeSupportIbssRsn()); 178 break; 179 case NL80211_ATTR_SUPPORT_MESH_AUTH: 180 attr.reset(new Nl80211AttributeSupportMeshAuth()); 181 break; 182 case NL80211_ATTR_SUPPORTED_IFTYPES: 183 attr.reset(new Nl80211AttributeSupportedIftypes()); 184 break; 185 case NL80211_ATTR_TDLS_EXTERNAL_SETUP: 186 attr.reset(new Nl80211AttributeTdlsExternalSetup()); 187 break; 188 case NL80211_ATTR_TDLS_SUPPORT: 189 attr.reset(new Nl80211AttributeTdlsSupport()); 190 break; 191 case NL80211_ATTR_TIMED_OUT: 192 attr.reset(new Nl80211AttributeTimedOut()); 193 break; 194 case NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX: 195 attr.reset(new Nl80211AttributeWiphyAntennaAvailRx()); 196 break; 197 case NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX: 198 attr.reset(new Nl80211AttributeWiphyAntennaAvailTx()); 199 break; 200 case NL80211_ATTR_WIPHY_ANTENNA_RX: 201 attr.reset(new Nl80211AttributeWiphyAntennaRx()); 202 break; 203 case NL80211_ATTR_WIPHY_ANTENNA_TX: 204 attr.reset(new Nl80211AttributeWiphyAntennaTx()); 205 break; 206 case NL80211_ATTR_WIPHY_BANDS: 207 attr.reset(new Nl80211AttributeWiphyBands()); 208 break; 209 case NL80211_ATTR_WIPHY_COVERAGE_CLASS: 210 attr.reset(new Nl80211AttributeWiphyCoverageClass()); 211 break; 212 case NL80211_ATTR_WIPHY_FRAG_THRESHOLD: 213 attr.reset(new Nl80211AttributeWiphyFragThreshold()); 214 break; 215 case NL80211_ATTR_WIPHY_FREQ: 216 attr.reset(new Nl80211AttributeWiphyFreq()); 217 break; 218 case NL80211_ATTR_WIPHY_CHANNEL_TYPE: 219 attr.reset(new Nl80211AttributeChannelType()); 220 break; 221 case NL80211_ATTR_CHANNEL_WIDTH: 222 attr.reset(new Nl80211AttributeChannelWidth()); 223 break; 224 case NL80211_ATTR_CENTER_FREQ1: 225 attr.reset(new Nl80211AttributeCenterFreq1()); 226 break; 227 case NL80211_ATTR_CENTER_FREQ2: 228 attr.reset(new Nl80211AttributeCenterFreq2()); 229 break; 230 case NL80211_ATTR_WIPHY: 231 attr.reset(new Nl80211AttributeWiphy()); 232 break; 233 case NL80211_ATTR_WIPHY_NAME: 234 attr.reset(new Nl80211AttributeWiphyName()); 235 break; 236 case NL80211_ATTR_WIPHY_RETRY_LONG: 237 attr.reset(new Nl80211AttributeWiphyRetryLong()); 238 break; 239 case NL80211_ATTR_WIPHY_RETRY_SHORT: 240 attr.reset(new Nl80211AttributeWiphyRetryShort()); 241 break; 242 case NL80211_ATTR_WIPHY_RTS_THRESHOLD: 243 attr.reset(new Nl80211AttributeWiphyRtsThreshold()); 244 break; 245 #if !defined(DISABLE_WAKE_ON_WIFI) 246 case NL80211_ATTR_WOWLAN_TRIGGERS: 247 attr.reset(new Nl80211AttributeWowlanTriggers(context)); 248 break; 249 case NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED: 250 attr.reset(new Nl80211AttributeWowlanTriggersSupported()); 251 break; 252 #endif // DISABLE_WAKE_ON_WIFI 253 case NL80211_ATTR_SURVEY_INFO: 254 attr.reset(new Nl80211AttributeSurveyInfo()); 255 break; 256 default: 257 attr.reset(new NetlinkAttributeGeneric(id)); 258 break; 259 } 260 return attr.release(); 261 } 262 263 // static 264 NetlinkAttribute* NetlinkAttribute::NewControlAttributeFromId(int id) { 265 unique_ptr<NetlinkAttribute> attr; 266 switch (id) { 267 case CTRL_ATTR_FAMILY_ID: 268 attr.reset(new ControlAttributeFamilyId()); 269 break; 270 case CTRL_ATTR_FAMILY_NAME: 271 attr.reset(new ControlAttributeFamilyName()); 272 break; 273 case CTRL_ATTR_VERSION: 274 attr.reset(new ControlAttributeVersion()); 275 break; 276 case CTRL_ATTR_HDRSIZE: 277 attr.reset(new ControlAttributeHdrSize()); 278 break; 279 case CTRL_ATTR_MAXATTR: 280 attr.reset(new ControlAttributeMaxAttr()); 281 break; 282 case CTRL_ATTR_OPS: 283 attr.reset(new ControlAttributeAttrOps()); 284 break; 285 case CTRL_ATTR_MCAST_GROUPS: 286 attr.reset(new ControlAttributeMcastGroups()); 287 break; 288 default: 289 attr.reset(new NetlinkAttributeGeneric(id)); 290 break; 291 } 292 return attr.release(); 293 } 294 295 // Duplicate attribute data, store in map indexed on |id|. 296 bool NetlinkAttribute::InitFromValue(const ByteString& input) { 297 data_ = input; 298 return true; 299 } 300 301 bool NetlinkAttribute::GetU8Value(uint8_t* value) const { 302 LOG(ERROR) << "Attribute is not of type 'U8'"; 303 return false; 304 } 305 306 bool NetlinkAttribute::SetU8Value(uint8_t value) { 307 LOG(ERROR) << "Attribute is not of type 'U8'"; 308 return false; 309 } 310 311 bool NetlinkAttribute::GetU16Value(uint16_t* value) const { 312 LOG(ERROR) << "Attribute is not of type 'U16'"; 313 return false; 314 } 315 316 bool NetlinkAttribute::SetU16Value(uint16_t value) { 317 LOG(ERROR) << "Attribute is not of type 'U16'"; 318 return false; 319 } 320 321 bool NetlinkAttribute::GetU32Value(uint32_t* value) const { 322 LOG(ERROR) << "Attribute is not of type 'U32'"; 323 return false; 324 } 325 326 bool NetlinkAttribute::SetU32Value(uint32_t value) { 327 LOG(ERROR) << "Attribute is not of type 'U32'"; 328 return false; 329 } 330 331 bool NetlinkAttribute::GetU64Value(uint64_t* value) const { 332 LOG(ERROR) << "Attribute is not of type 'U64'"; 333 return false; 334 } 335 336 bool NetlinkAttribute::SetU64Value(uint64_t value) { 337 LOG(ERROR) << "Attribute is not of type 'U64'"; 338 return false; 339 } 340 341 bool NetlinkAttribute::GetFlagValue(bool* value) const { 342 LOG(ERROR) << "Attribute is not of type 'Flag'"; 343 return false; 344 } 345 346 bool NetlinkAttribute::SetFlagValue(bool value) { 347 LOG(ERROR) << "Attribute is not of type 'Flag'"; 348 return false; 349 } 350 351 bool NetlinkAttribute::GetStringValue(string* value) const { 352 LOG(ERROR) << "Attribute is not of type 'String'"; 353 return false; 354 } 355 356 bool NetlinkAttribute::SetStringValue(string value) { 357 LOG(ERROR) << "Attribute is not of type 'String'"; 358 return false; 359 } 360 361 bool NetlinkAttribute::GetNestedAttributeList(AttributeListRefPtr* value) { 362 LOG(ERROR) << "Attribute is not of type 'Nested'"; 363 return false; 364 } 365 366 bool NetlinkAttribute::ConstGetNestedAttributeList( 367 AttributeListConstRefPtr* value) const { 368 LOG(ERROR) << "Attribute is not of type 'Nested'"; 369 return false; 370 } 371 372 bool NetlinkAttribute::SetNestedHasAValue() { 373 LOG(ERROR) << "Attribute is not of type 'Nested'"; 374 return false; 375 } 376 377 bool NetlinkAttribute::GetRawValue(ByteString* value) const { 378 LOG(ERROR) << "Attribute is not of type 'Raw'"; 379 return false; 380 } 381 382 bool NetlinkAttribute::SetRawValue(const ByteString new_value) { 383 LOG(ERROR) << "Attribute is not of type 'Raw'"; 384 return false; 385 } 386 387 void NetlinkAttribute::Print(int log_level, int indent) const { 388 string attribute_value; 389 VLOG(log_level) << HeaderToPrint(indent) << " " 390 << (ToString(&attribute_value) ? attribute_value : 391 "<DOES NOT EXIST>"); 392 } 393 394 string NetlinkAttribute::RawToString() const { 395 string output = " === RAW: "; 396 397 if (!has_a_value_) { 398 StringAppendF(&output, "(empty)"); 399 return output; 400 } 401 402 uint16_t length = data_.GetLength(); 403 const uint8_t* const_data = data_.GetConstData(); 404 405 StringAppendF(&output, "len=%u", length); 406 output.append(" DATA: "); 407 for (int i =0 ; i < length; ++i) { 408 StringAppendF(&output, "[%d]=%02x ", i, *(const_data)+i); 409 } 410 output.append(" ==== "); 411 return output; 412 } 413 414 string NetlinkAttribute::HeaderToPrint(int indent) const { 415 static const int kSpacesPerIndent = 2; 416 return StringPrintf("%*s%s(%d) %s %s=", 417 indent * kSpacesPerIndent, "", 418 id_string(), 419 id(), 420 datatype_string(), 421 ((has_a_value()) ? "": "UNINITIALIZED ")); 422 } 423 424 ByteString NetlinkAttribute::EncodeGeneric(const unsigned char* data, 425 size_t num_bytes) const { 426 ByteString result; 427 if (has_a_value_) { 428 nlattr header; 429 header.nla_type = id(); 430 header.nla_len = NLA_HDRLEN + num_bytes; 431 result = ByteString(reinterpret_cast<unsigned char*>(&header), 432 sizeof(header)); 433 result.Resize(NLA_HDRLEN); // Add padding after the header. 434 if (data && (num_bytes != 0)) { 435 result.Append(ByteString(data, num_bytes)); 436 } 437 result.Resize(NLA_ALIGN(result.GetLength())); // Add padding. 438 } 439 return result; 440 } 441 442 // NetlinkU8Attribute 443 444 const char NetlinkU8Attribute::kMyTypeString[] = "uint8_t"; 445 const NetlinkAttribute::Type NetlinkU8Attribute::kType = 446 NetlinkAttribute::kTypeU8; 447 448 bool NetlinkU8Attribute::InitFromValue(const ByteString& input) { 449 uint8_t data; 450 if (!input.CopyData(sizeof(data), &data)) { 451 LOG(ERROR) << "Invalid |input| for " << id_string() << " of type " 452 << datatype_string() << ": expected " << sizeof(data) 453 << " bytes but only had " << input.GetLength() << "."; 454 return false; 455 } 456 SetU8Value(data); 457 return NetlinkAttribute::InitFromValue(input); 458 } 459 460 bool NetlinkU8Attribute::GetU8Value(uint8_t* output) const { 461 if (!has_a_value_) { 462 VLOG(7) << "U8 attribute " << id_string() 463 << " hasn't been set to any value."; 464 return false; 465 } 466 if (output) { 467 *output = value_; 468 } 469 return true; 470 } 471 472 bool NetlinkU8Attribute::SetU8Value(uint8_t new_value) { 473 value_ = new_value; 474 has_a_value_ = true; 475 return true; 476 } 477 478 bool NetlinkU8Attribute::ToString(string* output) const { 479 if (!output) { 480 LOG(ERROR) << "Null |output| parameter"; 481 return false; 482 } 483 uint8_t value; 484 if (!GetU8Value(&value)) 485 return false; 486 *output = StringPrintf("%u", value); 487 return true; 488 } 489 490 ByteString NetlinkU8Attribute::Encode() const { 491 return NetlinkAttribute::EncodeGeneric( 492 reinterpret_cast<const unsigned char*>(&value_), sizeof(value_)); 493 } 494 495 // NetlinkU16Attribute 496 497 const char NetlinkU16Attribute::kMyTypeString[] = "uint16_t"; 498 const NetlinkAttribute::Type NetlinkU16Attribute::kType = 499 NetlinkAttribute::kTypeU16; 500 501 bool NetlinkU16Attribute::InitFromValue(const ByteString& input) { 502 uint16_t data; 503 if (!input.CopyData(sizeof(data), &data)) { 504 LOG(ERROR) << "Invalid |input| for " << id_string() << " of type " 505 << datatype_string() << ": expected " << sizeof(data) 506 << " bytes but only had " << input.GetLength() << "."; 507 return false; 508 } 509 510 SetU16Value(data); 511 return NetlinkAttribute::InitFromValue(input); 512 } 513 514 bool NetlinkU16Attribute::GetU16Value(uint16_t* output) const { 515 if (!has_a_value_) { 516 VLOG(7) << "U16 attribute " << id_string() 517 << " hasn't been set to any value."; 518 return false; 519 } 520 if (output) { 521 *output = value_; 522 } 523 return true; 524 } 525 526 bool NetlinkU16Attribute::SetU16Value(uint16_t new_value) { 527 value_ = new_value; 528 has_a_value_ = true; 529 return true; 530 } 531 532 bool NetlinkU16Attribute::ToString(string* output) const { 533 if (!output) { 534 LOG(ERROR) << "Null |output| parameter"; 535 return false; 536 } 537 uint16_t value; 538 if (!GetU16Value(&value)) 539 return false; 540 *output = StringPrintf("%u", value); 541 return true; 542 } 543 544 ByteString NetlinkU16Attribute::Encode() const { 545 return NetlinkAttribute::EncodeGeneric( 546 reinterpret_cast<const unsigned char*>(&value_), sizeof(value_)); 547 } 548 549 // NetlinkU32Attribute:: 550 551 const char NetlinkU32Attribute::kMyTypeString[] = "uint32_t"; 552 const NetlinkAttribute::Type NetlinkU32Attribute::kType = 553 NetlinkAttribute::kTypeU32; 554 555 bool NetlinkU32Attribute::InitFromValue(const ByteString& input) { 556 uint32_t data; 557 if (!input.CopyData(sizeof(data), &data)) { 558 LOG(ERROR) << "Invalid |input| for " << id_string() << " of type " 559 << datatype_string() << ": expected " << sizeof(data) 560 << " bytes but only had " << input.GetLength() << "."; 561 return false; 562 } 563 564 SetU32Value(data); 565 return NetlinkAttribute::InitFromValue(input); 566 } 567 568 bool NetlinkU32Attribute::GetU32Value(uint32_t* output) const { 569 if (!has_a_value_) { 570 VLOG(7) << "U32 attribute " << id_string() 571 << " hasn't been set to any value."; 572 return false; 573 } 574 if (output) { 575 *output = value_; 576 } 577 return true; 578 } 579 580 bool NetlinkU32Attribute::SetU32Value(uint32_t new_value) { 581 value_ = new_value; 582 has_a_value_ = true; 583 return true; 584 } 585 586 bool NetlinkU32Attribute::ToString(string* output) const { 587 if (!output) { 588 LOG(ERROR) << "Null |output| parameter"; 589 return false; 590 } 591 uint32_t value; 592 if (!GetU32Value(&value)) 593 return false; 594 *output = StringPrintf("%" PRIu32, value); 595 return true; 596 } 597 598 ByteString NetlinkU32Attribute::Encode() const { 599 return NetlinkAttribute::EncodeGeneric( 600 reinterpret_cast<const unsigned char*>(&value_), sizeof(value_)); 601 } 602 603 // NetlinkU64Attribute 604 605 const char NetlinkU64Attribute::kMyTypeString[] = "uint64_t"; 606 const NetlinkAttribute::Type NetlinkU64Attribute::kType = 607 NetlinkAttribute::kTypeU64; 608 609 bool NetlinkU64Attribute::InitFromValue(const ByteString& input) { 610 uint64_t data; 611 if (!input.CopyData(sizeof(data), &data)) { 612 LOG(ERROR) << "Invalid |input| for " << id_string() << " of type " 613 << datatype_string() << ": expected " << sizeof(data) 614 << " bytes but only had " << input.GetLength() << "."; 615 return false; 616 } 617 SetU64Value(data); 618 return NetlinkAttribute::InitFromValue(input); 619 } 620 621 bool NetlinkU64Attribute::GetU64Value(uint64_t* output) const { 622 if (!has_a_value_) { 623 VLOG(7) << "U64 attribute " << id_string() 624 << " hasn't been set to any value."; 625 return false; 626 } 627 if (output) { 628 *output = value_; 629 } 630 return true; 631 } 632 633 bool NetlinkU64Attribute::SetU64Value(uint64_t new_value) { 634 value_ = new_value; 635 has_a_value_ = true; 636 return true; 637 } 638 639 bool NetlinkU64Attribute::ToString(string* output) const { 640 if (!output) { 641 LOG(ERROR) << "Null |output| parameter"; 642 return false; 643 } 644 uint64_t value; 645 if (!GetU64Value(&value)) 646 return false; 647 *output = StringPrintf("%" PRIu64, value); 648 return true; 649 } 650 651 ByteString NetlinkU64Attribute::Encode() const { 652 return NetlinkAttribute::EncodeGeneric( 653 reinterpret_cast<const unsigned char*>(&value_), sizeof(value_)); 654 } 655 656 // NetlinkFlagAttribute 657 658 const char NetlinkFlagAttribute::kMyTypeString[] = "flag"; 659 const NetlinkAttribute::Type NetlinkFlagAttribute::kType = 660 NetlinkAttribute::kTypeFlag; 661 662 bool NetlinkFlagAttribute::InitFromValue(const ByteString& input) { 663 // The existence of the parameter means it's true 664 SetFlagValue(true); 665 return NetlinkAttribute::InitFromValue(input); 666 } 667 668 669 bool NetlinkFlagAttribute::GetFlagValue(bool* output) const { 670 if (output) { 671 // The lack of the existence of the attribute implies 'false'. 672 *output = (has_a_value_) ? value_ : false; 673 } 674 return true; 675 } 676 677 bool NetlinkFlagAttribute::SetFlagValue(bool new_value) { 678 value_ = new_value; 679 has_a_value_ = true; 680 return true; 681 } 682 683 bool NetlinkFlagAttribute::ToString(string* output) const { 684 if (!output) { 685 LOG(ERROR) << "Null |output| parameter"; 686 return false; 687 } 688 bool value; 689 if (!GetFlagValue(&value)) 690 return false; 691 *output = StringPrintf("%s", value ? "true" : "false"); 692 return true; 693 } 694 695 ByteString NetlinkFlagAttribute::Encode() const { 696 if (has_a_value_ && value_) { 697 return NetlinkAttribute::EncodeGeneric(nullptr, 0); 698 } 699 return ByteString(); // Encoding of nothing implies 'false'. 700 } 701 702 // NetlinkStringAttribute 703 704 const char NetlinkStringAttribute::kMyTypeString[] = "string"; 705 const NetlinkAttribute::Type NetlinkStringAttribute::kType = 706 NetlinkAttribute::kTypeString; 707 708 bool NetlinkStringAttribute::InitFromValue(const ByteString& input) { 709 if (!input.GetLength()) { 710 // Assume an empty string. 711 SetStringValue(""); 712 } else { 713 const char* string_ptr = 714 reinterpret_cast<const char*>(input.GetConstData()); 715 const char* first_null_pos = reinterpret_cast<const char*>( 716 memchr(string_ptr, '\0', input.GetLength())); 717 if (first_null_pos == string_ptr + input.GetLength() - 1) { 718 SetStringValue(string_ptr); 719 } else if (first_null_pos) { 720 LOG(WARNING) << "String appears to be terminated " 721 << (input.GetLength() - 1) - (first_null_pos - string_ptr) 722 << " bytes early."; 723 SetStringValue(string_ptr); 724 } else { 725 VLOG(1) << "String is unterminated."; 726 SetStringValue(string(string_ptr, input.GetLength())); 727 } 728 } 729 730 return NetlinkAttribute::InitFromValue(input); 731 } 732 733 bool NetlinkStringAttribute::GetStringValue(string* output) const { 734 if (!has_a_value_) { 735 VLOG(7) << "String attribute " << id_string() 736 << " hasn't been set to any value."; 737 return false; 738 } 739 if (output) { 740 *output = value_; 741 } 742 return true; 743 } 744 745 bool NetlinkStringAttribute::SetStringValue(const string new_value) { 746 value_ = new_value; 747 has_a_value_ = true; 748 return true; 749 } 750 751 bool NetlinkStringAttribute::ToString(string* output) const { 752 if (!output) { 753 LOG(ERROR) << "Null |output| parameter"; 754 return false; 755 } 756 string value; 757 if (!GetStringValue(&value)) 758 return false; 759 760 *output = StringPrintf("'%s'", value.c_str()); 761 return true; 762 } 763 764 ByteString NetlinkStringAttribute::Encode() const { 765 return NetlinkAttribute::EncodeGeneric( 766 reinterpret_cast<const unsigned char*>(value_.c_str()), 767 value_.size() + 1); 768 } 769 770 // SSID attribute. 771 772 bool NetlinkSsidAttribute::ToString(string* output) const { 773 if (!output) { 774 LOG(ERROR) << "Null |output| parameter"; 775 return false; 776 } 777 string value; 778 if (!GetStringValue(&value)) 779 return false; 780 781 string temp; 782 for (const auto& chr : value) { 783 // Replace '[' and ']' (in addition to non-printable characters) so that 784 // it's easy to match the right substring through a non-greedy regex. 785 if (chr == '[' || chr == ']' || !std::isprint(chr)) { 786 base::StringAppendF(&temp, "\\x%02x", chr); 787 } else { 788 temp += chr; 789 } 790 } 791 *output = StringPrintf("[SSID=%s]", temp.c_str()); 792 793 return true; 794 } 795 796 // NetlinkNestedAttribute 797 798 const char NetlinkNestedAttribute::kMyTypeString[] = "nested"; 799 const NetlinkAttribute::Type NetlinkNestedAttribute::kType = 800 NetlinkAttribute::kTypeNested; 801 const size_t NetlinkNestedAttribute::kArrayAttrEnumVal = 0; 802 803 NetlinkNestedAttribute::NetlinkNestedAttribute(int id, 804 const char* id_string) : 805 NetlinkAttribute(id, id_string, kType, kMyTypeString), 806 value_(new AttributeList) {} 807 808 ByteString NetlinkNestedAttribute::Encode() const { 809 // Encode attribute header. 810 nlattr header; 811 header.nla_type = id(); 812 header.nla_len = 0; // Filled in at the end. 813 ByteString result(reinterpret_cast<unsigned char*>(&header), sizeof(header)); 814 result.Resize(NLA_HDRLEN); // Add padding after the header. 815 816 // Encode all nested attributes. 817 map<int, AttributeList::AttributePointer>::const_iterator attribute; 818 for (attribute = value_->attributes_.begin(); 819 attribute != value_->attributes_.end(); 820 ++attribute) { 821 // Each attribute appends appropriate padding so it's not necessary to 822 // re-add padding. 823 result.Append(attribute->second->Encode()); 824 } 825 826 // Go back and fill-in the size. 827 nlattr* new_header = reinterpret_cast<nlattr*>(result.GetData()); 828 new_header->nla_len = result.GetLength(); 829 830 return result; 831 } 832 833 void NetlinkNestedAttribute::Print(int log_level, int indent) const { 834 VLOG(log_level) << HeaderToPrint(indent); 835 value_->Print(log_level, indent + 1); 836 } 837 838 bool NetlinkNestedAttribute::ToString(string* output) const { 839 if (!output) { 840 LOG(ERROR) << "Null |output| parameter"; 841 return false; 842 } 843 844 // This should never be called (attribute->ToString is only called 845 // from attribute->Print but NetlinkNestedAttribute::Print doesn't call 846 // |ToString|. Still, we should print something in case we got here 847 // accidentally. 848 LOG(WARNING) << "It is unexpected for this method to be called."; 849 output->append("<Nested Attribute>"); 850 return true; 851 } 852 853 bool NetlinkNestedAttribute::InitFromValue(const ByteString& input) { 854 if (!InitNestedFromValue(value_, nested_template_, input)) { 855 LOG(ERROR) << "InitNestedFromValue() failed"; 856 return false; 857 } 858 has_a_value_ = true; 859 return true; 860 } 861 862 bool NetlinkNestedAttribute::GetNestedAttributeList( 863 AttributeListRefPtr* output) { 864 // Not checking |has_a_value| since GetNestedAttributeList is called to get 865 // a newly created AttributeList in order to have something to which to add 866 // attributes. 867 if (output) { 868 *output = value_; 869 } 870 return true; 871 } 872 873 bool NetlinkNestedAttribute::ConstGetNestedAttributeList( 874 AttributeListConstRefPtr* output) const { 875 if (!has_a_value_) { 876 LOG(ERROR) << "Attribute does not exist."; 877 return false; 878 } 879 if (output) { 880 *output = value_; 881 } 882 return true; 883 } 884 885 bool NetlinkNestedAttribute::SetNestedHasAValue() { 886 has_a_value_ = true; 887 return true; 888 } 889 890 bool NetlinkNestedAttribute::InitNestedFromValue( 891 const AttributeListRefPtr& list, 892 const NetlinkNestedAttribute::NestedData::NestedDataMap& templates, 893 const ByteString& value) { 894 if (templates.empty()) { 895 LOG(ERROR) << "|templates| size is zero"; 896 return false; 897 } 898 if (templates.size() == 1 && templates.cbegin()->second.is_array) { 899 return AttributeList::IterateAttributes( 900 value, 0, base::Bind( 901 &NetlinkNestedAttribute::AddAttributeToNestedArray, 902 templates.cbegin()->second, list)); 903 } else { 904 return AttributeList::IterateAttributes( 905 value, 0, base::Bind( 906 &NetlinkNestedAttribute::AddAttributeToNestedMap, 907 templates, list)); 908 } 909 } 910 911 // static 912 bool NetlinkNestedAttribute::AddAttributeToNestedArray( 913 const NetlinkNestedAttribute::NestedData& array_template, 914 const AttributeListRefPtr& list, int id, const ByteString& value) { 915 string attribute_name = StringPrintf( 916 "%s_%d", array_template.attribute_name.c_str(), id); 917 return AddAttributeToNestedInner( 918 array_template, attribute_name, list, id, value); 919 } 920 921 // static 922 bool NetlinkNestedAttribute::AddAttributeToNestedMap( 923 const NetlinkNestedAttribute::NestedData::NestedDataMap& templates, 924 const AttributeListRefPtr& list, int id, const ByteString& value) { 925 auto template_it = templates.find(id); 926 if (template_it == templates.end()) { 927 // No interest in this value. 928 return true; 929 } 930 const NestedData& nested_template = template_it->second; 931 return AddAttributeToNestedInner( 932 nested_template, nested_template.attribute_name, list, id, value); 933 } 934 935 // static 936 bool NetlinkNestedAttribute::AddAttributeToNestedInner( 937 const NetlinkNestedAttribute::NestedData& nested_template, 938 const string& attribute_name, const AttributeListRefPtr& list, 939 int id, const ByteString& value) { 940 CHECK(list); 941 if (!nested_template.parse_attribute.is_null()) { 942 if (!nested_template.parse_attribute.Run( 943 list.get(), id, attribute_name, value)) { 944 LOG(WARNING) << "Custom attribute parser returned |false| for " 945 << attribute_name << "(" << id << ")."; 946 return false; 947 } 948 return true; 949 } 950 switch (nested_template.type) { 951 case kTypeRaw: 952 list->CreateRawAttribute(id, attribute_name.c_str()); 953 return list->SetRawAttributeValue(id, value); 954 case kTypeU8: 955 list->CreateU8Attribute(id, attribute_name.c_str()); 956 return list->InitAttributeFromValue(id, value); 957 case kTypeU16: 958 list->CreateU16Attribute(id, attribute_name.c_str()); 959 return list->InitAttributeFromValue(id, value); 960 case kTypeU32: 961 list->CreateU32Attribute(id, attribute_name.c_str()); 962 return list->InitAttributeFromValue(id, value); 963 break; 964 case kTypeU64: 965 list->CreateU64Attribute(id, attribute_name.c_str()); 966 return list->InitAttributeFromValue(id, value); 967 case kTypeFlag: 968 list->CreateFlagAttribute(id, attribute_name.c_str()); 969 return list->SetFlagAttributeValue(id, true); 970 case kTypeString: 971 list->CreateStringAttribute(id, attribute_name.c_str()); 972 return list->InitAttributeFromValue(id, value); 973 case kTypeNested: 974 { 975 if (nested_template.deeper_nesting.empty()) { 976 LOG(ERROR) << "No rules for nesting " << attribute_name 977 << ". Ignoring."; 978 break; 979 } 980 list->CreateNestedAttribute(id, attribute_name.c_str()); 981 982 // Now, handle the nested data. 983 AttributeListRefPtr nested_attribute; 984 if (!list->GetNestedAttributeList(id, &nested_attribute) || 985 !nested_attribute) { 986 LOG(FATAL) << "Couldn't get attribute " << attribute_name 987 << " which we just created."; 988 return false; 989 } 990 991 if (!InitNestedFromValue(nested_attribute, 992 nested_template.deeper_nesting, 993 value)) { 994 LOG(ERROR) << "Couldn't parse attribute " << attribute_name; 995 return false; 996 } 997 list->SetNestedAttributeHasAValue(id); 998 } 999 break; 1000 default: 1001 LOG(ERROR) << "Discarding " << attribute_name 1002 << ". Attribute has unhandled type " 1003 << nested_template.type << "."; 1004 break; 1005 } 1006 return true; 1007 } 1008 1009 NetlinkNestedAttribute::NestedData::NestedData() 1010 : type(kTypeRaw), attribute_name("<UNKNOWN>"), is_array(false) {} 1011 NetlinkNestedAttribute::NestedData::NestedData( 1012 NetlinkAttribute::Type type_arg, string attribute_name_arg, 1013 bool is_array_arg) 1014 : type(type_arg), attribute_name(attribute_name_arg), 1015 is_array(is_array_arg) {} 1016 1017 NetlinkNestedAttribute::NestedData::NestedData( 1018 NetlinkAttribute::Type type_arg, string attribute_name_arg, 1019 bool is_array_arg, const AttributeParser& parse_attribute_arg) 1020 : type(type_arg), attribute_name(attribute_name_arg), 1021 is_array(is_array_arg), parse_attribute(parse_attribute_arg) {} 1022 1023 // NetlinkRawAttribute 1024 1025 const char NetlinkRawAttribute::kMyTypeString[] = "<raw>"; 1026 const NetlinkAttribute::Type NetlinkRawAttribute::kType = 1027 NetlinkAttribute::kTypeRaw; 1028 1029 bool NetlinkRawAttribute::InitFromValue(const ByteString& input) { 1030 if (!NetlinkAttribute::InitFromValue(input)) { 1031 return false; 1032 } 1033 has_a_value_ = true; 1034 return true; 1035 } 1036 1037 bool NetlinkRawAttribute::GetRawValue(ByteString* output) const { 1038 if (!has_a_value_) { 1039 VLOG(7) << "Raw attribute " << id_string() 1040 << " hasn't been set to any value."; 1041 return false; 1042 } 1043 if (output) { 1044 *output = data_; 1045 } 1046 return true; 1047 } 1048 1049 bool NetlinkRawAttribute::SetRawValue(const ByteString new_value) { 1050 data_ = new_value; 1051 has_a_value_ = true; 1052 return true; 1053 } 1054 1055 bool NetlinkRawAttribute::ToString(string* output) const { 1056 if (!output) { 1057 LOG(ERROR) << "Null |output| parameter"; 1058 return false; 1059 } 1060 if (!has_a_value_) { 1061 VLOG(7) << "Raw attribute " << id_string() 1062 << " hasn't been set to any value."; 1063 return false; 1064 } 1065 int total_bytes = data_.GetLength(); 1066 const uint8_t* const_data = data_.GetConstData(); 1067 1068 *output = StringPrintf("%d bytes:", total_bytes); 1069 for (int i = 0; i < total_bytes; ++i) { 1070 StringAppendF(output, " 0x%02x", const_data[i]); 1071 } 1072 return true; 1073 } 1074 1075 ByteString NetlinkRawAttribute::Encode() const { 1076 return NetlinkAttribute::EncodeGeneric(data_.GetConstData(), 1077 data_.GetLength()); 1078 } 1079 1080 NetlinkAttributeGeneric::NetlinkAttributeGeneric(int id) 1081 : NetlinkRawAttribute(id, "unused-string") { 1082 StringAppendF(&id_string_, "<UNKNOWN ATTRIBUTE %d>", id); 1083 } 1084 1085 const char* NetlinkAttributeGeneric::id_string() const { 1086 return id_string_.c_str(); 1087 } 1088 1089 } // namespace shill 1090