Beispiel #1
0
// public
bool IPAddress::inSubnetWithMask(const IPAddress& subnet, ByteRange mask)
    const {
  auto mkByteArray4 = [&]() -> ByteArray4 {
    ByteArray4 ba{{0}};
    std::memcpy(ba.data(), mask.begin(), std::min<size_t>(mask.size(), 4));
    return ba;
  };

  if (bitCount() == subnet.bitCount()) {
    if (isV4()) {
      return asV4().inSubnetWithMask(subnet.asV4(), mkByteArray4());
    } else {
      ByteArray16 ba{{0}};
      std::memcpy(ba.data(), mask.begin(), std::min<size_t>(mask.size(), 16));
      return asV6().inSubnetWithMask(subnet.asV6(), ba);
    }
  }

  // an IPv4 address can never belong in a IPv6 subnet unless the IPv6 is a 6to4
  // address and vice-versa
  if (isV6()) {
    const IPAddressV6& v6addr = asV6();
    const IPAddressV4& v4subnet = subnet.asV4();
    if (v6addr.is6To4()) {
      return v6addr.getIPv4For6To4().inSubnetWithMask(v4subnet, mkByteArray4());
    }
  } else if (subnet.isV6()) {
    const IPAddressV6& v6subnet = subnet.asV6();
    const IPAddressV4& v4addr = asV4();
    if (v6subnet.is6To4()) {
      return v4addr.inSubnetWithMask(v6subnet.getIPv4For6To4(), mkByteArray4());
    }
  }
  return false;
}
Beispiel #2
0
RecordInfo findRecord(ByteRange searchRange,
                      ByteRange wholeRange,
                      uint32_t fileId) {
  static const uint32_t magic = Header::kMagic;
  static const ByteRange magicRange(reinterpret_cast<const uint8_t*>(&magic),
                                    sizeof(magic));

  DCHECK_GE(searchRange.begin(), wholeRange.begin());
  DCHECK_LE(searchRange.end(), wholeRange.end());

  const uint8_t* start = searchRange.begin();
  const uint8_t* end = std::min(searchRange.end(),
                                wholeRange.end() - sizeof(Header));
  // end-1: the last place where a Header could start
  while (start < end) {
    auto p = ByteRange(start, end + sizeof(magic)).find(magicRange);
    if (p == ByteRange::npos) {
      break;
    }

    start += p;
    auto r = validateRecord(ByteRange(start, wholeRange.end()), fileId);
    if (!r.record.empty()) {
      return r;
    }

    // No repeated prefix in magic, so we can do better than start++
    start += sizeof(magic);
  }

  return {0, {}};
}
Beispiel #3
0
void MacAddress::setFromBinary(ByteRange value) {
  if (value.size() != SIZE) {
    throw invalid_argument(to<string>("MAC address must be 6 bytes "
                                      "long, got ", value.size()));
  }
  memcpy(bytes_ + 2, value.begin(), SIZE);
}
Beispiel #4
0
void RecordIOReader::Iterator::advanceToValid() {
  ByteRange record = findRecord(range_, fileId_).record;
  if (record.empty()) {
    recordAndPos_ = std::make_pair(ByteRange(), off_t(-1));
    range_.clear();  // at end
  } else {
    size_t skipped = record.begin() - range_.begin();
    DCHECK_GE(skipped, headerSize());
    skipped -= headerSize();
    range_.advance(skipped);
    recordAndPos_.first = record;
    recordAndPos_.second += skipped;
  }
}
Beispiel #5
0
RecordInfo validateRecord(ByteRange range, uint32_t fileId) {
  if (range.size() <= headerSize()) {  // records may not be empty
    return {0, {}};
  }
  const Header* header = reinterpret_cast<const Header*>(range.begin());
  range.advance(sizeof(Header));
  if (header->magic != Header::kMagic ||
      header->version != 0 ||
      header->hashFunction != 0 ||
      header->flags != 0 ||
      (fileId != 0 && header->fileId != fileId) ||
      header->dataLength > range.size()) {
    return {0, {}};
  }
  if (headerHash(*header) != header->headerHash) {
    return {0, {}};
  }
  range.reset(range.begin(), header->dataLength);
  if (dataHash(range) != header->dataHash) {
    return {0, {}};
  }
  return {header->fileId, range};
}
Beispiel #6
0
void Normalize::normalizeQueueGetConfigReplyV1() {
  Header *hdr = header();

  size_t length = hdr->length();
  if (length < sizeof(QueueGetConfigReply)) {
    markInputInvalid("QueueGetConfigReply is too short");
    return;
  }

  if (hdr->version() == OFP_VERSION_1) {
    // Convert port number to 32-bits -- only for OpenFlow 1.0.
    UInt8 *ptr = buf_.mutableData() + sizeof(Header);
    PortNumber port = PortNumber::fromV1(*Big16_cast(ptr));
    std::memcpy(ptr, &port, sizeof(port));
  }

  // Convert QueueV1 to Queue.
  ByteRange data = SafeByteRange(buf_.mutableData(), buf_.size(),
                                 sizeof(QueueGetConfigReply));
  deprecated::QueueV1Range queues{data};

  Validation context;
  if (!queues.validateInput(&context)) {
    markInputInvalid("QueueGetConfigReply has invalid queues");
    return;
  }

  QueueList newQueues;
  for (auto &queue : queues) {
    QueueBuilder newQueue{queue};
    newQueues.add(newQueue);
  }

  // When converting to the regular `Queue` structure, we may exceed the max
  // message size of 65535.
  if (newQueues.size() > 65535 - sizeof(QueueGetConfigReply)) {
    markInputTooBig("QueueGetConfigReply is too big");
    return;
  }

  buf_.replace(data.begin(), data.end(), newQueues.data(), newQueues.size());
}
Beispiel #7
0
void Normalize::normalizeQueueGetConfigReplyV2() {
  // Pad all queues to a multiple of 8. You can only get a queue whose size is
  // not a multiple of 8 if it contains an experimenter property with an
  // unusual length.

  Header *hdr = header();

  size_t length = hdr->length();
  if (length < sizeof(QueueGetConfigReply))
    return;

  ByteRange data = SafeByteRange(buf_.mutableData(), buf_.size(),
                                 sizeof(QueueGetConfigReply));

  size_t remaining = data.size();
  const UInt8 *ptr = data.data();

  ByteList newBuf;
  while (remaining > 16) {
    // Read 16-bit queue length from a potentially mis-aligned position.
    UInt16 queueLen = Big16_unaligned(ptr + 8);
    if (queueLen > remaining || queueLen < 16)
      return;
    // Copy queue header.
    newBuf.add(ptr, 16);

    // Iterate over properties and pad out the properties whose sizes are not
    // multiples of 8.
    const UInt8 *prop = ptr + 16;
    size_t propLeft = queueLen - 16;
    while (propLeft > 4) {
      UInt16 propSize = Big16_unaligned(prop + 2);
      if (propSize > propLeft || propSize < 4)
        return;
      newBuf.add(prop, propSize);
      if ((propSize % 8) != 0) {
        newBuf.addZeros(PadLength(propSize) - propSize);
      }
      prop += propSize;
      propLeft -= propSize;
    }

    if (propLeft != 0) {
      log_debug("normalizeQueueGetConfigReplyV2: propLeft != 0");
      return;
    }

    ptr += queueLen;
    assert(prop == ptr);

    remaining -= queueLen;
  }

  if (remaining != 0) {
    log_debug("normalizeQueueGetConfigReplyV2: remaining != 0");
    return;
  }

  // When padding the regular `Queue` structure, we may exceed the max
  // message size of 65535.
  if (newBuf.size() > 65535 - sizeof(QueueGetConfigReply)) {
    markInputTooBig("QueueGetConfigReply is too big");
    return;
  }

  buf_.replace(data.begin(), data.end(), newBuf.data(), newBuf.size());
}
Beispiel #8
0
bool are_identical(const ByteRange& lhs, const ByteRange& rhs)
{
    return lhs.begin() == rhs.begin() && lhs.end() == rhs.end();
}
Beispiel #9
0
bool are_equal(const ByteRange& lhs, const ByteRange& rhs)
{
    return lhs.size() == rhs.size() && !memcmp(lhs.begin(), rhs.begin(), rhs.size());
}