C++程序  |  259行  |  7.72 KB

//
// Copyright (C) 2012 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

#ifndef SHILL_NET_RTNL_MESSAGE_H_
#define SHILL_NET_RTNL_MESSAGE_H_

#include <unordered_map>
#include <vector>

#include <base/macros.h>
#include <base/stl_util.h>

#include "shill/net/byte_string.h"
#include "shill/net/ip_address.h"
#include "shill/net/shill_export.h"

struct rtattr;

namespace shill {

struct RTNLHeader;

class SHILL_EXPORT RTNLMessage {
 public:
  enum Type {
    kTypeUnknown,
    kTypeLink,
    kTypeAddress,
    kTypeRoute,
    kTypeRdnss,
    kTypeDnssl,
    kTypeNeighbor,
  };

  enum Mode {
    kModeUnknown,
    kModeGet,
    kModeAdd,
    kModeDelete,
    kModeQuery
  };

  struct LinkStatus {
    LinkStatus()
        : type(0),
          flags(0),
          change(0) {}
    LinkStatus(unsigned int in_type,
               unsigned int in_flags,
               unsigned int in_change)
        : type(in_type),
          flags(in_flags),
          change(in_change) {}
    unsigned int type;
    unsigned int flags;
    unsigned int change;
  };

  struct AddressStatus {
    AddressStatus()
        : prefix_len(0),
          flags(0),
          scope(0) {}
    AddressStatus(unsigned char prefix_len_in,
                  unsigned char flags_in,
                  unsigned char scope_in)
        : prefix_len(prefix_len_in),
          flags(flags_in),
          scope(scope_in) {}
    unsigned char prefix_len;
    unsigned char flags;
    unsigned char scope;
  };

  struct RouteStatus {
    RouteStatus()
        : dst_prefix(0),
          src_prefix(0),
          table(0),
          protocol(0),
          scope(0),
          type(0),
          flags(0) {}
    RouteStatus(unsigned char dst_prefix_in,
                unsigned char src_prefix_in,
                unsigned char table_in,
                unsigned char protocol_in,
                unsigned char scope_in,
                unsigned char type_in,
                unsigned char flags_in)
        : dst_prefix(dst_prefix_in),
          src_prefix(src_prefix_in),
          table(table_in),
          protocol(protocol_in),
          scope(scope_in),
          type(type_in),
          flags(flags_in) {}
    unsigned char dst_prefix;
    unsigned char src_prefix;
    unsigned char table;
    unsigned char protocol;
    unsigned char scope;
    unsigned char type;
    unsigned char flags;
  };

  struct NeighborStatus {
    NeighborStatus()
        : state(0),
          flags(0),
          type(0) {}
    NeighborStatus(uint16_t state_in,
                   uint8_t flags_in,
                   uint8_t type_in)
        : state(state_in),
          flags(flags_in),
          type(type_in) {}
    uint16_t state;
    uint8_t flags;
    uint8_t type;
  };

  struct RdnssOption {
    RdnssOption()
        : lifetime(0) {}
    RdnssOption(uint32_t lifetime_in,
                std::vector<IPAddress> addresses_in)
        : lifetime(lifetime_in),
          addresses(addresses_in) {}
    uint32_t lifetime;
    std::vector<IPAddress> addresses;
  };

  // Empty constructor
  RTNLMessage();
  // Build an RTNL message from arguments
  RTNLMessage(Type type,
              Mode mode,
              unsigned int flags,
              uint32_t seq,
              uint32_t pid,
              int interface_index,
              IPAddress::Family family);

  // Parse an RTNL message.  Returns true on success.
  bool Decode(const ByteString& data);
  // Encode an RTNL message.  Returns empty ByteString on failure.
  ByteString Encode() const;
  // Reset all fields.
  void Reset();

  // Getters and setters
  Type type() const { return type_; }
  Mode mode() const { return mode_; }
  uint16_t flags() const { return flags_; }
  uint32_t seq() const { return seq_; }
  void set_seq(uint32_t seq) { seq_ = seq; }
  uint32_t pid() const { return pid_; }
  uint32_t interface_index() const { return interface_index_; }
  IPAddress::Family family() const { return family_; }

  const LinkStatus& link_status() const { return link_status_; }
  void set_link_status(const LinkStatus& link_status) {
    link_status_ = link_status;
  }
  const AddressStatus& address_status() const { return address_status_; }
  void set_address_status(const AddressStatus& address_status) {
    address_status_ = address_status;
  }
  const RouteStatus& route_status() const { return route_status_; }
  void set_route_status(const RouteStatus& route_status) {
    route_status_ = route_status;
  }
  const RdnssOption& rdnss_option() const { return rdnss_option_; }
  void set_rdnss_option(const RdnssOption& rdnss_option) {
    rdnss_option_ = rdnss_option;
  }
  const NeighborStatus& neighbor_status() const { return neighbor_status_; }
  void set_neighbor_status(const NeighborStatus& neighbor_status) {
    neighbor_status_ = neighbor_status;
  }
  // GLint hates "unsigned short", and I don't blame it, but that's the
  // type that's used in the system headers.  Use uint16_t instead and hope
  // that the conversion never ends up truncating on some strange platform.
  bool HasAttribute(uint16_t attr) const {
    return ContainsKey(attributes_, attr);
  }
  const ByteString GetAttribute(uint16_t attr) const {
    return HasAttribute(attr) ?
        attributes_.find(attr)->second : ByteString(0);
  }
  void SetAttribute(uint16_t attr, const ByteString& val) {
    attributes_[attr] = val;
  }

 private:
  SHILL_PRIVATE bool DecodeInternal(const ByteString& msg);
  SHILL_PRIVATE bool DecodeLink(const RTNLHeader* hdr,
                                Mode mode,
                                rtattr** attr_data,
                                int* attr_length);
  SHILL_PRIVATE bool DecodeAddress(const RTNLHeader* hdr,
                                   Mode mode,
                                   rtattr** attr_data,
                                   int* attr_length);
  SHILL_PRIVATE bool DecodeRoute(const RTNLHeader* hdr,
                                 Mode mode,
                                 rtattr** attr_data,
                                 int* attr_length);
  SHILL_PRIVATE bool DecodeNdUserOption(const RTNLHeader* hdr,
                                        Mode mode,
                                        rtattr** attr_data,
                                        int* attr_length);
  SHILL_PRIVATE bool ParseRdnssOption(const uint8_t* data,
                                      int length,
                                      uint32_t lifetime);
  SHILL_PRIVATE bool DecodeNeighbor(const RTNLHeader* hdr,
                                    Mode mode,
                                    rtattr** attr_data,
                                    int* attr_length);
  SHILL_PRIVATE bool EncodeLink(RTNLHeader* hdr) const;
  SHILL_PRIVATE bool EncodeAddress(RTNLHeader* hdr) const;
  SHILL_PRIVATE bool EncodeRoute(RTNLHeader* hdr) const;
  SHILL_PRIVATE bool EncodeNeighbor(RTNLHeader* hdr) const;

  Type type_;
  Mode mode_;
  uint16_t flags_;
  uint32_t seq_;
  uint32_t pid_;
  unsigned int interface_index_;
  IPAddress::Family family_;
  LinkStatus link_status_;
  AddressStatus address_status_;
  RouteStatus route_status_;
  NeighborStatus neighbor_status_;
  RdnssOption rdnss_option_;
  std::unordered_map<uint16_t, ByteString> attributes_;

  DISALLOW_COPY_AND_ASSIGN(RTNLMessage);
};

}  // namespace shill

#endif  // SHILL_NET_RTNL_MESSAGE_H_