예제 #1
0
    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
예제 #3
0
 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
예제 #4
0
    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
예제 #5
0
    // 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
예제 #6
0
unsigned long SQLiteQuery::getULong(const std::string &name)
{
	int col = m_aCols[name];
	if (col >= 0)
		return getULong(col);
	
	return 0;
}
예제 #7
0
const Reader &BasicReader::readUnsignedLong (unsigned long& val )
{
    Glib::ustring buf = readWord();
    unsigned long ival;
    if (getULong(buf, &ival))
        val = ival;
    return *this;
}
예제 #8
0
    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
예제 #9
0
 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
예제 #10
0
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;
}
예제 #11
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
예제 #12
0
 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
예제 #13
0
파일: tiffimage.cpp 프로젝트: obklar/exiv2
    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
예제 #14
0
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
예제 #15
0
    // 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
예제 #16
0
    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
예제 #17
0
    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
예제 #18
0
    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
예제 #19
0
// 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");
	}
}
예제 #20
0
unsigned long SQLiteQuery::getULong()
{
	return getULong(m_thisColumn++);
}
예제 #21
0
파일: ddns.c 프로젝트: greearb/dhcp-ct
/* 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);
	}
예제 #22
0
파일: PvObject.cpp 프로젝트: dchabot/pvaPy
unsigned long long PvObject::getULong() const
{
    std::string key = PyPvDataUtility::getValueOrSingleFieldName(pvStructurePtr);
    return getULong(key);
}
예제 #23
0
파일: types.cpp 프로젝트: obklar/exiv2
 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);
 }
예제 #24
0
/*
 * 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);
}
예제 #25
0
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;
}
예제 #26
0
파일: ddns.c 프로젝트: inibir/daemongroup
/* 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;
		}
예제 #27
0
파일: ddns.c 프로젝트: tcdog001/apv5sdk-v15
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;
}
예제 #28
0
    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
예제 #29
0
/*
 * 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>");
}
예제 #30
0
 inline uint32_t getValue(const byte* buf, ByteOrder byteOrder)
 {
     return getULong(buf, byteOrder);
 }