blob: d54b5244ac1007c6975099289162be7a890095d5 [file] [log] [blame]
// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "shill/nl80211_attribute.h"
#include <ctype.h>
#include <linux/nl80211.h>
#include <netlink/attr.h>
#include <netlink/netlink.h>
#include <iomanip>
#include <string>
#include <base/format_macros.h>
#include <base/stl_util.h>
#include <base/stringprintf.h>
#include "shill/logging.h"
#include "shill/scope_logger.h"
using std::string;
using base::StringAppendF;
using base::StringPrintf;
namespace shill {
Nl80211Attribute::Nl80211Attribute(enum nl80211_attrs name,
const char *name_string,
Type type,
const char *type_string)
: name_(name), name_string_(name_string), type_(type),
type_string_(type_string) {}
// static
Nl80211Attribute *Nl80211Attribute::NewFromNlAttr(nl80211_attrs name,
const nlattr *data) {
scoped_ptr<Nl80211Attribute> attr;
switch (name) {
case NL80211_ATTR_DURATION:
attr.reset(new Nl80211AttributeDuration());
break;
// TODO(wdg): Add more attributes.
default:
attr.reset(new Nl80211AttributeGeneric(name));
break;
}
attr->InitFromNlAttr(data);
return attr.release();
}
// Duplicate attribute data, store in map indexed on |name|.
bool Nl80211Attribute::InitFromNlAttr(const nlattr *other) {
if (!other) {
LOG(ERROR) << "NULL data";
return false;
}
data_ = ByteString(reinterpret_cast<const unsigned char *>(other),
nla_total_size(nla_len(const_cast<nlattr *>(other))));
return true;
}
// Retrieves a pointer to the raw attribute data but not the header.
bool Nl80211Attribute::GetRawData(ByteString *output) const {
if (!output) {
LOG(ERROR) << "Null |output| parameter";
return false;
}
*output = data_;
return true;
}
string Nl80211Attribute::RawToString() const {
string output = " === RAW: ";
nlattr *data_nlattr = const_cast<nlattr *>(data());
uint16_t length = nla_len(data_nlattr);
StringAppendF(&output, "len=%u", length);
const uint8_t *const_data = reinterpret_cast<const uint8_t *>(data());
output.append(" DATA: ");
for (int i =0 ; i < length; ++i) {
StringAppendF(&output, "[%d]=%02x ", i, *(const_data)+i);
}
output.append(" ==== ");
return output;
}
// Nl80211U32Attribute::
const char Nl80211U32Attribute::kMyTypeString[] = "uint32_t";
const Nl80211Attribute::Type Nl80211U32Attribute::kType =
Nl80211Attribute::kTypeU32;
bool Nl80211U32Attribute::InitFromNlAttr(const nlattr *param) {
if (!param) {
LOG(ERROR) << "Null |param| parameter";
return false;
}
uint32_t data = nla_get_u32(const_cast<nlattr *>(param));
SetU32Value(data);
return Nl80211Attribute::InitFromNlAttr(param);
}
bool Nl80211U32Attribute::GetU32Value(uint32_t *output) const {
if (!output) {
LOG(ERROR) << "Null |output| parameter";
return false;
}
*output = value_;
return true;
}
bool Nl80211U32Attribute::SetU32Value(uint32_t new_value) {
value_ = new_value;
return true;
}
bool Nl80211U32Attribute::AsString(string *output) const {
if (!output) {
LOG(ERROR) << "Null |output| parameter";
return false;
}
uint32_t value;
if (!GetU32Value(&value))
return false;
*output = StringPrintf("%" PRIu32, value);
return true;
}
// Nl80211RawAttribute
const char Nl80211RawAttribute::kMyTypeString[] = "<raw>";
const Nl80211Attribute::Type Nl80211RawAttribute::kType =
Nl80211Attribute::kTypeRaw;
bool Nl80211RawAttribute::InitFromNlAttr(const nlattr *param) {
if (!param) {
LOG(ERROR) << "Null |param| parameter";
return false;
}
return Nl80211Attribute::InitFromNlAttr(param);
}
bool Nl80211RawAttribute::GetRawValue(const ByteString **output) const {
if (!output) {
LOG(ERROR) << "NULL |output|";
return false;
}
*output = &data_;
return true;
}
bool Nl80211RawAttribute::AsString(string *output) const {
if (!output) {
LOG(ERROR) << "Null |output| parameter";
return false;
}
const uint8_t *raw_data = reinterpret_cast<const uint8_t *>(data());
int total_bytes = nla_len(data());
*output = StringPrintf("%d bytes:", total_bytes);
for (int i = 0; i < total_bytes; ++i) {
StringAppendF(output, " 0x%02x", raw_data[i]);
}
return true;
}
// Specific Attributes.
const nl80211_attrs Nl80211AttributeDuration::kName = NL80211_ATTR_DURATION;
const char Nl80211AttributeDuration::kNameString[] = "NL80211_ATTR_DURATION";
Nl80211AttributeGeneric::Nl80211AttributeGeneric(nl80211_attrs name)
: Nl80211RawAttribute(name, "unused-string") {
StringAppendF(&name_string_, "<UNKNOWN ATTRIBUTE %d>", name);
}
const char *Nl80211AttributeGeneric::name_string() const {
return name_string_.c_str();
}
} // namespace shill