void RafImage::readMetadata() { #ifdef DEBUG std::cerr << "Reading RAF file " << io_->path() << "\n"; #endif if (io_->open() != 0) throw Error(9, io_->path(), strError()); IoCloser closer(*io_); // Ensure that this is the correct image type if (!isRafType(*io_, false)) { if (io_->error() || io_->eof()) throw Error(14); throw Error(3, "RAF"); } byte const* pData = io_->mmap(); long size = io_->size(); if (size < 88 + 4) throw Error(14); // includes the test for -1 uint32_t const start = getULong(pData + 84, bigEndian) + 12; if (static_cast<uint32_t>(size) < start) throw Error(14); clearMetadata(); ByteOrder bo = TiffParser::decode(exifData_, iptcData_, xmpData_, pData + start, size - start); exifData_["Exif.Image2.JPEGInterchangeFormat"] = getULong(pData + 84, bigEndian); exifData_["Exif.Image2.JPEGInterchangeFormatLength"] = getULong(pData + 88, bigEndian); setByteOrder(bo); } // RafImage::readMetadata
void MrwImage::readMetadata() { #ifdef DEBUG std::cerr << "Reading MRW file " << io_->path() << "\n"; #endif if (io_->open() != 0) { throw Error(9, io_->path(), strError()); } IoCloser closer(*io_); // Ensure that this is the correct image type if (!isMrwType(*io_, false)) { if (io_->error() || io_->eof()) throw Error(14); throw Error(3, "MRW"); } clearMetadata(); // Find the TTW block and read it into a buffer uint32_t const len = 8; byte tmp[len]; io_->read(tmp, len); uint32_t pos = len; uint32_t const end = getULong(tmp + 4, bigEndian); pos += len; if (pos > end) throw Error(14); io_->read(tmp, len); if (io_->error() || io_->eof()) throw Error(14); while (memcmp(tmp + 1, "TTW", 3) != 0) { uint32_t const siz = getULong(tmp + 4, bigEndian); pos += siz; if (pos > end) throw Error(14); io_->seek(siz, BasicIo::cur); if (io_->error() || io_->eof()) throw Error(14); pos += len; if (pos > end) throw Error(14); io_->read(tmp, len); if (io_->error() || io_->eof()) throw Error(14); } DataBuf buf(getULong(tmp + 4, bigEndian)); io_->read(buf.pData_, buf.size_); if (io_->error() || io_->eof()) throw Error(14); ByteOrder bo = TiffParser::decode(exifData_, iptcData_, xmpData_, buf.pData_, buf.size_); setByteOrder(bo); } // MrwImage::readMetadata
void CiffDirectory::readDirectory(const byte* buf, uint32_t len, uint32_t start, ByteOrder byteOrder, int32_t /*shift*/) { uint32_t dataSize = getULong(buf + len - 4, byteOrder); uint32_t o = start + dataSize; if (o + 2 > len) throw Error(33); uint16_t count = getUShort(buf + o, byteOrder); o += 2; for (uint16_t i = 0; i < count; ++i) { if (o + 10 > len) throw Error(33); uint16_t tag = getUShort(buf + o, byteOrder); CiffComponent* p = 0; switch (CiffComponent::typeId(tag)) { case directory: p = new CiffDirectory; break; default: p = new CiffEntry; break; } p->setDir(this->tag()); RawMetadata::AutoPtr m(p); m->read(buf, len, o, byteOrder); add(m); o += 10; } } // CiffDirectory::readDirectory
void CiffHeader::read(const byte* buf, uint32_t len, uint32_t start, ByteOrder byteOrder, int32_t /*shift*/) { if (len < 14) throw Error(33); if (buf[0] == 0x49 && buf[1] == 0x49) { byteOrder_ = littleEndian; } else if (buf[0] == 0x4d && buf[1] == 0x4d) { byteOrder_ = bigEndian; } else { throw Error(33); } offset_ = getULong(buf + 2, byteOrder_); if (std::memcmp(buf + 6, signature_, 8) != 0) { throw Error(33); } rootDirectory_ = new CiffDirectory; rootDirectory_->readDirectory(buf + offset_, len - offset_, 0, byteOrder_); } // CiffHeader::read
// Todo: Generalised from JpegBase::locateIptcData without really understanding // the format (in particular the header). So it remains to be confirmed // if this also makes sense for psTag != Photoshop::iptc int Photoshop::locateIrb(const byte* pPsData, long sizePsData, uint16_t psTag, const byte** record, uint32_t *const sizeHdr, uint32_t *const sizeData) { assert(record); assert(sizeHdr); assert(sizeData); // Used for error checking long position = 0; // Data should follow Photoshop format, if not exit while ( position <= sizePsData - 14 && memcmp(pPsData + position, Photoshop::bimId_, 4) == 0) { const byte *hrd = pPsData + position; position += 4; uint16_t type = getUShort(pPsData + position, bigEndian); position += 2; // Pascal string is padded to have an even size (including size byte) byte psSize = pPsData[position] + 1; psSize += (psSize & 1); position += psSize; if (position + 4 > sizePsData) { #ifndef SUPPRESS_WARNINGS std::cerr << "Error: " << "Invalid Photoshop IRB\n"; #endif return -2; } uint32_t dataSize = getULong(pPsData + position, bigEndian); position += 4; if (dataSize > static_cast<uint32_t>(sizePsData - position)) { #ifndef SUPPRESS_WARNINGS std::cerr << "Error: " << "Invalid Photoshop IRB data size " << dataSize << "\n"; #endif return -2; } #ifndef DEBUG if ( (dataSize & 1) && position + dataSize == static_cast<uint32_t>(sizePsData)) { std::cerr << "Warning: " << "Photoshop IRB data is not padded to even size\n"; } #endif if (type == psTag) { *sizeData = dataSize; *sizeHdr = psSize + 10; *record = hrd; return 0; } // Data size is also padded to be even position += dataSize + (dataSize & 1); } return 3; } // Photoshop::locateIrb
unsigned long SQLiteQuery::getULong(const std::string &name) { int col = m_aCols[name]; if (col >= 0) return getULong(col); return 0; }
const Reader &BasicReader::readUnsignedLong (unsigned long& val ) { Glib::ustring buf = readWord(); unsigned long ival; if (getULong(buf, &ival)) val = ival; return *this; }
bool Cr2Header::read(const byte* pData, uint32_t size) { if (size < 16) return false; if (pData[0] == 0x49 && pData[1] == 0x49) { setByteOrder(littleEndian); } else if (pData[0] == 0x4d && pData[1] == 0x4d) { setByteOrder(bigEndian); } else { return false; } if (tag() != getUShort(pData + 2, byteOrder())) return false; setOffset(getULong(pData + 4, byteOrder())); if (0 != memcmp(pData + 8, cr2sig_, 4)) return false; offset2_ = getULong(pData + 12, byteOrder()); return true; } // Cr2Header::read
int Ifd::readSubIfd( Ifd& dest, const char* buf, ByteOrder byteOrder, uint16 tag ) const { int rc = 0; const_iterator pos = findTag(tag); if (pos != entries_.end()) { uint32 offset = getULong(pos->data(), byteOrder); rc = dest.read(buf + offset, byteOrder, offset); } return rc; } // Ifd::readSubIfd
int TiffHeader::read(const byte* buf) { if (buf[0] == 0x49 && buf[1] == 0x49) { byteOrder_ = littleEndian; } else if (buf[0] == 0x4d && buf[1] == 0x4d) { byteOrder_ = bigEndian; } else { return 1; } tag_ = getUShort(buf+2, byteOrder_); offset_ = getULong(buf+4, byteOrder_); return 0; }
void CiffComponent::read(const byte* buf, uint32_t len, uint32_t start, ByteOrder byteOrder, int32_t /*shift*/) { if (len < 10) throw Error(33); tag_ = getUShort(buf + start, byteOrder); switch (dataLocation()) { case valueData: size_ = getULong(buf + start + 2, byteOrder); offset_ = getULong(buf + start + 6, byteOrder); break; case directoryData: size_ = 8; offset_ = start + 2; break; case invalidDataLocId: case lastDataLocId: // empty break; } pData_ = buf + offset_; } // CiffComponent::read
bool FujiMnHeader::read(const byte* pData, uint32_t size, ByteOrder /*byteOrder*/) { if (!pData || size < sizeOfSignature()) return false; header_.alloc(sizeOfSignature()); std::memcpy(header_.pData_, pData, header_.size_); // Read offset to the IFD relative to the start of the makernote // from the header. Note that we ignore the byteOrder argument start_ = getULong(header_.pData_ + 8, byteOrder_); if ( static_cast<uint32_t>(header_.size_) < sizeOfSignature() || 0 != memcmp(header_.pData_, signature_, 8)) { return false; } return true; } // FujiMnHeader::read
bool TiffHeade2::read(const byte* pData, uint32_t size) { if (size < 8) return false; if (pData[0] == 0x49 && pData[1] == 0x49) { byteOrder_ = littleEndian; } else if (pData[0] == 0x4d && pData[1] == 0x4d) { byteOrder_ = bigEndian; } else { return false; } if (tag_ != getUShort(pData + 2, byteOrder_)) return false; offset_ = getULong(pData + 4, byteOrder_); return true; } // TiffHeade2::read
bool OrfHeader::read(const byte* pData, uint32_t size) { if (size < 8) return false; if (pData[0] == 0x49 && pData[1] == 0x49) { setByteOrder(littleEndian); } else if (pData[0] == 0x4d && pData[1] == 0x4d) { setByteOrder(bigEndian); } else { return false; } if (tag() != getUShort(pData + 2, byteOrder())) return false; setOffset(getULong(pData + 4, byteOrder())); if (offset() != 0x00000008) return false; return true; } // OrfHeader::read
// Todo: Generalised from JpegBase::locateIptcData without really understanding // the format (in particular the header). So it remains to be confirmed // if this also makes sense for psTag != Photoshop::iptc int Photoshop::locateIrb(const byte* pPsData, long sizePsData, uint16_t psTag, const byte** record, uint32_t *const sizeHdr, uint32_t *const sizeData) { assert(record); assert(sizeHdr); assert(sizeData); // Used for error checking long position = 0; // Data should follow Photoshop format, if not exit while ( position <= sizePsData - 14 && memcmp(pPsData + position, Photoshop::bimId_, 4) == 0) { const byte *hrd = pPsData + position; position += 4; uint16_t type = getUShort(pPsData + position, bigEndian); position += 2; // Pascal string is padded to have an even size (including size byte) byte psSize = pPsData[position] + 1; psSize += (psSize & 1); position += psSize; if (position >= sizePsData) return -2; // Data is also padded to be even uint32_t dataSize = getULong(pPsData + position, bigEndian); position += 4; if (dataSize > static_cast<uint32_t>(sizePsData - position)) return -2; if (type == psTag) { *sizeData = dataSize; *sizeHdr = psSize + 10; *record = hrd; return 0; } position += dataSize + (dataSize & 1); } return 3; } // Photoshop::locateIrb
void RafImage::readMetadata() { #ifdef DEBUG std::cerr << "Reading RAF file " << io_->path() << "\n"; #endif if (io_->open() != 0) throw Error(9, io_->path(), strError()); IoCloser closer(*io_); // Ensure that this is the correct image type if (!isRafType(*io_, false)) { if (io_->error() || io_->eof()) throw Error(14); throw Error(3, "RAF"); } byte const* pData = io_->mmap(); long size = io_->size(); if (size < 84 + 4) throw Error(14); // includes the test for -1 uint32_t const start = getULong(pData + 84, bigEndian) + 12; if (static_cast<uint32_t>(size) < start) throw Error(14); clearMetadata(); TiffParser::decode(this, pData + start, size - start, TiffCreator::create, TiffDecoder::findDecoder); } // RafImage::readMetadata
bool OrfHeader::read(const byte* pData, uint32_t size) { if (size < 8) return false; if (pData[0] == 0x49 && pData[1] == 0x49) { setByteOrder(littleEndian); } else if (pData[0] == 0x4d && pData[1] == 0x4d) { setByteOrder(bigEndian); } else { return false; } uint16_t sig = getUShort(pData + 2, byteOrder()); if (tag() != sig && 0x5352 != sig) return false; // #658: Added 0x5352 for SP-560UZ sig_ = sig; setOffset(getULong(pData + 4, byteOrder())); if (offset() != 0x00000008) return false; return true; } // OrfHeader::read
void PsdImage::doWriteMetadata(BasicIo& outIo) { if (!io_->isopen()) throw Error(20); if (!outIo.isopen()) throw Error(21); #ifdef DEBUG std::cout << "Exiv2::PsdImage::doWriteMetadata: Writing PSD file " << io_->path() << "\n"; std::cout << "Exiv2::PsdImage::doWriteMetadata: tmp file created " << outIo.path() << "\n"; #endif // Ensure that this is the correct image type if (!isPsdType(*io_, true)) { if (io_->error() || io_->eof()) throw Error(20); throw Error(22); } io_->seek(0, BasicIo::beg); // rewind DataBuf lbuf(4096); byte buf[8]; // Get Photoshop header from original file byte psd_head[26]; if (io_->read(psd_head, 26) != 26) throw Error(3, "Photoshop"); // Write Photoshop header data out to new PSD file if (outIo.write(psd_head, 26) != 26) throw Error(21); // Read colorDataLength from original PSD if (io_->read(buf, 4) != 4) throw Error(3, "Photoshop"); uint32_t colorDataLength = getULong(buf, bigEndian); // Write colorDataLength ul2Data(buf, colorDataLength, bigEndian); if (outIo.write(buf, 4) != 4) throw Error(21); #ifdef DEBUG std::cerr << std::dec << "colorDataLength: " << colorDataLength << "\n"; #endif // Copy colorData uint32_t readTotal = 0; long toRead = 0; while (readTotal < colorDataLength) { toRead = static_cast<long>(colorDataLength - readTotal) < lbuf.size_ ? colorDataLength - readTotal : lbuf.size_; if (io_->read(lbuf.pData_, toRead) != toRead) throw Error(3, "Photoshop"); readTotal += toRead; if (outIo.write(lbuf.pData_, toRead) != toRead) throw Error(21); } if (outIo.error()) throw Error(21); uint32_t resLenOffset = io_->tell(); // remember for later update // Read length of all resource blocks from original PSD if (io_->read(buf, 4) != 4) throw Error(3, "Photoshop"); uint32_t oldResLength = getULong(buf, bigEndian); uint32_t newResLength = 0; // Write oldResLength (will be updated later) ul2Data(buf, oldResLength, bigEndian); if (outIo.write(buf, 4) != 4) throw Error(21); #ifdef DEBUG std::cerr << std::dec << "oldResLength: " << oldResLength << "\n"; #endif // Iterate over original resource blocks. // Replace or insert IPTC, EXIF and XMP // Original resource blocks assumed to be sorted ASC bool iptcDone = false; bool exifDone = false; bool xmpDone = false; while (oldResLength > 0) { if (io_->read(buf, 8) != 8) throw Error(3, "Photoshop"); // read resource type and ID uint32_t resourceType = getULong(buf, bigEndian); if (resourceType != kPhotoshopResourceType) { break; // bad resource type } uint16_t resourceId = getUShort(buf + 4, bigEndian); uint32_t resourceNameLength = buf[6]; uint32_t adjResourceNameLen = resourceNameLength & ~1; unsigned char resourceNameFirstChar = buf[7]; // read rest of resource name, plus any padding DataBuf resName(256); if ( io_->read(resName.pData_, adjResourceNameLen) != static_cast<long>(adjResourceNameLen)) throw Error(3, "Photoshop"); // read resource size (actual length w/o padding!) if (io_->read(buf, 4) != 4) throw Error(3, "Photoshop"); uint32_t resourceSize = getULong(buf, bigEndian); uint32_t curOffset = io_->tell(); // Write IPTC_NAA resource block if ( resourceId == kPhotoshopResourceID_IPTC_NAA || (resourceId > kPhotoshopResourceID_IPTC_NAA && iptcDone == false)) { newResLength += writeIptcData(iptcData_, outIo); resourceSize = (resourceSize + 1) & ~1; // adjust for padding iptcDone = true; } // Write ExifInfo resource block else if ( resourceId == kPhotoshopResourceID_ExifInfo || (resourceId > kPhotoshopResourceID_ExifInfo && exifDone == false)) { newResLength += writeExifData(exifData_, outIo); resourceSize = (resourceSize + 1) & ~1; // adjust for padding exifDone = true; } // Write XMPpacket resource block else if ( resourceId == kPhotoshopResourceID_XMPPacket || (resourceId > kPhotoshopResourceID_XMPPacket && xmpDone == false)) { newResLength += writeXmpData(xmpData_, outIo); resourceSize = (resourceSize + 1) & ~1; // adjust for padding xmpDone = true; } // Copy all other resource blocks if ( resourceId != kPhotoshopResourceID_IPTC_NAA && resourceId != kPhotoshopResourceID_ExifInfo && resourceId != kPhotoshopResourceID_XMPPacket) { #ifdef DEBUG std::cerr << std::hex << "copy : resourceId: " << resourceId << "\n"; std::cerr << std::dec; #endif // Copy resource block to new PSD file ul2Data(buf, kPhotoshopResourceType, bigEndian); if (outIo.write(buf, 4) != 4) throw Error(21); us2Data(buf, resourceId, bigEndian); if (outIo.write(buf, 2) != 2) throw Error(21); // Write resource name as Pascal string buf[0] = resourceNameLength & 0x000f; if (outIo.write(buf, 1) != 1) throw Error(21); buf[0] = resourceNameFirstChar; if (outIo.write(buf, 1) != 1) throw Error(21); if ( outIo.write(resName.pData_, adjResourceNameLen) != static_cast<long>(adjResourceNameLen)) throw Error(21); ul2Data(buf, resourceSize, bigEndian); if (outIo.write(buf, 4) != 4) throw Error(21); readTotal = 0; toRead = 0; resourceSize = (resourceSize + 1) & ~1; // pad to even while (readTotal < resourceSize) { toRead = static_cast<long>(resourceSize - readTotal) < lbuf.size_ ? resourceSize - readTotal : lbuf.size_; if (io_->read(lbuf.pData_, toRead) != toRead) { throw Error(3, "Photoshop"); } readTotal += toRead; if (outIo.write(lbuf.pData_, toRead) != toRead) throw Error(21); } if (outIo.error()) throw Error(21); newResLength += resourceSize + adjResourceNameLen + 12; } io_->seek(curOffset + resourceSize, BasicIo::beg); oldResLength -= (12 + adjResourceNameLen + resourceSize); } // Append IPTC_NAA resource block, if not yet written if (iptcDone == false) { newResLength += writeIptcData(iptcData_, outIo); iptcDone = true; } // Append ExifInfo resource block, if not yet written if (exifDone == false) { newResLength += writeExifData(exifData_, outIo); exifDone = true; } // Append XmpPacket resource block, if not yet written if (xmpDone == false) { newResLength += writeXmpData(xmpData_, outIo); xmpDone = true; } // Copy remaining data long readSize = 0; while ((readSize=io_->read(lbuf.pData_, lbuf.size_))) { if (outIo.write(lbuf.pData_, readSize) != readSize) throw Error(21); } if (outIo.error()) throw Error(21); // Update length of resources #ifdef DEBUG std::cerr << "newResLength: " << newResLength << "\n"; #endif outIo.seek(resLenOffset, BasicIo::beg); ul2Data(buf, newResLength, bigEndian); if (outIo.write(buf, 4) != 4) throw Error(21); } // PsdImage::doWriteMetadata
// Dump integer attributes of an object void dump_integers(sqlite3* db, long long oid) { int rv; unsigned long count; sqlite3_stmt* sqlcnt = NULL; sqlite3_stmt* sqlid = NULL; std::string commandcnt = "select count(id) from attribute_integer where object_id=?;"; std::string commandid = "select id from attribute_integer where object_id=?;"; rv = sqlite3_prepare_v2(db, commandcnt.c_str(), -1, &sqlcnt, NULL); if (rv != SQLITE_OK) { fprintf(stderr, "can't count the object table: %d(%s)\n", rv, sqlite3_errmsg(db)); sqlite3_finalize(sqlcnt); return; } rv = sqlite3_bind_int64(sqlcnt, 1, oid); if (rv != SQLITE_OK) { fprintf(stderr, "can't bind the object id: %d(%s)\n", rv, sqlite3_errmsg(db)); sqlite3_finalize(sqlcnt); return; } while ((rv = sqlite3_step(sqlcnt)) == SQLITE_BUSY) { sched_yield(); } if (rv != SQLITE_ROW) { fprintf(stderr, "can't count the object table: %d(%s)\n", rv, sqlite3_errmsg(db)); sqlite3_finalize(sqlcnt); return; } count = sqlite3_column_int(sqlcnt, 0); sqlite3_finalize(sqlcnt); if (count == 0) return; printf("%lu integer attributes for object %lld\n", count, oid); rv = sqlite3_prepare_v2(db, commandid.c_str(), -1, &sqlid, NULL); if (rv != SQLITE_OK) { fprintf(stderr, "can't count the object table: %d(%s)\n", rv, sqlite3_errmsg(db)); sqlite3_finalize(sqlid); return; } rv = sqlite3_bind_int64(sqlid, 1, oid); if (rv != SQLITE_OK) { fprintf(stderr, "can't bind the object id: %d(%s)\n", rv, sqlite3_errmsg(db)); sqlite3_finalize(sqlid); return; } while (count-- > 0) { while ((rv = sqlite3_step(sqlid)) == SQLITE_BUSY) { sched_yield(); } if (rv != SQLITE_ROW) { if (rv != SQLITE_DONE) { fprintf(stderr, "can't get next object id: %d(%s)\n", rv, sqlite3_errmsg(db)); } sqlite3_finalize(sqlid); return; } long long id = sqlite3_column_int64(sqlid, 0); uint64_t type; uint64_t value; if (!getULong(db, oid, id, type, value)) { return; } dumpULong(type); if ((uint64_t)((uint32_t)type) != type) { printf("overflow attribute type\n"); } else { dumpCKA((unsigned long) type, 48); printf("\n"); } dumpULong(value); dumpCKx(type, value, 48); printf("\n"); } }
unsigned long SQLiteQuery::getULong() { return getULong(m_thisColumn++); }
/* Determine what, if any, forward and reverse updates need to be * performed, and carry them through. */ int ddns_updates(struct packet *packet, struct lease *lease, struct lease *old, struct iasubopt *lease6, struct iasubopt *old6, struct option_state *options) { unsigned long ddns_ttl = DEFAULT_DDNS_TTL; struct data_string ddns_hostname; struct data_string ddns_domainname; struct data_string old_ddns_fwd_name; struct data_string ddns_fwd_name; //struct data_string ddns_rev_name; struct data_string ddns_dhcid; struct binding_scope **scope = NULL; //struct iaddr addr; struct data_string d1; struct option_cache *oc; int s1, s2; int result = 0; isc_result_t rcode1 = ISC_R_SUCCESS; int server_updates_a = 1; //int server_updates_ptr = 1; struct buffer *bp = (struct buffer *)0; int ignorep = 0, client_ignorep = 0; int rev_name_len; int i; dhcp_ddns_cb_t *ddns_cb; int do_remove = 0; if (ddns_update_style != 2) return 0; /* * sigh, I want to cancel any previous udpates before we do anything * else but this means we need to deal with the lease vs lease6 * question twice. * If there is a ddns request already outstanding cancel it. */ if (lease != NULL) { if ((old != NULL) && (old->ddns_cb != NULL)) { ddns_cancel(old->ddns_cb); old->ddns_cb = NULL; } } else if (lease6 != NULL) { if ((old6 != NULL) && (old6->ddns_cb != NULL)) { ddns_cancel(old->ddns_cb); old6->ddns_cb = NULL; } } else { log_fatal("Impossible condition at %s:%d.", MDL); /* Silence compiler warnings. */ result = 0; return(0); } /* allocate our control block */ ddns_cb = ddns_cb_alloc(MDL); if (ddns_cb == NULL) { return(0); } /* assume that we shall update both the A and ptr records */ ddns_cb->flags = DDNS_UPDATE_ADDR | DDNS_UPDATE_PTR; if (lease != NULL) { scope = &(lease->scope); ddns_cb->address = lease->ip_addr; } else if (lease6 != NULL) { scope = &(lease6->scope); memcpy(ddns_cb->address.iabuf, lease6->addr.s6_addr, 16); ddns_cb->address.len = 16; } memset (&d1, 0, sizeof(d1)); memset (&ddns_hostname, 0, sizeof (ddns_hostname)); memset (&ddns_domainname, 0, sizeof (ddns_domainname)); memset (&old_ddns_fwd_name, 0, sizeof (ddns_fwd_name)); memset (&ddns_fwd_name, 0, sizeof (ddns_fwd_name)); //memset (&ddns_rev_name, 0, sizeof (ddns_rev_name)); memset (&ddns_dhcid, 0, sizeof (ddns_dhcid)); /* If we are allowed to accept the client's update of its own A record, see if the client wants to update its own A record. */ if (!(oc = lookup_option(&server_universe, options, SV_CLIENT_UPDATES)) || evaluate_boolean_option_cache(&client_ignorep, packet, lease, NULL, packet->options, options, scope, oc, MDL)) { /* If there's no fqdn.no-client-update or if it's nonzero, don't try to use the client-supplied XXX */ if (!(oc = lookup_option (&fqdn_universe, packet -> options, FQDN_SERVER_UPDATE)) || evaluate_boolean_option_cache(&ignorep, packet, lease, NULL, packet->options, options, scope, oc, MDL)) goto noclient; /* Win98 and Win2k will happily claim to be willing to update an unqualified domain name. */ if (!(oc = lookup_option (&fqdn_universe, packet -> options, FQDN_DOMAINNAME))) goto noclient; if (!(oc = lookup_option (&fqdn_universe, packet -> options, FQDN_FQDN)) || !evaluate_option_cache(&ddns_fwd_name, packet, lease, NULL, packet->options, options, scope, oc, MDL)) goto noclient; ddns_cb->flags &= ~DDNS_UPDATE_ADDR; server_updates_a = 0; goto client_updates; } noclient: /* If do-forward-updates is disabled, this basically means don't do an update unless the client is participating, so if we get here and do-forward-updates is disabled, we can stop. */ if ((oc = lookup_option (&server_universe, options, SV_DO_FORWARD_UPDATES)) && !evaluate_boolean_option_cache(&ignorep, packet, lease, NULL, packet->options, options, scope, oc, MDL)) { goto out; } /* If it's a static lease, then don't do the DNS update unless we're specifically configured to do so. If the client asked to do its own update and we allowed that, we don't do this test. */ /* XXX: note that we cannot detect static DHCPv6 leases. */ if ((lease != NULL) && (lease->flags & STATIC_LEASE)) { if (!(oc = lookup_option(&server_universe, options, SV_UPDATE_STATIC_LEASES)) || !evaluate_boolean_option_cache(&ignorep, packet, lease, NULL, packet->options, options, scope, oc, MDL)) goto out; } /* * Compute the name for the A record. */ oc = lookup_option(&server_universe, options, SV_DDNS_HOST_NAME); if (oc) s1 = evaluate_option_cache(&ddns_hostname, packet, lease, NULL, packet->options, options, scope, oc, MDL); else s1 = 0; oc = lookup_option(&server_universe, options, SV_DDNS_DOMAIN_NAME); if (oc) s2 = evaluate_option_cache(&ddns_domainname, packet, lease, NULL, packet->options, options, scope, oc, MDL); else s2 = 0; if (s1 && s2) { if (ddns_hostname.len + ddns_domainname.len > 253) { log_error ("ddns_update: host.domain name too long"); goto out; } buffer_allocate (&ddns_fwd_name.buffer, ddns_hostname.len + ddns_domainname.len + 2, MDL); if (ddns_fwd_name.buffer) { ddns_fwd_name.data = ddns_fwd_name.buffer->data; data_string_append (&ddns_fwd_name, &ddns_hostname); ddns_fwd_name.buffer->data[ddns_fwd_name.len] = '.'; ddns_fwd_name.len++; data_string_append (&ddns_fwd_name, &ddns_domainname); ddns_fwd_name.buffer->data[ddns_fwd_name.len] ='\0'; ddns_fwd_name.terminated = 1; } } client_updates: /* See if there's a name already stored on the lease. */ if (find_bound_string(&old_ddns_fwd_name, *scope, "ddns-fwd-name")) { /* If there is, see if it's different. */ if (old_ddns_fwd_name.len != ddns_fwd_name.len || memcmp (old_ddns_fwd_name.data, ddns_fwd_name.data, old_ddns_fwd_name.len)) { /* * If the name is different, mark the old record * for deletion and continue getting the new info. */ do_remove = 1; goto in; } /* See if there's a DHCID on the lease, and if not * then potentially look for 'on events' for ad-hoc ddns. */ if (!find_bound_string(&ddns_dhcid, *scope, "ddns-txt") && (old != NULL)) { /* If there's no DHCID, the update was probably done with the old-style ad-hoc DDNS updates. So if the expiry and release events look like they're the same, run them. This should delete the old DDNS data. */ if (old -> on_expiry == old -> on_release) { execute_statements(NULL, NULL, lease, NULL, NULL, NULL, scope, old->on_expiry); if (old -> on_expiry) executable_statement_dereference (&old -> on_expiry, MDL); if (old -> on_release) executable_statement_dereference (&old -> on_release, MDL); /* Now, install the DDNS data the new way. */ goto in; } } else data_string_forget(&ddns_dhcid, MDL); /* See if the administrator wants to do updates even in cases where the update already appears to have been done. */ if (!(oc = lookup_option(&server_universe, options, SV_UPDATE_OPTIMIZATION)) || evaluate_boolean_option_cache(&ignorep, packet, lease, NULL, packet->options, options, scope, oc, MDL)) { result = 1; goto noerror; } /* If there's no "ddns-fwd-name" on the lease record, see if * there's a ddns-client-fqdn indicating a previous client * update (if it changes, we need to adjust the PTR). */ } else if (find_bound_string(&old_ddns_fwd_name, *scope, "ddns-client-fqdn")) { /* If the name is not different, no need to update the PTR record. */ if (old_ddns_fwd_name.len == ddns_fwd_name.len && !memcmp (old_ddns_fwd_name.data, ddns_fwd_name.data, old_ddns_fwd_name.len) && (!(oc = lookup_option(&server_universe, options, SV_UPDATE_OPTIMIZATION)) || evaluate_boolean_option_cache(&ignorep, packet, lease, NULL, packet->options, options, scope, oc, MDL))) { goto noerror; } } in: /* If we don't have a name that the client has been assigned, we can just skip all this. */ if ((!ddns_fwd_name.len) || (ddns_fwd_name.len > 255)) { if (ddns_fwd_name.len > 255) { log_error ("client provided fqdn: too long"); } /* If desired do the removals */ if (do_remove != 0) { (void) ddns_removals(lease, lease6, NULL); } goto out; } /* * Compute the RR TTL. * * We have two ways of computing the TTL. * The old behavior was to allow for the customer to set up * the option or to default things. For v4 this was 1/2 * of the lease time, for v6 this was DEFAULT_DDNS_TTL. * The new behavior continues to allow the customer to set * up an option but the defaults are a little different. * We now use 1/2 of the (preferred) lease time for both * v4 and v6 and cap them at a maximum value. * If the customer chooses to use an experession that references * part of the lease the v6 value will be the default as there * isn't a lease available for v6. */ ddns_ttl = DEFAULT_DDNS_TTL; if (lease != NULL) { if (lease->ends <= cur_time) { ddns_ttl = 0; } else { ddns_ttl = (lease->ends - cur_time)/2; } } #ifndef USE_OLD_DDNS_TTL else if (lease6 != NULL) { ddns_ttl = lease6->prefer/2; } if (ddns_ttl > MAX_DEFAULT_DDNS_TTL) { ddns_ttl = MAX_DEFAULT_DDNS_TTL; } #endif if ((oc = lookup_option(&server_universe, options, SV_DDNS_TTL))) { if (evaluate_option_cache(&d1, packet, lease, NULL, packet->options, options, scope, oc, MDL)) { if (d1.len == sizeof (u_int32_t)) ddns_ttl = getULong (d1.data); data_string_forget (&d1, MDL); } } ddns_cb->ttl = ddns_ttl; /* * Compute the reverse IP name, starting with the domain name. */ oc = lookup_option(&server_universe, options, SV_DDNS_REV_DOMAIN_NAME); if (oc) s1 = evaluate_option_cache(&d1, packet, lease, NULL, packet->options, options, scope, oc, MDL); else s1 = 0; /* * Figure out the length of the part of the name that depends * on the address. */ if (ddns_cb->address.len == 4) { char buf[17]; /* XXX: WOW this is gross. */ rev_name_len = snprintf(buf, sizeof(buf), "%u.%u.%u.%u.", ddns_cb->address.iabuf[3] & 0xff, ddns_cb->address.iabuf[2] & 0xff, ddns_cb->address.iabuf[1] & 0xff, ddns_cb->address.iabuf[0] & 0xff) + 1; if (s1) { rev_name_len += d1.len; if (rev_name_len > 255) { log_error("ddns_update: Calculated rev domain " "name too long."); s1 = 0; data_string_forget(&d1, MDL); } } } else if (ddns_cb->address.len == 16) { /* * IPv6 reverse names are always the same length, with * 32 hex characters separated by dots. */ rev_name_len = sizeof("0.1.2.3.4.5.6.7." "8.9.a.b.c.d.e.f." "0.1.2.3.4.5.6.7." "8.9.a.b.c.d.e.f." "ip6.arpa."); /* Set s1 to make sure we gate into updates. */ s1 = 1; } else { log_fatal("invalid address length %d", ddns_cb->address.len); /* Silence compiler warnings. */ return 0; } /* See if we are configured NOT to do reverse ptr updates */ if ((oc = lookup_option(&server_universe, options, SV_DO_REVERSE_UPDATES)) && !evaluate_boolean_option_cache(&ignorep, packet, lease, NULL, packet->options, options, scope, oc, MDL)) { ddns_cb->flags &= ~DDNS_UPDATE_PTR; } if (s1) { buffer_allocate(&ddns_cb->rev_name.buffer, rev_name_len, MDL); if (ddns_cb->rev_name.buffer != NULL) { struct data_string *rname = &ddns_cb->rev_name; rname->data = rname->buffer->data; if (ddns_cb->address.len == 4) { rname->len = sprintf((char *)rname->buffer->data, "%u.%u.%u.%u.", ddns_cb->address.iabuf[3] & 0xff, ddns_cb->address.iabuf[2] & 0xff, ddns_cb->address.iabuf[1] & 0xff, ddns_cb->address.iabuf[0] & 0xff); /* * d1.data may be opaque, garbage bytes, from * user (mis)configuration. */ data_string_append(rname, &d1); rname->buffer->data[rname->len] = '\0'; } else if (ddns_cb->address.len == 16) { char *p = (char *)&rname->buffer->data; unsigned char *a = ddns_cb->address.iabuf + 15; for (i=0; i<16; i++) { sprintf(p, "%x.%x.", (*a & 0xF), ((*a >> 4) & 0xF)); p += 4; a -= 1; } strcat(p, "ip6.arpa."); rname->len = strlen((const char *)rname->data); } rname->terminated = 1; } if (d1.data != NULL) data_string_forget(&d1, MDL); }
unsigned long long PvObject::getULong() const { std::string key = PyPvDataUtility::getValueOrSingleFieldName(pvStructurePtr); return getULong(key); }
URational getURational(const byte* buf, ByteOrder byteOrder) { uint32_t nominator = getULong(buf, byteOrder); uint32_t denominator = getULong(buf + 4, byteOrder); return std::make_pair(nominator, denominator); }
/* * Format the specified option so that a human can easily read it. */ char * pretty_print_option(unsigned int code, struct option_data *option, int emit_punct) { static char optbuf[32768]; /* XXX */ int hunksize = 0, numhunk = -1, numelem = 0; char fmtbuf[32], *op = optbuf; int i, j, k, opleft = sizeof(optbuf); unsigned char *data = option->data; unsigned char *dp = data; int len = option->len; int opcount = 0; struct in_addr foo; char comma; memset(optbuf, 0, sizeof(optbuf)); /* Code should be between 0 and 255. */ if (code > 255) { warning("pretty_print_option: bad code %d", code); goto done; } if (emit_punct) comma = ','; else comma = ' '; /* Figure out the size of the data. */ for (i = 0; dhcp_options[code].format[i]; i++) { if (!numhunk) { warning("%s: Excess information in format string: %s", dhcp_options[code].name, &(dhcp_options[code].format[i])); goto done; } numelem++; fmtbuf[i] = dhcp_options[code].format[i]; switch (dhcp_options[code].format[i]) { case 'A': --numelem; fmtbuf[i] = 0; numhunk = 0; if (hunksize == 0) { warning("%s: no size indicator before A" " in format string: %s", dhcp_options[code].name, dhcp_options[code].format); goto done; } break; case 'X': for (k = 0; k < len; k++) if (!isascii(data[k]) || !isprint(data[k])) break; if (k == len) { fmtbuf[i] = 't'; numhunk = -2; } else { hunksize++; comma = ':'; numhunk = 0; } fmtbuf[i + 1] = 0; break; case 't': fmtbuf[i + 1] = 0; numhunk = -2; break; case 'I': case 'l': case 'L': hunksize += 4; break; case 'S': hunksize += 2; break; case 'B': case 'f': hunksize++; break; case 'e': break; case 'C': hunksize += 5; break; default: warning("%s: garbage in format string: %s", dhcp_options[code].name, &(dhcp_options[code].format[i])); goto done; } } /* Check for too few bytes. */ if (hunksize > len) { warning("%s: expecting at least %d bytes; got %d", dhcp_options[code].name, hunksize, len); goto done; } /* Check for too many bytes. */ if (numhunk == -1 && hunksize < len) { warning("%s: expecting only %d bytes: got %d", dhcp_options[code].name, hunksize, len); goto done; } /* If this is an array, compute its size. */ if (!numhunk) numhunk = len / hunksize; /* See if we got an exact number of hunks. */ if (numhunk > 0 && numhunk * hunksize != len) { warning("%s: expecting %d bytes: got %d", dhcp_options[code].name, numhunk * hunksize, len); goto done; } /* A one-hunk array prints the same as a single hunk. */ if (numhunk < 0) numhunk = 1; /* Cycle through the array (or hunk) printing the data. */ for (i = 0; i < numhunk; i++) { for (j = 0; j < numelem; j++) { switch (fmtbuf[j]) { case 't': opcount = pretty_print_string(op, opleft, dp, len, emit_punct); break; case 'I': foo.s_addr = htonl(getULong(dp)); opcount = snprintf(op, opleft, "%s", inet_ntoa(foo)); dp += 4; break; case 'l': opcount = snprintf(op, opleft, "%ld", (long)getLong(dp)); dp += 4; break; case 'L': opcount = snprintf(op, opleft, "%lu", (unsigned long)getULong(dp)); dp += 4; break; case 'S': opcount = snprintf(op, opleft, "%u", getUShort(dp)); dp += 2; break; case 'B': opcount = snprintf(op, opleft, "%u", *dp); dp++; break; case 'X': opcount = snprintf(op, opleft, "%x", *dp); dp++; break; case 'f': opcount = snprintf(op, opleft, "%s", *dp ? "true" : "false"); dp++; break; case 'C': memset(&foo, 0, sizeof(foo)); memcpy(&foo.s_addr, dp+1, (*dp + 7) / 8); opcount = snprintf(op, opleft, "%s/%u", inet_ntoa(foo), *dp); if (opcount >= opleft || opcount == -1) goto toobig; dp += 1 + (*dp + 7) / 8; break; default: warning("Unexpected format code %c", fmtbuf[j]); goto toobig; } if (opcount >= opleft || opcount == -1) goto toobig; opleft -= opcount; op += opcount; if (j + 1 < numelem && comma != ':') { opcount = snprintf(op, opleft, " "); if (opcount >= opleft || opcount == -1) goto toobig; opleft -= opcount; op += opcount; } } if (i + 1 < numhunk) { opcount = snprintf(op, opleft, "%c", comma); if (opcount >= opleft || opcount == -1) goto toobig; opleft -= opcount; op += opcount; } } done: return (optbuf); toobig: memset(optbuf, 0, sizeof(optbuf)); return (optbuf); }
isc_result_t ns_parserr(ns_msg *handle, ns_sect section, int rrnum, ns_rr *rr) { int b; isc_result_t status; int tmp; /* XXX used to force a signed comparison below */ /* Make section right. */ if ((tmp = section) < 0 || section >= ns_s_max) return ISC_R_NOTIMPLEMENTED; if (section != handle->_sect) setsection(handle, section); /* Make rrnum right. */ if (rrnum == -1) rrnum = handle->_rrnum; if (rrnum < 0 || rrnum >= handle->_counts[(int)section]) return ISC_R_UNKNOWNATTRIBUTE; if (rrnum < handle->_rrnum) setsection(handle, section); if (rrnum > handle->_rrnum) { status = ns_skiprr(handle->_ptr, handle->_eom, section, rrnum - handle->_rrnum, &b); if (status != ISC_R_SUCCESS) return status; handle->_ptr += b; handle->_rrnum = rrnum; } /* Do the parse. */ b = dn_expand(handle->_msg, handle->_eom, handle->_ptr, rr->name, NS_MAXDNAME); if (b < 0) return ISC_R_FORMERR; handle->_ptr += b; if (handle->_ptr + NS_INT16SZ + NS_INT16SZ > handle->_eom) return ISC_R_INCOMPLETE; rr->type = getUShort (handle->_ptr); handle -> _ptr += 2; rr->rr_class = getUShort (handle->_ptr); handle -> _ptr += 2; if (section == ns_s_qd) { rr->ttl = 0; rr->rdlength = 0; rr->rdata = NULL; } else { if (handle->_ptr + NS_INT32SZ + NS_INT16SZ > handle->_eom) return ISC_R_INCOMPLETE; rr->ttl = getULong (handle->_ptr); handle -> _ptr += 4; rr->rdlength = getUShort (handle->_ptr); handle -> _ptr += 2; if (handle->_ptr + rr->rdlength > handle->_eom) return ISC_R_INCOMPLETE; rr->rdata = handle->_ptr; handle->_ptr += rr->rdlength; } if (++handle->_rrnum > handle->_counts[(int)section]) setsection(handle, (ns_sect)((int)section + 1)); /* All done. */ return ISC_R_SUCCESS; }
/* Determine what, if any, forward and reverse updates need to be * performed, and carry them through. */ int ddns_updates(struct packet *packet, struct lease *lease, struct lease *old, struct iasubopt *lease6, struct iasubopt *old6, struct option_state *options) { unsigned long ddns_ttl = DEFAULT_DDNS_TTL; struct data_string ddns_hostname; struct data_string ddns_domainname; struct data_string old_ddns_fwd_name; struct data_string ddns_fwd_name; struct data_string ddns_rev_name; struct data_string ddns_dhcid; struct binding_scope **scope; struct iaddr addr; struct data_string d1; struct option_cache *oc; int s1, s2; int result = 0; isc_result_t rcode1 = ISC_R_SUCCESS, rcode2 = ISC_R_SUCCESS; int server_updates_a = 1; int server_updates_ptr = 1; struct buffer *bp = (struct buffer *)0; int ignorep = 0, client_ignorep = 0; int rev_name_len; int i; if (ddns_update_style != 2) return 0; if (lease != NULL) { scope = &(lease->scope); addr = lease->ip_addr; } else if (lease6 != NULL) { scope = &(lease6->scope); memcpy(addr.iabuf, lease6->addr.s6_addr, 16); addr.len = 16; } else { log_fatal("Impossible condition at %s:%d.", MDL); /* Silence compiler warnings. */ return 0; } memset(&d1, 0, sizeof(d1)); memset (&ddns_hostname, 0, sizeof (ddns_hostname)); memset (&ddns_domainname, 0, sizeof (ddns_domainname)); memset (&old_ddns_fwd_name, 0, sizeof (ddns_fwd_name)); memset (&ddns_fwd_name, 0, sizeof (ddns_fwd_name)); memset (&ddns_rev_name, 0, sizeof (ddns_rev_name)); memset (&ddns_dhcid, 0, sizeof (ddns_dhcid)); /* If we are allowed to accept the client's update of its own A record, see if the client wants to update its own A record. */ if (!(oc = lookup_option(&server_universe, options, SV_CLIENT_UPDATES)) || evaluate_boolean_option_cache(&client_ignorep, packet, lease, NULL, packet->options, options, scope, oc, MDL)) { /* If there's no fqdn.no-client-update or if it's nonzero, don't try to use the client-supplied XXX */ if (!(oc = lookup_option (&fqdn_universe, packet -> options, FQDN_SERVER_UPDATE)) || evaluate_boolean_option_cache(&ignorep, packet, lease, NULL, packet->options, options, scope, oc, MDL)) goto noclient; /* Win98 and Win2k will happily claim to be willing to update an unqualified domain name. */ if (!(oc = lookup_option (&fqdn_universe, packet -> options, FQDN_DOMAINNAME))) goto noclient; if (!(oc = lookup_option (&fqdn_universe, packet -> options, FQDN_FQDN)) || !evaluate_option_cache(&ddns_fwd_name, packet, lease, NULL, packet->options, options, scope, oc, MDL)) goto noclient; server_updates_a = 0; goto client_updates; } noclient: /* If do-forward-updates is disabled, this basically means don't do an update unless the client is participating, so if we get here and do-forward-updates is disabled, we can stop. */ if ((oc = lookup_option (&server_universe, options, SV_DO_FORWARD_UPDATES)) && !evaluate_boolean_option_cache(&ignorep, packet, lease, NULL, packet->options, options, scope, oc, MDL)) { return 0; } /* If it's a static lease, then don't do the DNS update unless we're specifically configured to do so. If the client asked to do its own update and we allowed that, we don't do this test. */ /* XXX: note that we cannot detect static DHCPv6 leases. */ if ((lease != NULL) && (lease->flags & STATIC_LEASE)) { if (!(oc = lookup_option(&server_universe, options, SV_UPDATE_STATIC_LEASES)) || !evaluate_boolean_option_cache(&ignorep, packet, lease, NULL, packet->options, options, scope, oc, MDL)) return 0; } /* * Compute the name for the A record. */ oc = lookup_option(&server_universe, options, SV_DDNS_HOST_NAME); if (oc) s1 = evaluate_option_cache(&ddns_hostname, packet, lease, NULL, packet->options, options, scope, oc, MDL); else s1 = 0; oc = lookup_option(&server_universe, options, SV_DDNS_DOMAIN_NAME); if (oc) s2 = evaluate_option_cache(&ddns_domainname, packet, lease, NULL, packet->options, options, scope, oc, MDL); else s2 = 0; if (s1 && s2) { if (ddns_hostname.len + ddns_domainname.len > 253) { log_error ("ddns_update: host.domain name too long"); goto out; } buffer_allocate (&ddns_fwd_name.buffer, ddns_hostname.len + ddns_domainname.len + 2, MDL); if (ddns_fwd_name.buffer) { ddns_fwd_name.data = ddns_fwd_name.buffer -> data; data_string_append (&ddns_fwd_name, &ddns_hostname); ddns_fwd_name.buffer -> data [ddns_fwd_name.len] = '.'; ddns_fwd_name.len++; data_string_append (&ddns_fwd_name, &ddns_domainname); ddns_fwd_name.buffer -> data [ddns_fwd_name.len] ='\0'; ddns_fwd_name.terminated = 1; } } client_updates: /* See if there's a name already stored on the lease. */ if (find_bound_string(&old_ddns_fwd_name, *scope, "ddns-fwd-name")) { /* If there is, see if it's different. */ if (old_ddns_fwd_name.len != ddns_fwd_name.len || memcmp (old_ddns_fwd_name.data, ddns_fwd_name.data, old_ddns_fwd_name.len)) { /* If the name is different, try to delete the old A record. */ if (!ddns_removals(lease, lease6)) goto out; /* If the delete succeeded, go install the new record. */ goto in; } /* See if there's a DHCID on the lease, and if not * then potentially look for 'on events' for ad-hoc ddns. */ if (!find_bound_string(&ddns_dhcid, *scope, "ddns-txt") && (old != NULL)) { /* If there's no DHCID, the update was probably done with the old-style ad-hoc DDNS updates. So if the expiry and release events look like they're the same, run them. This should delete the old DDNS data. */ if (old -> on_expiry == old -> on_release) { execute_statements(NULL, NULL, lease, NULL, NULL, NULL, scope, old->on_expiry); if (old -> on_expiry) executable_statement_dereference (&old -> on_expiry, MDL); if (old -> on_release) executable_statement_dereference (&old -> on_release, MDL); /* Now, install the DDNS data the new way. */ goto in; } } else data_string_forget(&ddns_dhcid, MDL); /* See if the administrator wants to do updates even in cases where the update already appears to have been done. */ if (!(oc = lookup_option(&server_universe, options, SV_UPDATE_OPTIMIZATION)) || evaluate_boolean_option_cache(&ignorep, packet, lease, NULL, packet->options, options, scope, oc, MDL)) { result = 1; goto noerror; } /* If there's no "ddns-fwd-name" on the lease record, see if * there's a ddns-client-fqdn indicating a previous client * update (if it changes, we need to adjust the PTR). */ } else if (find_bound_string(&old_ddns_fwd_name, *scope, "ddns-client-fqdn")) { /* If the name is not different, no need to update the PTR record. */ if (old_ddns_fwd_name.len == ddns_fwd_name.len && !memcmp (old_ddns_fwd_name.data, ddns_fwd_name.data, old_ddns_fwd_name.len) && (!(oc = lookup_option(&server_universe, options, SV_UPDATE_OPTIMIZATION)) || evaluate_boolean_option_cache(&ignorep, packet, lease, NULL, packet->options, options, scope, oc, MDL))) { goto noerror; } } in: /* If we don't have a name that the client has been assigned, we can just skip all this. */ if (!ddns_fwd_name.len) goto out; if (ddns_fwd_name.len > 255) { log_error ("client provided fqdn: too long"); goto out; } /* * Compute the RR TTL. */ ddns_ttl = DEFAULT_DDNS_TTL; if ((oc = lookup_option(&server_universe, options, SV_DDNS_TTL))) { if (evaluate_option_cache(&d1, packet, lease, NULL, packet->options, options, scope, oc, MDL)) { if (d1.len == sizeof (u_int32_t)) ddns_ttl = getULong (d1.data); data_string_forget (&d1, MDL); } } /* * Compute the reverse IP name, starting with the domain name. */ oc = lookup_option(&server_universe, options, SV_DDNS_REV_DOMAIN_NAME); if (oc) s1 = evaluate_option_cache(&d1, packet, lease, NULL, packet->options, options, scope, oc, MDL); else s1 = 0; /* * Figure out the length of the part of the name that depends * on the address. */ if (addr.len == 4) { char buf[17]; /* XXX: WOW this is gross. */ rev_name_len = snprintf(buf, sizeof(buf), "%u.%u.%u.%u.", addr.iabuf[3] & 0xff, addr.iabuf[2] & 0xff, addr.iabuf[1] & 0xff, addr.iabuf[0] & 0xff) + 1; if (s1) { rev_name_len += d1.len; if (rev_name_len > 255) { log_error("ddns_update: Calculated rev domain " "name too long."); s1 = 0; data_string_forget(&d1, MDL); } } } else if (addr.len == 16) { /* * IPv6 reverse names are always the same length, with * 32 hex characters separated by dots. */ rev_name_len = sizeof("0.1.2.3.4.5.6.7." "8.9.a.b.c.d.e.f." "0.1.2.3.4.5.6.7." "8.9.a.b.c.d.e.f." "ip6.arpa."); /* Set s1 to make sure we gate into updates. */ s1 = 1; } else { log_fatal("invalid address length %d", addr.len); /* Silence compiler warnings. */ return 0; } /* See if we are configured NOT to do reverse ptr updates */ if ((oc = lookup_option(&server_universe, options, SV_DO_REVERSE_UPDATES)) && !evaluate_boolean_option_cache(&ignorep, packet, lease, NULL, packet->options, options, scope, oc, MDL)) { server_updates_ptr = 0; } if (s1) { i=buffer_allocate(&ddns_rev_name.buffer, rev_name_len, MDL); if(!i){ log_error("buffer_allocate failed!\n"); } if (ddns_rev_name.buffer != NULL) { ddns_rev_name.data = ddns_rev_name.buffer->data; if (addr.len == 4) { ddns_rev_name.len = sprintf((char *)ddns_rev_name.buffer->data, "%u.%u.%u.%u.", addr.iabuf[3] & 0xff, addr.iabuf[2] & 0xff, addr.iabuf[1] & 0xff, addr.iabuf[0] & 0xff); /* * d1.data may be opaque, garbage bytes, from * user (mis)configuration. */ data_string_append(&ddns_rev_name, &d1); ddns_rev_name.buffer->data[ddns_rev_name.len] = '\0'; } else if (addr.len == 16) { char *p = (char *)&ddns_rev_name.buffer->data; unsigned char *a = addr.iabuf + 15; for (i=0; i<16; i++) { sprintf(p, "%x.%x.", (*a & 0xF), ((*a >> 4) & 0xF)); p += 4; a -= 1; } strcat(p, "ip6.arpa."); ddns_rev_name.len = strlen((const char *)ddns_rev_name.data); } ddns_rev_name.terminated = 1; }
int ddns_updates (struct packet *packet, struct lease *lease, struct lease *old, struct lease_state *state) { unsigned long ddns_ttl = DEFAULT_DDNS_TTL; struct data_string ddns_hostname; struct data_string ddns_domainname; struct data_string old_ddns_fwd_name; struct data_string ddns_fwd_name; struct data_string ddns_rev_name; struct data_string ddns_dhcid; unsigned len; struct data_string d1; struct option_cache *oc; int s1, s2; int result = 0; isc_result_t rcode1 = ISC_R_SUCCESS, rcode2 = ISC_R_SUCCESS; int server_updates_a = 1; int server_updates_ptr = 1; struct buffer *bp = (struct buffer *)0; int ignorep = 0, client_ignorep = 0; if (ddns_update_style != 2) return 0; /* Can only cope with IPv4 addrs at the moment. */ if (lease -> ip_addr . len != 4) return 0; memset(&d1, 0, sizeof(d1)); memset (&ddns_hostname, 0, sizeof (ddns_hostname)); memset (&ddns_domainname, 0, sizeof (ddns_domainname)); memset (&old_ddns_fwd_name, 0, sizeof (ddns_fwd_name)); memset (&ddns_fwd_name, 0, sizeof (ddns_fwd_name)); memset (&ddns_rev_name, 0, sizeof (ddns_rev_name)); memset (&ddns_dhcid, 0, sizeof (ddns_dhcid)); /* If we are allowed to accept the client's update of its own A record, see if the client wants to update its own A record. */ if (!(oc = lookup_option(&server_universe, state->options, SV_CLIENT_UPDATES)) || evaluate_boolean_option_cache(&client_ignorep, packet, lease, NULL, packet->options, state->options, &lease->scope, oc, MDL)) { /* If there's no fqdn.no-client-update or if it's nonzero, don't try to use the client-supplied XXX */ if (!(oc = lookup_option (&fqdn_universe, packet -> options, FQDN_SERVER_UPDATE)) || evaluate_boolean_option_cache (&ignorep, packet, lease, (struct client_state *)0, packet -> options, state -> options, &lease -> scope, oc, MDL)) goto noclient; /* Win98 and Win2k will happily claim to be willing to update an unqualified domain name. */ if (!(oc = lookup_option (&fqdn_universe, packet -> options, FQDN_DOMAINNAME))) goto noclient; if (!(oc = lookup_option (&fqdn_universe, packet -> options, FQDN_FQDN)) || !evaluate_option_cache (&ddns_fwd_name, packet, lease, (struct client_state *)0, packet -> options, state -> options, &lease -> scope, oc, MDL)) goto noclient; server_updates_a = 0; goto client_updates; } noclient: /* If do-forward-updates is disabled, this basically means don't do an update unless the client is participating, so if we get here and do-forward-updates is disabled, we can stop. */ if ((oc = lookup_option (&server_universe, state -> options, SV_DO_FORWARD_UPDATES)) && !evaluate_boolean_option_cache (&ignorep, packet, lease, (struct client_state *)0, packet -> options, state -> options, &lease -> scope, oc, MDL)) { return 0; } /* If it's a static lease, then don't do the DNS update unless we're specifically configured to do so. If the client asked to do its own update and we allowed that, we don't do this test. */ if (lease -> flags & STATIC_LEASE) { if (!(oc = lookup_option (&server_universe, state -> options, SV_UPDATE_STATIC_LEASES)) || !evaluate_boolean_option_cache (&ignorep, packet, lease, (struct client_state *)0, packet -> options, state -> options, &lease -> scope, oc, MDL)) return 0; } /* * Compute the name for the A record. */ oc = lookup_option (&server_universe, state -> options, SV_DDNS_HOST_NAME); if (oc) s1 = evaluate_option_cache (&ddns_hostname, packet, lease, (struct client_state *)0, packet -> options, state -> options, &lease -> scope, oc, MDL); else s1 = 0; oc = lookup_option (&server_universe, state -> options, SV_DDNS_DOMAIN_NAME); if (oc) s2 = evaluate_option_cache (&ddns_domainname, packet, lease, (struct client_state *)0, packet -> options, state -> options, &lease -> scope, oc, MDL); else s2 = 0; if (s1 && s2) { if (ddns_hostname.len + ddns_domainname.len > 253) { log_error ("ddns_update: host.domain name too long"); goto out; } buffer_allocate (&ddns_fwd_name.buffer, ddns_hostname.len + ddns_domainname.len + 2, MDL); if (ddns_fwd_name.buffer) { ddns_fwd_name.data = ddns_fwd_name.buffer -> data; data_string_append (&ddns_fwd_name, &ddns_hostname); ddns_fwd_name.buffer -> data [ddns_fwd_name.len] = '.'; ddns_fwd_name.len++; data_string_append (&ddns_fwd_name, &ddns_domainname); ddns_fwd_name.buffer -> data [ddns_fwd_name.len] ='\0'; ddns_fwd_name.terminated = 1; } } client_updates: /* See if there's a name already stored on the lease. */ if (find_bound_string (&old_ddns_fwd_name, lease -> scope, "ddns-fwd-name")) { /* If there is, see if it's different. */ if (old_ddns_fwd_name.len != ddns_fwd_name.len || memcmp (old_ddns_fwd_name.data, ddns_fwd_name.data, old_ddns_fwd_name.len)) { /* If the name is different, try to delete the old A record. */ if (!ddns_removals (lease)) goto out; /* If the delete succeeded, go install the new record. */ goto in; } /* See if there's a DHCID on the lease. */ if (!find_bound_string (&ddns_dhcid, lease -> scope, "ddns-txt")) { /* If there's no DHCID, the update was probably done with the old-style ad-hoc DDNS updates. So if the expiry and release events look like they're the same, run them. This should delete the old DDNS data. */ if (old -> on_expiry == old -> on_release) { execute_statements ((struct binding_value **)0, (struct packet *)0, lease, (struct client_state *)0, (struct option_state *)0, (struct option_state *)0, &lease -> scope, old -> on_expiry); if (old -> on_expiry) executable_statement_dereference (&old -> on_expiry, MDL); if (old -> on_release) executable_statement_dereference (&old -> on_release, MDL); /* Now, install the DDNS data the new way. */ goto in; } } else data_string_forget(&ddns_dhcid, MDL); /* See if the administrator wants to do updates even in cases where the update already appears to have been done. */ if (!(oc = lookup_option (&server_universe, state -> options, SV_UPDATE_OPTIMIZATION)) || evaluate_boolean_option_cache (&ignorep, packet, lease, (struct client_state *)0, packet -> options, state -> options, &lease -> scope, oc, MDL)) { result = 1; goto noerror; } /* If there's no "ddns-fwd-name" on the lease record, see if * there's a ddns-client-fqdn indicating a previous client * update (if it changes, we need to adjust the PTR). */ } else if (find_bound_string(&old_ddns_fwd_name, lease->scope, "ddns-client-fqdn")) { /* If the name is not different, no need to update the PTR record. */ if (old_ddns_fwd_name.len == ddns_fwd_name.len && !memcmp (old_ddns_fwd_name.data, ddns_fwd_name.data, old_ddns_fwd_name.len) && (!(oc = lookup_option (&server_universe, state -> options, SV_UPDATE_OPTIMIZATION)) || evaluate_boolean_option_cache (&ignorep, packet, lease, (struct client_state *)0, packet -> options, state -> options, &lease -> scope, oc, MDL))) { goto noerror; } } in: /* If we don't have a name that the client has been assigned, we can just skip all this. */ if (!ddns_fwd_name.len) goto out; if (ddns_fwd_name.len > 255) { log_error ("client provided fqdn: too long"); goto out; } /* * Compute the RR TTL. */ ddns_ttl = DEFAULT_DDNS_TTL; if ((oc = lookup_option (&server_universe, state -> options, SV_DDNS_TTL))) { if (evaluate_option_cache (&d1, packet, lease, (struct client_state *)0, packet -> options, state -> options, &lease -> scope, oc, MDL)) { if (d1.len == sizeof (u_int32_t)) ddns_ttl = getULong (d1.data); data_string_forget (&d1, MDL); } } /* CC: see if we are configured NOT to do reverse ptr updates */ if ((oc = lookup_option (&server_universe, state -> options, SV_DO_REVERSE_UPDATES)) && !evaluate_boolean_option_cache (&ignorep, packet, lease, (struct client_state *)0, packet -> options, state -> options, &lease -> scope, oc, MDL)) { server_updates_ptr = 0; } /* * Compute the reverse IP name. */ oc = lookup_option (&server_universe, state -> options, SV_DDNS_REV_DOMAIN_NAME); if (oc) s1 = evaluate_option_cache (&d1, packet, lease, (struct client_state *)0, packet -> options, state -> options, &lease -> scope, oc, MDL); else s1 = 0; if (s1 && (d1.len > 238)) { log_error ("ddns_update: Calculated rev domain name too long."); s1 = 0; data_string_forget (&d1, MDL); } if (oc && s1) { /* Buffer length: XXX.XXX.XXX.XXX.<ddns-rev-domain-name>\0 */ buffer_allocate (&ddns_rev_name.buffer, d1.len + 17, MDL); if (ddns_rev_name.buffer) { ddns_rev_name.data = ddns_rev_name.buffer -> data; /* %Audit% Cannot exceed 17 bytes. %2004.06.17,Safe% */ sprintf ((char *)ddns_rev_name.buffer -> data, "%u.%u.%u.%u.", lease -> ip_addr . iabuf[3] & 0xff, lease -> ip_addr . iabuf[2] & 0xff, lease -> ip_addr . iabuf[1] & 0xff, lease -> ip_addr . iabuf[0] & 0xff); ddns_rev_name.len = strlen ((const char *)ddns_rev_name.data); data_string_append (&ddns_rev_name, &d1); ddns_rev_name.buffer -> data [ddns_rev_name.len] ='\0'; ddns_rev_name.terminated = 1; } data_string_forget (&d1, MDL); } /* * If we are updating the A record, compute the DHCID value. */ if (server_updates_a) { if (lease -> uid && lease -> uid_len) result = get_dhcid (&ddns_dhcid, DHO_DHCP_CLIENT_IDENTIFIER, lease -> uid, lease -> uid_len); else result = get_dhcid (&ddns_dhcid, 0, lease -> hardware_addr.hbuf, lease -> hardware_addr.hlen); if (!result) goto badfqdn; } /* * Start the resolver, if necessary. */ if (!resolver_inited) { minires_ninit (&resolver_state); resolver_inited = 1; resolver_state.retrans = 1; resolver_state.retry = 1; } /* * Perform updates. */ if (ddns_fwd_name.len && ddns_dhcid.len) { unsigned conflict; oc = lookup_option(&server_universe, state->options, SV_DDNS_CONFLICT_DETECT); if (!oc || evaluate_boolean_option_cache(&ignorep, packet, lease, NULL, packet->options, state->options, &lease->scope, oc, MDL)) conflict = 1; else conflict = 0; rcode1 = ddns_update_a (&ddns_fwd_name, lease -> ip_addr, &ddns_dhcid, ddns_ttl, 0, conflict); } if (rcode1 == ISC_R_SUCCESS && server_updates_ptr) { if (ddns_fwd_name.len && ddns_rev_name.len) rcode2 = ddns_update_ptr (&ddns_fwd_name, &ddns_rev_name, ddns_ttl); } else rcode2 = rcode1; if (rcode1 == ISC_R_SUCCESS && (server_updates_a || rcode2 == ISC_R_SUCCESS)) { bind_ds_value (&lease -> scope, (server_updates_a ? "ddns-fwd-name" : "ddns-client-fqdn"), &ddns_fwd_name); if (server_updates_a) bind_ds_value (&lease -> scope, "ddns-txt", &ddns_dhcid); } if (rcode2 == ISC_R_SUCCESS && server_updates_ptr) { bind_ds_value (&lease -> scope, "ddns-rev-name", &ddns_rev_name); } noerror: /* * If fqdn-reply option is disabled in dhcpd.conf, then don't * send the client an FQDN option at all, even if one was requested. * (WinXP clients allegedly misbehave if the option is present, * refusing to handle PTR updates themselves). */ if ((oc = lookup_option (&server_universe, state->options, SV_FQDN_REPLY)) && !evaluate_boolean_option_cache (&ignorep, packet, lease, (struct client_state *)0, packet->options, state->options, &lease->scope, oc, MDL)) { goto badfqdn; /* If we're ignoring client updates, then we tell a sort of 'white * lie'. We've already updated the name the server wants (per the * config written by the server admin). Now let the client do as * it pleases with the name they supplied (if any). * * We only form an FQDN option this way if the client supplied an * FQDN option that had FQDN_SERVER_UPDATE set false. */ } else if (client_ignorep && (oc = lookup_option(&fqdn_universe, packet->options, FQDN_SERVER_UPDATE)) && !evaluate_boolean_option_cache(&ignorep, packet, lease, NULL, packet->options, state->options, &lease->scope, oc, MDL)) { oc = lookup_option(&fqdn_universe, packet->options, FQDN_FQDN); if (oc && evaluate_option_cache(&d1, packet, lease, NULL, packet->options, state->options, &global_scope, oc, MDL)) { if (d1.len == 0 || !buffer_allocate(&bp, d1.len + 5, MDL)) goto badfqdn; /* Server pretends it is not updating. */ bp->data[0] = 0; if (!save_option_buffer(&fqdn_universe, state->options, bp, &bp->data[0], 1, FQDN_SERVER_UPDATE, 0)) goto badfqdn; /* Client is encouraged to update. */ bp->data[1] = 0; if (!save_option_buffer(&fqdn_universe, state->options, bp, &bp->data[1], 1, FQDN_NO_CLIENT_UPDATE, 0)) goto badfqdn; /* Use the encoding of client's FQDN option. */ oc = lookup_option(&fqdn_universe, packet->options, FQDN_ENCODED); if (oc && evaluate_boolean_option_cache(&ignorep, packet, lease, NULL, packet->options, state->options, &lease->scope, oc, MDL)) bp->data[2] = 1; /* FQDN is encoded. */ else bp->data[2] = 0; /* FQDN is not encoded. */ if (!save_option_buffer(&fqdn_universe, state->options, bp, &bp->data[2], 1, FQDN_ENCODED, 0)) goto badfqdn; /* Current FQDN drafts indicate 255 is mandatory. */ bp->data[3] = 255; if (!save_option_buffer(&fqdn_universe, state->options, bp, &bp->data[3], 1, FQDN_RCODE1, 0)) goto badfqdn; bp->data[4] = 255; if (!save_option_buffer(&fqdn_universe, state->options, bp, &bp->data[4], 1, FQDN_RCODE2, 0)) goto badfqdn; /* Copy in the FQDN supplied by the client. Note well * that the format of this option in the cache is going * to be in text format. If the fqdn supplied by the * client is encoded, it is decoded into the option * cache when parsed out of the packet. It will be * re-encoded when the option is assembled to be * transmitted if the client elects that encoding. */ memcpy(&bp->data[5], d1.data, d1.len); if (!save_option_buffer(&fqdn_universe, state->options, bp, &bp->data[5], 1, FQDN_FQDN, 0)) goto badfqdn; data_string_forget(&d1, MDL); } /* Set up the outgoing FQDN option if there was an incoming * FQDN option. If there's a valid FQDN option, there MUST * be an FQDN_SERVER_UPDATES suboption, it's part of the fixed * length head of the option contents, so we test the latter * to detect the presence of the former. */ } else if ((oc = lookup_option(&fqdn_universe, packet->options, FQDN_ENCODED)) && buffer_allocate(&bp, ddns_fwd_name.len + 5, MDL)) { bp -> data [0] = server_updates_a; if (!save_option_buffer (&fqdn_universe, state -> options, bp, &bp -> data [0], 1, FQDN_SERVER_UPDATE, 0)) goto badfqdn; bp -> data [1] = server_updates_a; if (!save_option_buffer (&fqdn_universe, state -> options, bp, &bp -> data [1], 1, FQDN_NO_CLIENT_UPDATE, 0)) goto badfqdn; /* Do the same encoding the client did. */ if (evaluate_boolean_option_cache(&ignorep, packet, lease, NULL, packet->options, state->options, &lease->scope, oc, MDL)) bp -> data [2] = 1; else bp -> data [2] = 0; if (!save_option_buffer (&fqdn_universe, state -> options, bp, &bp -> data [2], 1, FQDN_ENCODED, 0)) goto badfqdn; bp -> data [3] = isc_rcode_to_ns (rcode1); if (!save_option_buffer (&fqdn_universe, state -> options, bp, &bp -> data [3], 1, FQDN_RCODE1, 0)) goto badfqdn; bp -> data [4] = isc_rcode_to_ns (rcode2); if (!save_option_buffer (&fqdn_universe, state -> options, bp, &bp -> data [4], 1, FQDN_RCODE2, 0)) goto badfqdn; if (ddns_fwd_name.len) { memcpy (&bp -> data [5], ddns_fwd_name.data, ddns_fwd_name.len); if (!save_option_buffer (&fqdn_universe, state -> options, bp, &bp -> data [5], ddns_fwd_name.len, FQDN_FQDN, 0)) goto badfqdn; } } badfqdn: out: /* * Final cleanup. */ data_string_forget(&d1, MDL); data_string_forget(&ddns_hostname, MDL); data_string_forget(&ddns_domainname, MDL); data_string_forget(&old_ddns_fwd_name, MDL); data_string_forget(&ddns_fwd_name, MDL); data_string_forget(&ddns_rev_name, MDL); data_string_forget(&ddns_dhcid, MDL); if (bp) buffer_dereference(&bp, MDL); return result; }
void PsdImage::readMetadata() { #ifdef DEBUG std::cerr << "Exiv2::PsdImage::readMetadata: Reading Photoshop file " << io_->path() << "\n"; #endif if (io_->open() != 0) { throw Error(9, io_->path(), strError()); } IoCloser closer(*io_); // Ensure that this is the correct image type if (!isPsdType(*io_, false)) { if (io_->error() || io_->eof()) throw Error(14); throw Error(3, "Photoshop"); } clearMetadata(); /* The Photoshop header goes as follows -- all numbers are in big-endian byte order: offset length name description ====== ======= ========= ========= 0 4 bytes signature always '8BPS' 4 2 bytes version always equal to 1 6 6 bytes reserved must be zero 12 2 bytes channels number of channels in the image, including alpha channels (1 to 24) 14 4 bytes rows the height of the image in pixels 18 4 bytes columns the width of the image in pixels 22 2 bytes depth the number of bits per channel 24 2 bytes mode the color mode of the file; Supported values are: Bitmap=0; Grayscale=1; Indexed=2; RGB=3; CMYK=4; Multichannel=7; Duotone=8; Lab=9 */ byte buf[26]; if (io_->read(buf, 26) != 26) { throw Error(3, "Photoshop"); } pixelWidth_ = getLong(buf + 18, bigEndian); pixelHeight_ = getLong(buf + 14, bigEndian); // immediately following the image header is the color mode data section, // the first four bytes of which specify the byte size of the whole section if (io_->read(buf, 4) != 4) { throw Error(3, "Photoshop"); } // skip it uint32_t colorDataLength = getULong(buf, bigEndian); if (io_->seek(colorDataLength, BasicIo::cur)) { throw Error(3, "Photoshop"); } // after the color data section, comes a list of resource blocks, preceeded by the total byte size if (io_->read(buf, 4) != 4) { throw Error(3, "Photoshop"); } uint32_t resourcesLength = getULong(buf, bigEndian); while (resourcesLength > 0) { if (io_->read(buf, 8) != 8) { throw Error(3, "Photoshop"); } // read resource type and ID uint32_t resourceType = getULong(buf, bigEndian); uint16_t resourceId = getUShort(buf + 4, bigEndian); if (resourceType != kPhotoshopResourceType) { break; // bad resource type } uint32_t resourceNameLength = buf[6] & ~1; // skip the resource name, plus any padding io_->seek(resourceNameLength, BasicIo::cur); // read resource size if (io_->read(buf, 4) != 4) { throw Error(3, "Photoshop"); } uint32_t resourceSize = getULong(buf, bigEndian); uint32_t curOffset = io_->tell(); #ifdef DEBUG std::cerr << std::hex << "resourceId: " << resourceId << std::dec << " length: " << resourceSize << std::hex << "\n"; #endif readResourceBlock(resourceId, resourceSize); resourceSize = (resourceSize + 1) & ~1; // pad to even io_->seek(curOffset + resourceSize, BasicIo::beg); resourcesLength -= (12 + resourceNameLength + resourceSize); } } // PsdImage::readMetadata
/* * Format the specified option so that a human can easily read it. */ char * pretty_print_option(unsigned int code, unsigned char *data, int len, int emit_commas, int emit_quotes) { static char optbuf[32768]; /* XXX */ int hunksize = 0, numhunk = -1, numelem = 0; char fmtbuf[32], *op = optbuf; int i, j, k, opleft = sizeof(optbuf); unsigned char *dp = data; struct in_addr foo; char comma; /* Code should be between 0 and 255. */ if (code > 255) error("pretty_print_option: bad code %d", code); if (emit_commas) comma = ','; else comma = ' '; /* Figure out the size of the data. */ for (i = 0; dhcp_options[code].format[i]; i++) { if (!numhunk) { warning("%s: Excess information in format string: %s", dhcp_options[code].name, &(dhcp_options[code].format[i])); break; } numelem++; fmtbuf[i] = dhcp_options[code].format[i]; switch (dhcp_options[code].format[i]) { case 'A': --numelem; fmtbuf[i] = 0; numhunk = 0; break; case 'X': for (k = 0; k < len; k++) if (!isascii(data[k]) || !isprint(data[k])) break; if (k == len) { fmtbuf[i] = 't'; numhunk = -2; } else { fmtbuf[i] = 'x'; hunksize++; comma = ':'; numhunk = 0; } fmtbuf[i + 1] = 0; break; case 't': fmtbuf[i] = 't'; fmtbuf[i + 1] = 0; numhunk = -2; break; case 'I': case 'l': case 'L': hunksize += 4; break; case 's': case 'S': hunksize += 2; break; case 'b': case 'B': case 'f': hunksize++; break; case 'e': break; default: warning("%s: garbage in format string: %s", dhcp_options[code].name, &(dhcp_options[code].format[i])); break; } } /* Check for too few bytes... */ if (hunksize > len) { warning("%s: expecting at least %d bytes; got %d", dhcp_options[code].name, hunksize, len); return ("<error>"); } /* Check for too many bytes... */ if (numhunk == -1 && hunksize < len) warning("%s: %d extra bytes", dhcp_options[code].name, len - hunksize); /* If this is an array, compute its size. */ if (!numhunk) numhunk = len / hunksize; /* See if we got an exact number of hunks. */ if (numhunk > 0 && numhunk * hunksize < len) warning("%s: %d extra bytes at end of array", dhcp_options[code].name, len - numhunk * hunksize); /* A one-hunk array prints the same as a single hunk. */ if (numhunk < 0) numhunk = 1; /* Cycle through the array (or hunk) printing the data. */ for (i = 0; i < numhunk; i++) { for (j = 0; j < numelem; j++) { int opcount; switch (fmtbuf[j]) { case 't': if (emit_quotes) { *op++ = '"'; opleft--; } for (; dp < data + len; dp++) { if (!isascii(*dp) || !isprint(*dp)) { if (dp + 1 != data + len || *dp != 0) { snprintf(op, opleft, "\\%03o", *dp); op += 4; opleft -= 4; } } else if (*dp == '"' || *dp == '\'' || *dp == '$' || *dp == '`' || *dp == '\\') { *op++ = '\\'; *op++ = *dp; opleft -= 2; } else { *op++ = *dp; opleft--; } } if (emit_quotes) { *op++ = '"'; opleft--; } *op = 0; break; case 'I': foo.s_addr = htonl(getULong(dp)); opcount = strlcpy(op, inet_ntoa(foo), opleft); if (opcount >= opleft) goto toobig; opleft -= opcount; dp += 4; break; case 'l': opcount = snprintf(op, opleft, "%ld", (long)getLong(dp)); if (opcount >= opleft || opcount == -1) goto toobig; opleft -= opcount; dp += 4; break; case 'L': opcount = snprintf(op, opleft, "%ld", (unsigned long)getULong(dp)); if (opcount >= opleft || opcount == -1) goto toobig; opleft -= opcount; dp += 4; break; case 's': opcount = snprintf(op, opleft, "%d", getShort(dp)); if (opcount >= opleft || opcount == -1) goto toobig; opleft -= opcount; dp += 2; break; case 'S': opcount = snprintf(op, opleft, "%d", getUShort(dp)); if (opcount >= opleft || opcount == -1) goto toobig; opleft -= opcount; dp += 2; break; case 'b': opcount = snprintf(op, opleft, "%d", *(char *)dp++); if (opcount >= opleft || opcount == -1) goto toobig; opleft -= opcount; break; case 'B': opcount = snprintf(op, opleft, "%d", *dp++); if (opcount >= opleft || opcount == -1) goto toobig; opleft -= opcount; break; case 'x': opcount = snprintf(op, opleft, "%x", *dp++); if (opcount >= opleft || opcount == -1) goto toobig; opleft -= opcount; break; case 'f': opcount = strlcpy(op, *dp++ ? "true" : "false", opleft); if (opcount >= opleft) goto toobig; opleft -= opcount; break; default: warning("Unexpected format code %c", fmtbuf[j]); } op += strlen(op); opleft -= strlen(op); if (opleft < 1) goto toobig; if (j + 1 < numelem && comma != ':') { *op++ = ' '; opleft--; } } if (i + 1 < numhunk) { *op++ = comma; opleft--; } if (opleft < 1) goto toobig; } return (optbuf); toobig: warning("dhcp option too large"); return ("<error>"); }
inline uint32_t getValue(const byte* buf, ByteOrder byteOrder) { return getULong(buf, byteOrder); }