Home | History | Annotate | Download | only in net
      1 //
      2 // Copyright (C) 2013 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/generic_netlink_message.h"
     18 
     19 #include <base/bind.h>
     20 #include <base/logging.h>
     21 #include <base/strings/stringprintf.h>
     22 
     23 #include "shill/net/netlink_attribute.h"
     24 #include "shill/net/netlink_packet.h"
     25 
     26 using base::Bind;
     27 using base::StringPrintf;
     28 
     29 namespace shill {
     30 
     31 ByteString GenericNetlinkMessage::EncodeHeader(uint32_t sequence_number) {
     32   // Build nlmsghdr.
     33   ByteString result(NetlinkMessage::EncodeHeader(sequence_number));
     34   if (result.GetLength() == 0) {
     35     LOG(ERROR) << "Couldn't encode message header.";
     36     return result;
     37   }
     38 
     39   // Build and append the genl message header.
     40   genlmsghdr genl_header;
     41   genl_header.cmd = command();
     42   genl_header.version = 1;
     43   genl_header.reserved = 0;
     44 
     45   ByteString genl_header_string(
     46       reinterpret_cast<unsigned char*>(&genl_header), sizeof(genl_header));
     47   size_t genlmsghdr_with_pad = NLMSG_ALIGN(sizeof(genl_header));
     48   genl_header_string.Resize(genlmsghdr_with_pad);  // Zero-fill.
     49 
     50   nlmsghdr* pheader = reinterpret_cast<nlmsghdr*>(result.GetData());
     51   pheader->nlmsg_len += genlmsghdr_with_pad;
     52   result.Append(genl_header_string);
     53   return result;
     54 }
     55 
     56 ByteString GenericNetlinkMessage::Encode(uint32_t sequence_number) {
     57   ByteString result(EncodeHeader(sequence_number));
     58   if (result.GetLength() == 0) {
     59     LOG(ERROR) << "Couldn't encode message header.";
     60     return result;
     61   }
     62 
     63   // Build and append attributes (padding is included by
     64   // AttributeList::Encode).
     65   ByteString attribute_string = attributes_->Encode();
     66 
     67   // Need to re-calculate |header| since |Append|, above, moves the data.
     68   nlmsghdr* pheader = reinterpret_cast<nlmsghdr*>(result.GetData());
     69   pheader->nlmsg_len += attribute_string.GetLength();
     70   result.Append(attribute_string);
     71 
     72   return result;
     73 }
     74 
     75 bool GenericNetlinkMessage::InitAndStripHeader(NetlinkPacket* packet) {
     76   if (!packet) {
     77     LOG(ERROR) << "NULL packet";
     78     return false;
     79   }
     80   if (!NetlinkMessage::InitAndStripHeader(packet)) {
     81     return false;
     82   }
     83 
     84   genlmsghdr gnlh;
     85   if (!packet->ConsumeData(sizeof(gnlh), &gnlh)) {
     86     return false;
     87   }
     88 
     89   if (command_ != gnlh.cmd) {
     90     LOG(WARNING) << "This object thinks it's a " << command_
     91                  << " but the message thinks it's a " << gnlh.cmd;
     92   }
     93 
     94   return true;
     95 }
     96 
     97 void GenericNetlinkMessage::Print(int header_log_level,
     98                                   int detail_log_level) const {
     99   VLOG(header_log_level) << StringPrintf("Message %s (%d)",
    100                                          command_string(),
    101                                          command());
    102   attributes_->Print(detail_log_level, 1);
    103 }
    104 
    105 // Control Message
    106 
    107 const uint16_t ControlNetlinkMessage::kMessageType = GENL_ID_CTRL;
    108 
    109 bool ControlNetlinkMessage::InitFromPacket(
    110     NetlinkPacket* packet, NetlinkMessage::MessageContext context) {
    111   if (!packet) {
    112     LOG(ERROR) << "Null |packet| parameter";
    113     return false;
    114   }
    115 
    116   if (!InitAndStripHeader(packet)) {
    117     return false;
    118   }
    119 
    120   return packet->ConsumeAttributes(
    121       Bind(&NetlinkAttribute::NewControlAttributeFromId), attributes_);
    122 }
    123 
    124 // Specific Control types.
    125 
    126 const uint8_t NewFamilyMessage::kCommand = CTRL_CMD_NEWFAMILY;
    127 const char NewFamilyMessage::kCommandString[] = "CTRL_CMD_NEWFAMILY";
    128 
    129 const uint8_t GetFamilyMessage::kCommand = CTRL_CMD_GETFAMILY;
    130 const char GetFamilyMessage::kCommandString[] = "CTRL_CMD_GETFAMILY";
    131 
    132 GetFamilyMessage::GetFamilyMessage()
    133     : ControlNetlinkMessage(kCommand, kCommandString) {
    134   attributes()->CreateStringAttribute(CTRL_ATTR_FAMILY_NAME,
    135                                       "CTRL_ATTR_FAMILY_NAME");
    136 }
    137 
    138 // static
    139 NetlinkMessage* ControlNetlinkMessage::CreateMessage(
    140     const NetlinkPacket& packet) {
    141   genlmsghdr header;
    142   if (!packet.GetGenlMsgHdr(&header)) {
    143     LOG(ERROR) << "Could not read genl header.";
    144     return nullptr;
    145   }
    146 
    147   switch (header.cmd) {
    148     case NewFamilyMessage::kCommand:
    149       return new NewFamilyMessage();
    150     case GetFamilyMessage::kCommand:
    151       return new GetFamilyMessage();
    152     default:
    153       LOG(WARNING) << "Unknown/unhandled netlink control message "
    154                    << header.cmd;
    155       return new UnknownControlMessage(header.cmd);
    156       break;
    157   }
    158   return nullptr;
    159 }
    160 
    161 }  // namespace shill.
    162