mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 06:38:20 +00:00
719 lines
15 KiB
C++
719 lines
15 KiB
C++
#include <ctype.h>
|
|
|
|
#include "net_util.h"
|
|
#include "SerializationFormat.h"
|
|
#include "Serializer.h"
|
|
#include "Reporter.h"
|
|
|
|
SerializationFormat::SerializationFormat()
|
|
{
|
|
output = 0;
|
|
}
|
|
|
|
SerializationFormat::~SerializationFormat()
|
|
{
|
|
delete [] output;
|
|
}
|
|
|
|
void SerializationFormat::StartRead(char* data, uint32 arg_len)
|
|
{
|
|
input = data;
|
|
input_len = arg_len;
|
|
input_pos = 0;
|
|
bytes_read = 0;
|
|
}
|
|
|
|
void SerializationFormat::EndRead()
|
|
{
|
|
input = 0;
|
|
}
|
|
|
|
void SerializationFormat::StartWrite()
|
|
{
|
|
if ( output && output_size > INITIAL_SIZE )
|
|
{
|
|
delete [] output;
|
|
output = 0;
|
|
}
|
|
|
|
if ( ! output )
|
|
{
|
|
output = new char[INITIAL_SIZE];
|
|
output_size = INITIAL_SIZE;
|
|
}
|
|
|
|
output_pos = 0;
|
|
bytes_written = 0;
|
|
}
|
|
|
|
uint32 SerializationFormat::EndWrite(char** data)
|
|
{
|
|
*data = new char[output_pos];
|
|
memcpy(*data, output, output_pos);
|
|
return output_pos;
|
|
}
|
|
|
|
bool SerializationFormat::ReadData(void* b, size_t count)
|
|
{
|
|
if ( input_pos + count > input_len )
|
|
{
|
|
reporter->Error("data underflow during read in binary format");
|
|
abort();
|
|
return false;
|
|
}
|
|
|
|
memcpy(b, input + input_pos, count);
|
|
input_pos += count;
|
|
bytes_read += count;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool SerializationFormat::WriteData(const void* b, size_t count)
|
|
{
|
|
// Increase buffer if necessary.
|
|
while ( output_pos + count > output_size )
|
|
{
|
|
output_size = output_pos + count + INITIAL_SIZE;
|
|
char* tmp = new char[output_size];
|
|
memcpy(tmp, output, output_pos);
|
|
delete [] output;
|
|
output = tmp;
|
|
}
|
|
|
|
memcpy(output + output_pos, b, count);
|
|
output_pos += count;
|
|
bytes_written += count;
|
|
|
|
return true;
|
|
}
|
|
|
|
BinarySerializationFormat::BinarySerializationFormat()
|
|
{
|
|
}
|
|
|
|
BinarySerializationFormat::~BinarySerializationFormat()
|
|
{
|
|
}
|
|
|
|
bool BinarySerializationFormat::Read(int* v, const char* tag)
|
|
{
|
|
uint32 tmp;
|
|
if ( ! ReadData(&tmp, sizeof(tmp)) )
|
|
return false;
|
|
|
|
*v = (int) ntohl(tmp);
|
|
DBG_LOG(DBG_SERIAL, "Read int %d [%s]", *v, tag);
|
|
return true;
|
|
}
|
|
|
|
bool BinarySerializationFormat::Read(uint8* v, const char* tag)
|
|
{
|
|
if ( ! ReadData(v, sizeof(*v)) )
|
|
return false;
|
|
|
|
*v = ntohs(*v);
|
|
DBG_LOG(DBG_SERIAL, "Read uint8 %hu [%s]", *v, tag);
|
|
return true;
|
|
}
|
|
|
|
bool BinarySerializationFormat::Read(uint16* v, const char* tag)
|
|
{
|
|
if ( ! ReadData(v, sizeof(*v)) )
|
|
return false;
|
|
|
|
*v = ntohs(*v);
|
|
DBG_LOG(DBG_SERIAL, "Read uint16 %hu [%s]", *v, tag);
|
|
return true;
|
|
}
|
|
|
|
bool BinarySerializationFormat::Read(uint32* v, const char* tag)
|
|
{
|
|
if ( ! ReadData(v, sizeof(*v)) )
|
|
return false;
|
|
|
|
*v = ntohl(*v);
|
|
DBG_LOG(DBG_SERIAL, "Read uint32 %ld [%s]", *v, tag);
|
|
return true;
|
|
}
|
|
|
|
|
|
bool BinarySerializationFormat::Read(int64* v, const char* tag)
|
|
{
|
|
uint32 x[2];
|
|
if ( ! ReadData(x, sizeof(x)) )
|
|
return false;
|
|
|
|
*v = ((int64(ntohl(x[0]))) << 32) | ntohl(x[1]);
|
|
DBG_LOG(DBG_SERIAL, "Read int64 %lld [%s]", *v, tag);
|
|
return true;
|
|
}
|
|
|
|
bool BinarySerializationFormat::Read(uint64* v, const char* tag)
|
|
{
|
|
uint32 x[2];
|
|
if ( ! ReadData(x, sizeof(x)) )
|
|
return false;
|
|
|
|
*v = ((uint64(ntohl(x[0]))) << 32) | ntohl(x[1]);
|
|
DBG_LOG(DBG_SERIAL, "Read uint64 %llu [%s]", *v, tag);
|
|
return true;
|
|
}
|
|
|
|
bool BinarySerializationFormat::Read(bool* v, const char* tag)
|
|
{
|
|
char c;
|
|
if ( ! ReadData(&c, 1) )
|
|
return false;
|
|
|
|
*v = c == '\1' ? true : false;
|
|
DBG_LOG(DBG_SERIAL, "Read bool %s [%s]", *v ? "true" : "false", tag);
|
|
return true;
|
|
}
|
|
|
|
bool BinarySerializationFormat::Read(double* d, const char* tag)
|
|
{
|
|
if ( ! ReadData(d, sizeof(*d)) )
|
|
return false;
|
|
|
|
*d = ntohd(*d);
|
|
DBG_LOG(DBG_SERIAL, "Read double %.6f [%s]", *d, tag);
|
|
return true;
|
|
}
|
|
|
|
bool BinarySerializationFormat::Read(char* v, const char* tag)
|
|
{
|
|
bool ret = ReadData(v, 1);
|
|
DBG_LOG(DBG_SERIAL, "Read char %s [%s]", fmt_bytes(v, 1), tag);
|
|
return ret;
|
|
}
|
|
|
|
bool BinarySerializationFormat::Read(char** str, int* len, const char* tag)
|
|
{
|
|
int l;
|
|
if ( ! ReadData(&l, sizeof(l)) )
|
|
return false;
|
|
|
|
l = ntohl(l);
|
|
char* s = new char[l + 1];
|
|
|
|
if ( ! ReadData(s, l) )
|
|
{
|
|
delete [] s;
|
|
*str = 0;
|
|
return false;
|
|
}
|
|
|
|
if ( len )
|
|
*len = l;
|
|
else
|
|
{
|
|
// If len isn't given, make sure that the string
|
|
// doesn't contain any nulls.
|
|
for ( int i = 0; i < l; i++ )
|
|
if ( ! s[i] )
|
|
{
|
|
reporter->Error("binary Format: string contains null; replaced by '_'");
|
|
s[i] = '_';
|
|
}
|
|
}
|
|
|
|
s[l] = '\0';
|
|
|
|
*str = s;
|
|
|
|
DBG_LOG(DBG_SERIAL, "Read %d bytes |%s| [%s]", l, fmt_bytes(*str, l), tag);
|
|
return true;
|
|
}
|
|
|
|
bool BinarySerializationFormat::Read(string* v, const char* tag)
|
|
{
|
|
char* buffer;
|
|
int len;
|
|
|
|
if ( ! Read(&buffer, &len, tag) )
|
|
return false;
|
|
|
|
*v = string(buffer, len);
|
|
|
|
delete [] buffer;
|
|
return true;
|
|
}
|
|
|
|
bool BinarySerializationFormat::Read(IPAddr* addr, const char* tag)
|
|
{
|
|
int n = 0;
|
|
if ( ! Read(&n, "addr-len") )
|
|
return false;
|
|
|
|
if ( n != 1 && n != 4 )
|
|
return false;
|
|
|
|
uint32_t raw[4];
|
|
|
|
for ( int i = 0; i < n; ++i )
|
|
{
|
|
if ( ! Read(&raw[i], "addr-part") )
|
|
return false;
|
|
|
|
raw[i] = htonl(raw[i]);
|
|
}
|
|
|
|
if ( n == 1 )
|
|
*addr = IPAddr(IPv4, raw, IPAddr::Network);
|
|
else
|
|
*addr = IPAddr(IPv6, raw, IPAddr::Network);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool BinarySerializationFormat::Read(IPPrefix* prefix, const char* tag)
|
|
{
|
|
IPAddr addr;
|
|
int len;
|
|
|
|
if ( ! (Read(&addr, "prefix") && Read(&len, "width")) )
|
|
return false;
|
|
|
|
*prefix = IPPrefix(addr, len);
|
|
return true;
|
|
}
|
|
|
|
bool BinarySerializationFormat::Read(struct in_addr* addr, const char* tag)
|
|
{
|
|
uint32_t* bytes = (uint32_t*) &addr->s_addr;
|
|
|
|
if ( ! Read(&bytes[0], "addr4") )
|
|
return false;
|
|
|
|
bytes[0] = htonl(bytes[0]);
|
|
return true;
|
|
}
|
|
|
|
bool BinarySerializationFormat::Read(struct in6_addr* addr, const char* tag)
|
|
{
|
|
uint32_t* bytes = (uint32_t*) &addr->s6_addr;
|
|
|
|
for ( int i = 0; i < 4; ++i )
|
|
{
|
|
if ( ! Read(&bytes[i], "addr6-part") )
|
|
return false;
|
|
|
|
bytes[i] = htonl(bytes[i]);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool BinarySerializationFormat::Write(char v, const char* tag)
|
|
{
|
|
DBG_LOG(DBG_SERIAL, "Write char %s [%s]", fmt_bytes(&v, 1), tag);
|
|
return WriteData(&v, 1);
|
|
}
|
|
|
|
bool BinarySerializationFormat::Write(uint8 v, const char* tag)
|
|
{
|
|
DBG_LOG(DBG_SERIAL, "Write uint8 %hu [%s]", v, tag);
|
|
v = htons(v);
|
|
return WriteData(&v, sizeof(v));
|
|
}
|
|
|
|
bool BinarySerializationFormat::Write(uint16 v, const char* tag)
|
|
{
|
|
DBG_LOG(DBG_SERIAL, "Write uint16 %hu [%s]", v, tag);
|
|
v = htons(v);
|
|
return WriteData(&v, sizeof(v));
|
|
}
|
|
|
|
bool BinarySerializationFormat::Write(uint32 v, const char* tag)
|
|
{
|
|
DBG_LOG(DBG_SERIAL, "Write uint32 %ld [%s]", v, tag);
|
|
v = htonl(v);
|
|
return WriteData(&v, sizeof(v));
|
|
}
|
|
|
|
bool BinarySerializationFormat::Write(int v, const char* tag)
|
|
{
|
|
DBG_LOG(DBG_SERIAL, "Write int %d [%s]", v, tag);
|
|
uint32 tmp = htonl((uint32) v);
|
|
return WriteData(&tmp, sizeof(tmp));
|
|
}
|
|
|
|
bool BinarySerializationFormat::Write(uint64 v, const char* tag)
|
|
{
|
|
DBG_LOG(DBG_SERIAL, "Write uint64 %lu [%s]", v, tag);
|
|
uint32 x[2];
|
|
x[0] = htonl(v >> 32);
|
|
x[1] = htonl(v & 0xffffffff);
|
|
return WriteData(x, sizeof(x));
|
|
}
|
|
|
|
bool BinarySerializationFormat::Write(int64 v, const char* tag)
|
|
{
|
|
DBG_LOG(DBG_SERIAL, "Write int64 %ld [%s]", v, tag);
|
|
uint32 x[2];
|
|
x[0] = htonl(v >> 32);
|
|
x[1] = htonl(v & 0xffffffff);
|
|
return WriteData(x, sizeof(x));
|
|
}
|
|
|
|
bool BinarySerializationFormat::Write(double d, const char* tag)
|
|
{
|
|
DBG_LOG(DBG_SERIAL, "Write double %.6f [%s]", d, tag);
|
|
d = htond(d);
|
|
return WriteData(&d, sizeof(d));
|
|
}
|
|
|
|
bool BinarySerializationFormat::Write(bool v, const char* tag)
|
|
{
|
|
DBG_LOG(DBG_SERIAL, "Write bool %s [%s]", v ? "true" : "false", tag);
|
|
char c = v ? '\1' : '\0';
|
|
return WriteData(&c, 1);
|
|
}
|
|
|
|
bool BinarySerializationFormat::Write(const char* s, const char* tag)
|
|
{
|
|
return Write(s, strlen(s), tag);
|
|
}
|
|
|
|
bool BinarySerializationFormat::Write(const string& s, const char* tag)
|
|
{
|
|
return Write(s.data(), s.size(), tag);
|
|
}
|
|
|
|
bool BinarySerializationFormat::Write(const IPAddr& addr, const char* tag)
|
|
{
|
|
const uint32_t* raw;
|
|
int n = addr.GetBytes(&raw);
|
|
|
|
assert(n == 1 || n == 4);
|
|
|
|
if ( ! Write(n, "addr-len") )
|
|
return false;
|
|
|
|
for ( int i = 0; i < n; ++i )
|
|
{
|
|
if ( ! Write(ntohl(raw[i]), "addr-part") )
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool BinarySerializationFormat::Write(const IPPrefix& prefix, const char* tag)
|
|
{
|
|
return Write(prefix.Prefix(), "prefix") && Write(prefix.Length(), "width");
|
|
}
|
|
|
|
bool BinarySerializationFormat::Write(const struct in_addr& addr, const char* tag)
|
|
{
|
|
const uint32_t* bytes = (uint32_t*) &addr.s_addr;
|
|
|
|
if ( ! Write(ntohl(bytes[0]), "addr4") )
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool BinarySerializationFormat::Write(const struct in6_addr& addr, const char* tag)
|
|
{
|
|
const uint32_t* bytes = (uint32_t*) &addr.s6_addr;
|
|
|
|
for ( int i = 0; i < 4; ++i )
|
|
{
|
|
if ( ! Write(ntohl(bytes[i]), "addr6-part") )
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool BinarySerializationFormat::WriteOpenTag(const char* tag)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
bool BinarySerializationFormat::WriteCloseTag(const char* tag)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
bool BinarySerializationFormat::WriteSeparator()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
bool BinarySerializationFormat::Write(const char* buf, int len, const char* tag)
|
|
{
|
|
DBG_LOG(DBG_SERIAL, "Write bytes |%s| [%s]", fmt_bytes(buf, len), tag);
|
|
uint32 l = htonl(len);
|
|
return WriteData(&l, sizeof(l)) && WriteData(buf, len);
|
|
}
|
|
|
|
XMLSerializationFormat::XMLSerializationFormat()
|
|
{
|
|
}
|
|
|
|
XMLSerializationFormat::~XMLSerializationFormat()
|
|
{
|
|
}
|
|
|
|
bool XMLSerializationFormat::Read(int* v, const char* tag)
|
|
{
|
|
reporter->InternalError("no reading of xml");
|
|
return false;
|
|
}
|
|
|
|
bool XMLSerializationFormat::Read(uint8* v, const char* tag)
|
|
{
|
|
reporter->InternalError("no reading of xml");
|
|
return false;
|
|
}
|
|
|
|
bool XMLSerializationFormat::Read(uint16* v, const char* tag)
|
|
{
|
|
reporter->InternalError("no reading of xml");
|
|
return false;
|
|
}
|
|
|
|
bool XMLSerializationFormat::Read(uint32* v, const char* tag)
|
|
{
|
|
reporter->InternalError("no reading of xml");
|
|
return false;
|
|
}
|
|
|
|
bool XMLSerializationFormat::Read(int64* v, const char* tag)
|
|
{
|
|
reporter->InternalError("no reading of xml");
|
|
return false;
|
|
}
|
|
|
|
bool XMLSerializationFormat::Read(uint64* v, const char* tag)
|
|
{
|
|
reporter->InternalError("no reading of xml");
|
|
return false;
|
|
}
|
|
|
|
bool XMLSerializationFormat::Read(bool* v, const char* tag)
|
|
{
|
|
reporter->InternalError("no reading of xml");
|
|
return false;
|
|
}
|
|
|
|
bool XMLSerializationFormat::Read(double* d, const char* tag)
|
|
{
|
|
reporter->InternalError("no reading of xml");
|
|
return false;
|
|
}
|
|
|
|
bool XMLSerializationFormat::Read(char* v, const char* tag)
|
|
{
|
|
reporter->InternalError("no reading of xml");
|
|
return false;
|
|
}
|
|
|
|
bool XMLSerializationFormat::Read(char** str, int* len, const char* tag)
|
|
{
|
|
reporter->InternalError("no reading of xml");
|
|
return false;
|
|
}
|
|
|
|
bool XMLSerializationFormat::Read(string* s, const char* tag)
|
|
{
|
|
reporter->InternalError("no reading of xml");
|
|
return false;
|
|
}
|
|
|
|
bool XMLSerializationFormat::Read(IPAddr* addr, const char* tag)
|
|
{
|
|
reporter->InternalError("no reading of xml");
|
|
return false;
|
|
}
|
|
|
|
bool XMLSerializationFormat::Read(IPPrefix* prefix, const char* tag)
|
|
{
|
|
reporter->InternalError("no reading of xml");
|
|
return false;
|
|
}
|
|
|
|
bool XMLSerializationFormat::Read(struct in_addr* addr, const char* tag)
|
|
{
|
|
reporter->InternalError("no reading of xml");
|
|
return false;
|
|
}
|
|
|
|
bool XMLSerializationFormat::Read(struct in6_addr* addr, const char* tag)
|
|
{
|
|
reporter->InternalError("no reading of xml");
|
|
return false;
|
|
}
|
|
|
|
bool XMLSerializationFormat::Write(char v, const char* tag)
|
|
{
|
|
return WriteElem(tag, "char", &v, 1);
|
|
}
|
|
|
|
bool XMLSerializationFormat::Write(uint8 v, const char* tag)
|
|
{
|
|
const char* tmp = fmt("%" PRIu8, v);
|
|
return WriteElem(tag, "uint8", tmp, strlen(tmp));
|
|
}
|
|
|
|
|
|
bool XMLSerializationFormat::Write(uint16 v, const char* tag)
|
|
{
|
|
const char* tmp = fmt("%" PRIu16, v);
|
|
return WriteElem(tag, "uint16", tmp, strlen(tmp));
|
|
}
|
|
|
|
bool XMLSerializationFormat::Write(uint32 v, const char* tag)
|
|
{
|
|
const char* tmp = fmt("%"PRIu32, v);
|
|
return WriteElem(tag, "uint32", tmp, strlen(tmp));
|
|
}
|
|
|
|
bool XMLSerializationFormat::Write(uint64 v, const char* tag)
|
|
{
|
|
const char* tmp = fmt("%"PRIu64, v);
|
|
return WriteElem(tag, "uint64", tmp, strlen(tmp));
|
|
}
|
|
|
|
bool XMLSerializationFormat::Write(int64 v, const char* tag)
|
|
{
|
|
const char* tmp = fmt("%"PRId64, v);
|
|
return WriteElem(tag, "int64", tmp, strlen(tmp));
|
|
}
|
|
|
|
bool XMLSerializationFormat::Write(int v, const char* tag)
|
|
{
|
|
const char* tmp = fmt("%d", v);
|
|
return WriteElem(tag, "int", tmp, strlen(tmp));
|
|
}
|
|
|
|
bool XMLSerializationFormat::Write(double d, const char* tag)
|
|
{
|
|
const char* tmp = fmt("%f", d);
|
|
return WriteElem(tag, "double", tmp, strlen(tmp));
|
|
}
|
|
|
|
bool XMLSerializationFormat::Write(bool v, const char* tag)
|
|
{
|
|
if ( v )
|
|
return WriteElem(tag, "bool", "true", 4);
|
|
else
|
|
return WriteElem(tag, "bool", "false", 5);
|
|
}
|
|
|
|
bool XMLSerializationFormat::Write(const char* s, const char* tag)
|
|
{
|
|
return WriteElem(tag, "string", s, strlen(s));
|
|
}
|
|
|
|
bool XMLSerializationFormat::Write(const string& s, const char* tag)
|
|
{
|
|
return WriteElem(tag, "string", s.data(), s.size());
|
|
}
|
|
|
|
bool XMLSerializationFormat::WriteOpenTag(const char* tag)
|
|
{
|
|
return WriteData("<", 1) && WriteData(tag, strlen(tag) && WriteData(">", 1));
|
|
}
|
|
|
|
bool XMLSerializationFormat::WriteCloseTag(const char* tag)
|
|
{
|
|
return WriteData("</", 2) && WriteData(tag, strlen(tag))
|
|
&& WriteData(">", 1);
|
|
}
|
|
|
|
bool XMLSerializationFormat::WriteSeparator()
|
|
{
|
|
return WriteData("\n", 1);
|
|
}
|
|
|
|
bool XMLSerializationFormat::Write(const char* buf, int len, const char* tag)
|
|
{
|
|
return WriteElem(tag, "string", buf, len);
|
|
}
|
|
|
|
bool XMLSerializationFormat::Write(const IPAddr& addr, const char* tag)
|
|
{
|
|
reporter->InternalError("XML output of addresses not implemented");
|
|
return false;
|
|
}
|
|
|
|
bool XMLSerializationFormat::Write(const IPPrefix& prefix, const char* tag)
|
|
{
|
|
reporter->InternalError("XML output of prefixes not implemented");
|
|
return false;
|
|
}
|
|
|
|
bool XMLSerializationFormat::Write(const struct in_addr& addr, const char* tag)
|
|
{
|
|
reporter->InternalError("XML output of in_addr not implemented");
|
|
return false;
|
|
}
|
|
|
|
bool XMLSerializationFormat::Write(const struct in6_addr& addr, const char* tag)
|
|
{
|
|
reporter->InternalError("XML output of in6_addr not implemented");
|
|
return false;
|
|
}
|
|
|
|
bool XMLSerializationFormat::WriteEncodedString(const char* s, int len)
|
|
{
|
|
while ( len-- )
|
|
{
|
|
int success = false;
|
|
if ( ! isprint(*s) )
|
|
{
|
|
const char* tmp = fmt("%.4x", (int)* s++);
|
|
success = WriteData("&#x", 3) && WriteData(tmp, 4) &&
|
|
WriteData(";", 1);
|
|
}
|
|
else
|
|
{
|
|
switch ( *s ) {
|
|
case '"':
|
|
success = WriteData(""", 6);
|
|
break;
|
|
case '&':
|
|
success = WriteData("&", 5);
|
|
break;
|
|
case '<':
|
|
success = WriteData("<", 4);
|
|
break;
|
|
case '>':
|
|
success = WriteData(">", 4);
|
|
break;
|
|
default:
|
|
success = WriteData(s, 1);
|
|
}
|
|
|
|
if ( ! success )
|
|
return false;
|
|
|
|
++s;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool XMLSerializationFormat::WriteElem(const char* tag, const char* type,
|
|
const char* content, int len)
|
|
{
|
|
if ( ! tag )
|
|
return true;
|
|
|
|
return WriteData("<", 1) &&
|
|
WriteData(tag, strlen(tag)) &&
|
|
#if 0
|
|
WriteData(" type=\"", 7) &&
|
|
WriteData(type, strlen(type)) &&
|
|
WriteData("\"", 1) &&
|
|
#endif
|
|
WriteData(">", 1) &&
|
|
WriteEncodedString(content, len) &&
|
|
WriteData("</", 2) &&
|
|
WriteData(tag, strlen(tag)) &&
|
|
WriteData(">", 1);
|
|
}
|