// 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; }
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, {}}; }
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); }
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; } }
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}; }
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()); }
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()); }
bool are_identical(const ByteRange& lhs, const ByteRange& rhs) { return lhs.begin() == rhs.begin() && lhs.end() == rhs.end(); }
bool are_equal(const ByteRange& lhs, const ByteRange& rhs) { return lhs.size() == rhs.size() && !memcmp(lhs.begin(), rhs.begin(), rhs.size()); }