Merge remote-tracking branch 'origin/master' into topic/icmp6

Conflicts:
	src/ICMP.cc
	src/net_util.cc
	src/net_util.h
This commit is contained in:
Daniel Thayer 2012-02-20 17:18:55 -06:00
commit 8e32e89ce4
104 changed files with 2152 additions and 1956 deletions

View file

@ -17,7 +17,7 @@ ARP_Analyzer::~ARP_Analyzer()
{
}
bool ARP_Analyzer::IsARP(const u_char* pkt, int hdr_size) const
bool ARP_Analyzer::IsARP(const u_char* pkt, int hdr_size)
{
unsigned short network_protocol =
*(unsigned short*) (pkt + hdr_size - 2);

View file

@ -31,9 +31,6 @@ public:
ARP_Analyzer();
virtual ~ARP_Analyzer();
// Whether a packet is of interest for ARP analysis.
bool IsARP(const u_char* pkt, int hdr_size) const;
void NextPacket(double t, const struct pcap_pkthdr* hdr,
const u_char* const pkt, int hdr_size);
@ -41,6 +38,10 @@ public:
void RREvent(EventHandlerPtr e, const u_char* src, const u_char* dst,
const char* spa, const char* sha,
const char* tpa, const char* tha);
// Whether a packet is of interest for ARP analysis.
static bool IsARP(const u_char* pkt, int hdr_size);
protected:
AddrVal* ConstructAddrVal(const void* addr);
StringVal* EthAddrToStr(const u_char* addr);

View file

@ -153,7 +153,9 @@ void AnonymizeIPAddr_A50::init()
int AnonymizeIPAddr_A50::PreservePrefix(ipaddr32_t input, int num_bits)
{
DEBUG_MSG("%s/%d\n", dotted_addr(input), num_bits);
DEBUG_MSG("%s/%d\n",
IPAddr(IPAddr::IPv4, &input, IPAddr::Network).AsString().c_str(),
num_bits);
if ( ! before_anonymization )
{

View file

@ -331,6 +331,7 @@ set(bro_SRCS
IntSet.cc
InterConn.cc
IOSource.cc
IPAddr.cc
IRC.cc
List.cc
Reporter.cc

View file

@ -107,40 +107,28 @@ char* CompositeHash::SingleValHash(int type_check, char* kp0,
case TYPE_INTERNAL_ADDR:
{
// Use uint32 instead of int, because 'int' is not
// guaranteed to be 32-bit.
uint32* kp = AlignAndPadType<uint32>(kp0);
#ifdef BROv6
const addr_type av = v->AsAddr();
kp[0] = av[0];
kp[1] = av[1];
kp[2] = av[2];
kp[3] = av[3];
uint32 bytes[4];
v->AsAddr().CopyIPv6(bytes);
kp[0] = bytes[0];
kp[1] = bytes[1];
kp[2] = bytes[2];
kp[3] = bytes[3];
kp1 = reinterpret_cast<char*>(kp+4);
#else
*kp = v->AsAddr();
kp1 = reinterpret_cast<char*>(kp+1);
#endif
}
break;
case TYPE_INTERNAL_SUBNET:
{
uint32* kp = AlignAndPadType<uint32>(kp0);
#ifdef BROv6
const subnet_type* sv = v->AsSubNet();
kp[0] = sv->net[0];
kp[1] = sv->net[1];
kp[2] = sv->net[2];
kp[3] = sv->net[3];
kp[4] = sv->width;
uint32 bytes[4];
v->AsSubNet().Prefix().CopyIPv6(bytes);
kp[0] = bytes[0];
kp[1] = bytes[1];
kp[2] = bytes[2];
kp[3] = bytes[3];
kp[4] = v->AsSubNet().Length();
kp1 = reinterpret_cast<char*>(kp+5);
#else
const subnet_type* sv = v->AsSubNet();
kp[0] = sv->net;
kp[1] = sv->width;
kp1 = reinterpret_cast<char*>(kp+2);
#endif
}
break;
@ -358,26 +346,25 @@ HashKey* CompositeHash::ComputeSingletonHash(const Val* v, int type_check) const
if ( type_check && v->Type()->InternalType() != singleton_tag )
return 0;
uint32 tmp_addr;
switch ( singleton_tag ) {
case TYPE_INTERNAL_INT:
case TYPE_INTERNAL_UNSIGNED:
return new HashKey(v->ForceAsInt());
case TYPE_INTERNAL_ADDR:
#ifdef BROv6
return new HashKey(v->AsAddr(), 4);
#else
return new HashKey(v->AsAddr());
#endif
{
uint32 bytes[4];
v->AsAddr().CopyIPv6(bytes);
return new HashKey((void*)bytes, 4 * sizeof(uint32));
}
case TYPE_INTERNAL_SUBNET:
#ifdef BROv6
return new HashKey((const uint32*) v->AsSubNet(), 5);
#else
return new HashKey((const uint32*) v->AsSubNet(), 2);
#endif
{
uint32 bytes[5];
v->AsSubNet().Prefix().CopyIPv6(bytes);
bytes[4] = v->AsSubNet().Length();
return new HashKey((void*)bytes, 5 * sizeof(uint32));
}
case TYPE_INTERNAL_DOUBLE:
return new HashKey(v->InternalDouble());
@ -425,22 +412,13 @@ int CompositeHash::SingleTypeKeySize(BroType* bt, const Val* v,
break;
case TYPE_INTERNAL_ADDR:
#ifdef BROv6
sz = SizeAlign(sz, sizeof(uint32));
sz += sizeof(uint32) * 3; // to make a total of 4 words
#else
sz = SizeAlign(sz, sizeof(uint32));
#endif
break;
case TYPE_INTERNAL_SUBNET:
#ifdef BROv6
sz = SizeAlign(sz, sizeof(uint32));
sz += sizeof(uint32) * 4; // to make a total of 5 words
#else
sz = SizeAlign(sz, sizeof(uint32));
sz += sizeof(uint32); // make room for width
#endif
break;
case TYPE_INTERNAL_DOUBLE:
@ -748,16 +726,13 @@ const char* CompositeHash::RecoverOneVal(const HashKey* k, const char* kp0,
case TYPE_INTERNAL_ADDR:
{
const uint32* const kp = AlignType<uint32>(kp0);
#ifdef BROv6
const_addr_type addr_val = kp;
kp1 = reinterpret_cast<const char*>(kp+4);
#else
const_addr_type addr_val = *kp;
kp1 = reinterpret_cast<const char*>(kp+1);
#endif
IPAddr addr(IPAddr::IPv6, kp, IPAddr::Network);
switch ( tag ) {
case TYPE_ADDR:
pval = new AddrVal(addr_val);
pval = new AddrVal(addr);
break;
default:
@ -770,12 +745,9 @@ const char* CompositeHash::RecoverOneVal(const HashKey* k, const char* kp0,
case TYPE_INTERNAL_SUBNET:
{
const subnet_type* const kp =
reinterpret_cast<const subnet_type*>(
AlignType<uint32>(kp0));
kp1 = reinterpret_cast<const char*>(kp+1);
pval = new SubNetVal(kp->net, kp->width);
const uint32* const kp = AlignType<uint32>(kp0);
kp1 = reinterpret_cast<const char*>(kp+5);
pval = new SubNetVal(kp, kp[4]);
}
break;

View file

@ -24,15 +24,15 @@ HashKey* ConnID::BuildConnKey() const
if ( is_one_way ||
addr_port_canon_lt(src_addr, src_port, dst_addr, dst_port) )
{
copy_addr(src_addr, key.ip1);
copy_addr(dst_addr, key.ip2);
src_addr.CopyIPv6(key.ip1);
dst_addr.CopyIPv6(key.ip2);
key.port1 = src_port;
key.port2 = dst_port;
}
else
{
copy_addr(dst_addr, key.ip1);
copy_addr(src_addr, key.ip2);
dst_addr.CopyIPv6(key.ip1);
src_addr.CopyIPv6(key.ip2);
key.port1 = dst_port;
key.port2 = src_port;
}
@ -143,8 +143,8 @@ Connection::Connection(NetSessions* s, HashKey* k, double t, const ConnID* id)
key = k;
start_time = last_time = t;
copy_addr(id->src_addr, orig_addr);
copy_addr(id->dst_addr, resp_addr);
orig_addr = id->src_addr;
resp_addr = id->dst_addr;
orig_port = id->src_port;
resp_port = id->dst_port;
proto = TRANSPORT_UNKNOWN;
@ -521,7 +521,7 @@ Val* Connection::BuildVersionVal(const char* s, int len)
return sw;
}
int Connection::VersionFoundEvent(const uint32* addr, const char* s, int len,
int Connection::VersionFoundEvent(const IPAddr& addr, const char* s, int len,
Analyzer* analyzer)
{
if ( ! software_version_found && ! software_parse_error )
@ -559,7 +559,7 @@ int Connection::VersionFoundEvent(const uint32* addr, const char* s, int len,
return 1;
}
int Connection::UnparsedVersionFoundEvent(const uint32* addr,
int Connection::UnparsedVersionFoundEvent(const IPAddr& addr,
const char* full, int len, Analyzer* analyzer)
{
// Skip leading white space.
@ -693,10 +693,9 @@ TimerMgr* Connection::GetTimerMgr() const
void Connection::FlipRoles()
{
uint32 tmp_addr[NUM_ADDR_WORDS];
copy_addr(resp_addr, tmp_addr);
copy_addr(orig_addr, resp_addr);
copy_addr(tmp_addr, orig_addr);
IPAddr tmp_addr = resp_addr;
orig_addr = resp_addr;
resp_addr = tmp_addr;
uint32 tmp_port = resp_port;
resp_port = orig_port;
@ -752,14 +751,14 @@ void Connection::Describe(ODesc* d) const
}
d->SP();
d->Add(dotted_addr(orig_addr));
d->Add(orig_addr);
d->Add(":");
d->Add(ntohs(orig_port));
d->SP();
d->AddSP("->");
d->Add(dotted_addr(resp_addr));
d->Add(resp_addr);
d->Add(":");
d->Add(ntohs(resp_port));
@ -782,9 +781,8 @@ bool Connection::DoSerialize(SerialInfo* info) const
// First we write the members which are needed to
// create the HashKey.
for ( int j = 0; j < NUM_ADDR_WORDS; ++j )
if ( ! SERIALIZE(orig_addr[j]) || ! SERIALIZE(resp_addr[j]) )
return false;
if ( ! SERIALIZE(orig_addr) || ! SERIALIZE(resp_addr) )
return false;
if ( ! SERIALIZE(orig_port) || ! SERIALIZE(resp_port) )
return false;
@ -830,14 +828,14 @@ bool Connection::DoUnserialize(UnserialInfo* info)
// Build the hash key first. Some of the recursive *::Unserialize()
// functions may need it.
for ( int i = 0; i < NUM_ADDR_WORDS; ++i )
if ( ! UNSERIALIZE(&orig_addr[i]) || ! UNSERIALIZE(&resp_addr[i]) )
goto error;
ConnID id;
if ( ! UNSERIALIZE(&orig_addr) || ! UNSERIALIZE(&resp_addr) )
goto error;
if ( ! UNSERIALIZE(&orig_port) || ! UNSERIALIZE(&resp_port) )
goto error;
ConnID id;
id.src_addr = orig_addr;
id.dst_addr = resp_addr;
// This doesn't work for ICMP. But I guess this is not really important.

View file

@ -12,6 +12,7 @@
#include "PersistenceSerializer.h"
#include "RuleMatcher.h"
#include "AnalyzerTags.h"
#include "IPAddr.h"
class Connection;
class ConnectionTimer;
@ -32,8 +33,8 @@ typedef enum {
typedef void (Connection::*timer_func)(double t);
struct ConnID {
const uint32* src_addr;
const uint32* dst_addr;
IPAddr src_addr;
IPAddr dst_addr;
uint32 src_port;
uint32 dst_port;
bool is_one_way; // if true, don't canonicalize
@ -49,17 +50,20 @@ struct ConnID {
// The structure used internally for hashing.
struct Key {
uint32 ip1[NUM_ADDR_WORDS];
uint32 ip2[NUM_ADDR_WORDS];
uint32 ip1[4];
uint32 ip2[4];
uint16 port1;
uint16 port2;
};
};
static inline int addr_port_canon_lt(const uint32* a1, uint32 p1,
const uint32* a2, uint32 p2)
static inline int addr_port_canon_lt(const IPAddr& addr1, uint32 p1,
const IPAddr& addr2, uint32 p2)
{
#ifdef BROv6
uint32 a1[4];
uint32 a2[4];
addr1.CopyIPv6(a1);
addr2.CopyIPv6(a2);
// Because it's a canonical ordering, not a strict ordering,
// we can choose to give more weight to the least significant
// word than to the most significant word. This matters
@ -75,9 +79,6 @@ static inline int addr_port_canon_lt(const uint32* a1, uint32 p1,
(a1[0] < a2[0] ||
(a1[0] == a2[0] &&
p1 < p2)))))));
#else
return *a1 < *a2 || (*a1 == *a2 && p1 < p2);
#endif
}
class Analyzer;
@ -119,8 +120,8 @@ public:
double LastTime() const { return last_time; }
void SetLastTime(double t) { last_time = t; }
const uint32* OrigAddr() const { return orig_addr; }
const uint32* RespAddr() const { return resp_addr; }
const IPAddr& OrigAddr() const { return orig_addr; }
const IPAddr& RespAddr() const { return resp_addr; }
uint32 OrigPort() const { return orig_port; }
uint32 RespPort() const { return resp_port; }
@ -185,11 +186,11 @@ public:
// Raises a software_version_found event based on the
// given string (returns false if it's not parseable).
int VersionFoundEvent(const uint32* addr, const char* s, int len,
int VersionFoundEvent(const IPAddr& addr, const char* s, int len,
Analyzer* analyzer = 0);
// Raises a software_unparsed_version_found event.
int UnparsedVersionFoundEvent(const uint32* addr,
int UnparsedVersionFoundEvent(const IPAddr& addr,
const char* full_descr, int len, Analyzer* analyzer);
void Event(EventHandlerPtr f, Analyzer* analyzer, const char* name = 0);
@ -325,8 +326,8 @@ protected:
TimerMgr::Tag* conn_timer_mgr;
timer_list timers;
uint32 orig_addr[NUM_ADDR_WORDS]; // in network order
uint32 resp_addr[NUM_ADDR_WORDS]; // in network order
IPAddr orig_addr;
IPAddr resp_addr;
uint32 orig_port, resp_port; // in network order
TransportProto proto;
double start_time, last_time;

View file

@ -235,7 +235,8 @@ Connection* ConnCompressor::NextPacket(double t, HashKey* key, const IP_Hdr* ip,
tc = FirstFromOrig(t, key, ip, tp);
}
else if ( addr_eq(ip->SrcAddr(), SrcAddr(pending)) &&
else if ( ip->SrcAddr() ==
IPAddr(IPAddr::IPv6, SrcAddr(pending), IPAddr::Network) &&
tp->th_sport == SrcPort(pending) )
// Another packet from originator.
tc = NextFromOrig(pending, t, key, ip, tp);
@ -507,8 +508,8 @@ Connection* ConnCompressor::Instantiate(HashKey* key, PendingConn* pending)
{
// Instantantiate a Connection.
ConnID conn_id;
conn_id.src_addr = SrcAddr(pending);
conn_id.dst_addr = DstAddr(pending);
conn_id.src_addr = IPAddr(IPAddr::IPv6, SrcAddr(pending), IPAddr::Network);
conn_id.dst_addr = IPAddr(IPAddr::IPv6, DstAddr(pending), IPAddr::Network);
conn_id.src_port = SrcPort(pending);
conn_id.dst_port = DstPort(pending);
@ -541,7 +542,7 @@ Connection* ConnCompressor::Instantiate(HashKey* key, PendingConn* pending)
sessions->BuildHeader(faked_pkt->IP4_Hdr()));
// NewConn() may have swapped originator and responder.
int is_orig = addr_eq(conn_id.src_addr, new_conn->OrigAddr()) &&
int is_orig = conn_id.src_addr == new_conn->OrigAddr() &&
conn_id.src_port == new_conn->OrigPort();
// Pass the faked packet to the connection.
@ -607,7 +608,8 @@ void ConnCompressor::PktHdrToPendingConn(double time, const HashKey* key,
memcpy(&c->key, key->Key(), key->Size());
c->hash = key->Hash();
c->ip1_is_src = addr_eq(c->key.ip1, ip->SrcAddr()) &&
IPAddr ip1(IPAddr::IPv6, c->key.ip1, IPAddr::Network);
c->ip1_is_src = ip1 == ip->SrcAddr() &&
c->key.port1 == tp->th_sport;
c->time = time;
c->window = tp->th_win;
@ -656,17 +658,28 @@ const IP_Hdr* ConnCompressor::PendingConnToPacket(const PendingConn* c)
tp->th_urp = 0;
}
// Note, do *not* use copy_addr() here. This is because we're
// copying to an IPv4 header, which has room for exactly and
// only an IPv4 address.
#ifdef BROv6
if ( ! is_v4_addr(c->key.ip1) || ! is_v4_addr(c->key.ip2) )
IPAddr ip1(IPAddr::IPv6, c->key.ip1, IPAddr::Network);
IPAddr ip2(IPAddr::IPv6, c->key.ip2, IPAddr::Network);
if ( ip1.GetFamily() == IPAddr::IPv6 ||
ip2.GetFamily() == IPAddr::IPv6 )
reporter->InternalError("IPv6 snuck into connection compressor");
#endif
*(uint32*) &ip->ip_src =
to_v4_addr(c->ip1_is_src ? c->key.ip1 : c->key.ip2);
*(uint32*) &ip->ip_dst =
to_v4_addr(c->ip1_is_src ? c->key.ip2 : c->key.ip1);
else
{
const uint32* src_bytes;
const uint32* dst_bytes;
if ( c->ip1_is_src )
{
ip1.GetBytes(&src_bytes);
ip2.GetBytes(&dst_bytes);
}
else
{
ip2.GetBytes(&src_bytes);
ip1.GetBytes(&dst_bytes);
}
memcpy(&ip->ip_src, src_bytes, sizeof(ip->ip_src));
memcpy(&ip->ip_dst, dst_bytes, sizeof(ip->ip_dst));
}
if ( c->ip1_is_src )
{

View file

@ -137,12 +137,12 @@ static bool is_mapped_dce_rpc_endpoint(const dce_rpc_endpoint_addr& addr)
bool is_mapped_dce_rpc_endpoint(const ConnID* id, TransportProto proto)
{
#ifdef BROv6
if ( ! is_v4_addr(id->dst_addr) )
if ( id->dst_addr.GetFamily() == IPAddr::IPv6 )
// TODO: Does the protocol support v6 addresses? #773
return false;
#endif
dce_rpc_endpoint_addr addr;
addr.addr = ntohl(to_v4_addr(id->dst_addr));
addr.addr = id->dst_addr;
addr.port = ntohs(id->dst_port);
addr.proto = proto;
@ -160,12 +160,7 @@ static void add_dce_rpc_endpoint(const dce_rpc_endpoint_addr& addr,
// of the dce_rpc_endpoints table.
// FIXME: Don't hard-code the timeout.
// Convert the address to a v4/v6 address (depending on how
// Bro was configured). This is all based on the address currently
// being a 32-bit host-order v4 address.
AddrVal a(htonl(addr.addr));
const addr_type at = a.AsAddr();
dpm->ExpectConnection(0, at, addr.port, addr.proto,
dpm->ExpectConnection(IPAddr(), addr.addr, addr.port, addr.proto,
AnalyzerTag::DCE_RPC, 5 * 60, 0);
}
@ -418,8 +413,8 @@ void DCE_RPC_Session::DeliverEpmapperMapResponse(
break;
case binpac::DCE_RPC_Simple::EPM_PROTOCOL_IP:
mapped.addr.addr =
floor->rhs()->data()->ip();
uint32 hostip = floor->rhs()->data()->ip();
mapped.addr.addr = IPAddr(IPAddr::IPv4, &hostip, IPAddr::Host);
break;
}
}
@ -433,7 +428,7 @@ void DCE_RPC_Session::DeliverEpmapperMapResponse(
vl->append(analyzer->BuildConnVal());
vl->append(new StringVal(mapped.uuid.to_string()));
vl->append(new PortVal(mapped.addr.port, mapped.addr.proto));
vl->append(new AddrVal(htonl(mapped.addr.addr)));
vl->append(new AddrVal(mapped.addr.addr));
analyzer->ConnectionEvent(epm_map_response, vl);
}

View file

@ -8,6 +8,7 @@
#include "NetVar.h"
#include "TCP.h"
#include "IPAddr.h"
#include "dce_rpc_simple_pac.h"
@ -34,19 +35,19 @@ const char* uuid_to_string(const u_char* uuid_data);
struct dce_rpc_endpoint_addr {
// All fields are in host byteorder.
uint32 addr;
IPAddr addr;
u_short port;
TransportProto proto;
dce_rpc_endpoint_addr()
{
addr = 0;
addr = IPAddr();
port = 0;
proto = TRANSPORT_UNKNOWN;
}
bool is_valid_addr() const
{ return addr != 0 && port != 0 && proto != TRANSPORT_UNKNOWN; }
{ return addr != IPAddr() && port != 0 && proto != TRANSPORT_UNKNOWN; }
bool operator<(dce_rpc_endpoint_addr const &e) const
{
@ -64,7 +65,7 @@ struct dce_rpc_endpoint_addr {
{
static char buf[128];
snprintf(buf, sizeof(buf), "%s/%d/%s",
dotted_addr(htonl(addr)), port,
addr.AsString().c_str(), port,
proto == TRANSPORT_TCP ? "tcp" :
(proto == TRANSPORT_UDP ? "udp" : "?"));

View file

@ -758,62 +758,37 @@ int DNS_Interpreter::ParseRR_A(DNS_MsgInfo* msg,
int DNS_Interpreter::ParseRR_AAAA(DNS_MsgInfo* msg,
const u_char*& data, int& len, int rdlength)
{
// We need to parse an IPv6 address, high-order byte first.
// ### Currently, we fake an A reply rather than an AAAA reply,
// since for the latter we won't be able to express the full
// address (unless Bro was compiled for IPv6 addresses). We do
// this fake by using just the bottom 4 bytes of the IPv6 address.
uint32 addr[4];
int i;
for ( i = 0; i < 4; ++i )
for ( int i = 0; i < 4; ++i )
{
addr[i] = ntohl(ExtractLong(data, len));
addr[i] = htonl(ExtractLong(data, len));
if ( len < 0 )
{
analyzer->Weird("DNS_AAAA_neg_length");
if ( msg->atype == TYPE_AAAA )
analyzer->Weird("DNS_AAAA_neg_length");
else
analyzer->Weird("DNS_A6_neg_length");
return 0;
}
}
// Currently, dns_AAAA_reply is treated like dns_A_reply, since
// IPv6 addresses are not generally processed. This needs to be
// fixed. ###
if ( dns_A_reply && ! msg->skip_event )
EventHandlerPtr event;
if ( msg->atype == TYPE_AAAA )
event = dns_AAAA_reply;
else
event = dns_A6_reply;
if ( event && ! msg->skip_event )
{
val_list* vl = new val_list;
vl->append(analyzer->BuildConnVal());
vl->append(msg->BuildHdrVal());
vl->append(msg->BuildAnswerVal());
vl->append(new AddrVal(htonl(addr[3])));
analyzer->ConnectionEvent(dns_A_reply, vl);
}
#if 0
alternative AAAA code from Chris
if ( dns_AAAA_reply && ! msg->skip_event )
{
val_list* vl = new val_list;
vl->append(analyzer->BuildConnVal());
vl->append(msg->BuildHdrVal());
vl->append(msg->BuildAnswerVal());
#ifdef BROv6
// FIXME: might need to htonl the addr first
vl->append(new AddrVal(addr));
#else
vl->append(new AddrVal((uint32)0x0000));
#endif
char addrstr[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, addr, addrstr, INET6_ADDRSTRLEN);
vl->append(new StringVal(addrstr));
analyzer->ConnectionEvent(dns_AAAA_reply, vl);
analyzer->ConnectionEvent(event, vl);
}
#endif
return 1;
}

View file

@ -46,13 +46,13 @@ extern int select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
class DNS_Mgr_Request {
public:
DNS_Mgr_Request(const char* h) { host = copy_string(h); addr = 0; }
DNS_Mgr_Request(uint32 a) { addr = a; host = 0; }
DNS_Mgr_Request(const char* h, int af) { host = copy_string(h); fam = af; }
DNS_Mgr_Request(const IPAddr& a) { addr = a; host = 0; fam = 0; }
~DNS_Mgr_Request() { delete [] host; }
// Returns nil if this was an address request.
const char* ReqHost() const { return host; }
uint32 ReqAddr() const { return addr; }
const IPAddr& ReqAddr() const { return addr; }
int MakeRequest(nb_dns_info* nb_dns);
int RequestPending() const { return request_pending; }
@ -61,8 +61,8 @@ public:
protected:
char* host; // if non-nil, this is a host request
uint32 addr;
uint32 ttl;
int fam; // address family query type for host requests
IPAddr addr;
int request_pending;
};
@ -75,15 +75,20 @@ int DNS_Mgr_Request::MakeRequest(nb_dns_info* nb_dns)
char err[NB_DNS_ERRSIZE];
if ( host )
return nb_dns_host_request(nb_dns, host, (void*) this, err) >= 0;
return nb_dns_host_request2(nb_dns, host, fam, (void*) this, err) >= 0;
else
return nb_dns_addr_request(nb_dns, addr, (void*) this, err) >= 0;
{
const uint32* bytes;
int len = addr.GetBytes(&bytes);
return nb_dns_addr_request2(nb_dns, (char*) bytes,
len == 1 ? AF_INET : AF_INET6, (void*) this, err) >= 0;
}
}
class DNS_Mapping {
public:
DNS_Mapping(const char* host, struct hostent* h, uint32 ttl);
DNS_Mapping(uint32 addr, struct hostent* h, uint32 ttl);
DNS_Mapping(const IPAddr& addr, struct hostent* h, uint32 ttl);
DNS_Mapping(FILE* f);
int NoMapping() const { return no_mapping; }
@ -93,9 +98,11 @@ public:
// Returns nil if this was an address request.
const char* ReqHost() const { return req_host; }
uint32 ReqAddr() const { return req_addr; }
const char* ReqStr() const
{ return req_host ? req_host : dotted_addr(ReqAddr()); }
IPAddr ReqAddr() const { return req_addr; }
string ReqStr() const
{
return req_host ? req_host : req_addr;
}
ListVal* Addrs();
TableVal* AddrsSet(); // addresses returned as a set
@ -109,7 +116,14 @@ public:
int Valid() const { return ! failed; }
bool Expired() const
{ return current_time() > (creation_time + req_ttl); }
{
if ( req_host && num_addrs == 0)
return false; // nothing to expire
return current_time() > (creation_time + req_ttl);
}
int Type() const { return map_type; }
protected:
friend class DNS_Mgr;
@ -121,7 +135,7 @@ protected:
int init_failed;
char* req_host;
uint32 req_addr;
IPAddr req_addr;
uint32 req_ttl;
int num_names;
@ -129,11 +143,12 @@ protected:
StringVal* host_val;
int num_addrs;
uint32* addrs;
IPAddr* addrs;
ListVal* addrs_val;
int failed;
double creation_time;
int map_type;
};
void DNS_Mgr_mapping_delete_func(void* v)
@ -154,14 +169,13 @@ DNS_Mapping::DNS_Mapping(const char* host, struct hostent* h, uint32 ttl)
{
Init(h);
req_host = copy_string(host);
req_addr = 0;
req_ttl = ttl;
if ( names && ! names[0] )
names[0] = copy_string(host);
}
DNS_Mapping::DNS_Mapping(uint32 addr, struct hostent* h, uint32 ttl)
DNS_Mapping::DNS_Mapping(const IPAddr& addr, struct hostent* h, uint32 ttl)
{
Init(h);
req_addr = addr;
@ -175,7 +189,6 @@ DNS_Mapping::DNS_Mapping(FILE* f)
init_failed = 1;
req_host = 0;
req_addr = 0;
char buf[512];
@ -188,14 +201,15 @@ DNS_Mapping::DNS_Mapping(FILE* f)
char req_buf[512+1], name_buf[512+1];
int is_req_host;
if ( sscanf(buf, "%lf %d %512s %d %512s %d", &creation_time, &is_req_host,
req_buf, &failed, name_buf, &num_addrs) != 6 )
if ( sscanf(buf, "%lf %d %512s %d %512s %d %d %"PRIu32, &creation_time,
&is_req_host, req_buf, &failed, name_buf, &map_type, &num_addrs,
&req_ttl) != 8 )
return;
if ( is_req_host )
req_host = copy_string(req_buf);
else
req_addr = dotted_to_addr(req_buf);
req_addr = IPAddr(req_buf);
num_names = 1;
names = new char*[num_names];
@ -203,7 +217,7 @@ DNS_Mapping::DNS_Mapping(FILE* f)
if ( num_addrs > 0 )
{
addrs = new uint32[num_addrs];
addrs = new IPAddr[num_addrs];
for ( int i = 0; i < num_addrs; ++i )
{
@ -217,7 +231,7 @@ DNS_Mapping::DNS_Mapping(FILE* f)
if ( newline )
*newline = '\0';
addrs[i] = dotted_to_addr(buf);
addrs[i] = IPAddr(buf);
}
}
else
@ -280,14 +294,6 @@ StringVal* DNS_Mapping::Host()
return host_val;
}
// Converts an array of 4 bytes in network order to the corresponding
// 32-bit network long.
static uint32 raw_bytes_to_addr(const unsigned char b[4])
{
uint32 l = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3];
return uint32(htonl(l));
}
void DNS_Mapping::Init(struct hostent* h)
{
no_mapping = 0;
@ -296,12 +302,13 @@ void DNS_Mapping::Init(struct hostent* h)
host_val = 0;
addrs_val = 0;
if ( ! h || h->h_addrtype != AF_INET || h->h_length != 4 )
if ( ! h )
{
Clear();
return;
}
map_type = h->h_addrtype;
num_names = 1; // for now, just use official name
names = new char*[num_names];
names[0] = h->h_name ? copy_string(h->h_name) : 0;
@ -311,10 +318,14 @@ void DNS_Mapping::Init(struct hostent* h)
if ( num_addrs > 0 )
{
addrs = new uint32[num_addrs];
addrs = new IPAddr[num_addrs];
for ( int i = 0; i < num_addrs; ++i )
addrs[i] = raw_bytes_to_addr(
(unsigned char*)h->h_addr_list[i]);
if ( h->h_addrtype == AF_INET )
addrs[i] = IPAddr(IPAddr::IPv4, (uint32*)h->h_addr_list[i],
IPAddr::Network);
else if ( h->h_addrtype == AF_INET6 )
addrs[i] = IPAddr(IPAddr::IPv6, (uint32*)h->h_addr_list[i],
IPAddr::Network);
}
else
addrs = 0;
@ -330,18 +341,19 @@ void DNS_Mapping::Clear()
host_val = 0;
addrs_val = 0;
no_mapping = 0;
map_type = 0;
failed = 1;
}
void DNS_Mapping::Save(FILE* f) const
{
fprintf(f, "%.0f %d %s %d %s %d\n", creation_time, req_host != 0,
req_host ? req_host : dotted_addr(req_addr),
fprintf(f, "%.0f %d %s %d %s %d %d %"PRIu32"\n", creation_time, req_host != 0,
req_host ? req_host : req_addr.AsString().c_str(),
failed, (names && names[0]) ? names[0] : "*",
num_addrs);
map_type, num_addrs, req_ttl);
for ( int i = 0; i < num_addrs; ++i )
fprintf(f, "%s\n", dotted_addr(addrs[i]));
fprintf(f, "%s\n", addrs[i].AsString().c_str());
}
@ -351,7 +363,6 @@ DNS_Mgr::DNS_Mgr(DNS_MgrMode arg_mode)
mode = arg_mode;
host_mappings.SetDeleteFunc(DNS_Mgr_mapping_delete_func);
addr_mappings.SetDeleteFunc(DNS_Mgr_mapping_delete_func);
char err[NB_DNS_ERRSIZE];
@ -440,24 +451,34 @@ TableVal* DNS_Mgr::LookupHost(const char* name)
if ( mode != DNS_PRIME )
{
DNS_Mapping* d = host_mappings.Lookup(name);
HostMap::iterator it = host_mappings.find(name);
if ( d )
if ( it != host_mappings.end() )
{
if ( d->Valid() )
return d->Addrs()->ConvertToSet();
else
DNS_Mapping* d4 = it->second.first;
DNS_Mapping* d6 = it->second.second;
if ( (d4 && d4->Failed()) || (d6 && d6->Failed()) )
{
reporter->Warning("no such host: %s", name);
return empty_addr_set();
}
else if ( d4 && d6 )
{
TableVal* tv4 = d4->AddrsSet();
TableVal* tv6 = d6->AddrsSet();
tv4->AddTo(tv6, false);
Unref(tv4);
return tv6;
}
}
}
// Not found, or priming.
switch ( mode ) {
case DNS_PRIME:
requests.append(new DNS_Mgr_Request(name));
requests.append(new DNS_Mgr_Request(name, AF_INET));
requests.append(new DNS_Mgr_Request(name, AF_INET6));
return empty_addr_set();
case DNS_FORCE:
@ -465,7 +486,8 @@ TableVal* DNS_Mgr::LookupHost(const char* name)
return 0;
case DNS_DEFAULT:
requests.append(new DNS_Mgr_Request(name));
requests.append(new DNS_Mgr_Request(name, AF_INET));
requests.append(new DNS_Mgr_Request(name, AF_INET6));
Resolve();
return LookupHost(name);
@ -475,14 +497,14 @@ TableVal* DNS_Mgr::LookupHost(const char* name)
}
}
Val* DNS_Mgr::LookupAddr(uint32 addr)
Val* DNS_Mgr::LookupAddr(const IPAddr& addr)
{
if ( ! did_init )
Init();
if ( mode != DNS_PRIME )
{
HashKey h(&addr, 1);
HashKey h(addr);
DNS_Mapping* d = addr_mappings.Lookup(&h);
if ( d )
@ -491,8 +513,9 @@ Val* DNS_Mgr::LookupAddr(uint32 addr)
return d->Host();
else
{
reporter->Warning("can't resolve IP address: %s", dotted_addr(addr));
return new StringVal(dotted_addr(addr));
string s(addr);
reporter->Warning("can't resolve IP address: %s", s.c_str());
return new StringVal(s.c_str());
}
}
}
@ -505,7 +528,7 @@ Val* DNS_Mgr::LookupAddr(uint32 addr)
case DNS_FORCE:
reporter->FatalError("can't find DNS entry for %s in cache",
dotted_addr(addr));
addr.AsString().c_str());
return 0;
case DNS_DEFAULT:
@ -681,27 +704,55 @@ void DNS_Mgr::AddResult(DNS_Mgr_Request* dr, struct nb_dns_result* r)
if ( dr->ReqHost() )
{
new_dm = new DNS_Mapping(dr->ReqHost(), h, ttl);
prev_dm = host_mappings.Insert(dr->ReqHost(), new_dm);
HostMap::iterator it = host_mappings.find(dr->ReqHost());
if ( it == host_mappings.end() )
{
host_mappings[dr->ReqHost()].first =
new_dm->Type() == AF_INET ? new_dm : 0;
host_mappings[dr->ReqHost()].second =
new_dm->Type() == AF_INET6 ? new_dm : 0;
prev_dm = 0;
}
else
{
prev_dm = 0;
if ( new_dm->Type() == AF_INET )
{
prev_dm = it->second.first;
it->second.first = new_dm;
}
else
{
prev_dm = it->second.second;
it->second.second = new_dm;
}
}
if ( new_dm->Failed() && prev_dm && prev_dm->Valid() )
{
// Put previous, valid entry back - CompareMappings
// will generate a corresponding warning.
(void) host_mappings.Insert(dr->ReqHost(), prev_dm);
if ( prev_dm->Type() == AF_INET )
host_mappings[dr->ReqHost()].first = prev_dm;
else
host_mappings[dr->ReqHost()].second = prev_dm;
++keep_prev;
}
}
else
{
new_dm = new DNS_Mapping(dr->ReqAddr(), h, ttl);
uint32 tmp_addr = dr->ReqAddr();
HashKey k(&tmp_addr, 1);
HashKey k(dr->ReqAddr());
prev_dm = addr_mappings.Insert(&k, new_dm);
if ( new_dm->Failed() && prev_dm && prev_dm->Valid() )
{
uint32 tmp_addr = dr->ReqAddr();
HashKey k2(&tmp_addr, 1);
HashKey k2(dr->ReqAddr());
(void) addr_mappings.Insert(&k2, prev_dm);
++keep_prev;
}
@ -774,17 +825,13 @@ ListVal* DNS_Mgr::AddrListDelta(ListVal* al1, ListVal* al2)
for ( int i = 0; i < al1->Length(); ++i )
{
addr_type al1_i = al1->Index(i)->AsAddr();
const IPAddr& al1_i = al1->Index(i)->AsAddr();
int j;
for ( j = 0; j < al2->Length(); ++j )
{
addr_type al2_j = al2->Index(j)->AsAddr();
#ifdef BROv6
if ( addr_eq(al1_i, al2_j) )
#else
const IPAddr& al2_j = al2->Index(j)->AsAddr();
if ( al1_i == al2_j )
#endif
break;
}
@ -800,8 +847,8 @@ void DNS_Mgr::DumpAddrList(FILE* f, ListVal* al)
{
for ( int i = 0; i < al->Length(); ++i )
{
addr_type al_i = al->Index(i)->AsAddr();
fprintf(f, "%s%s", i > 0 ? "," : "", dotted_addr(al_i));
const IPAddr& al_i = al->Index(i)->AsAddr();
fprintf(f, "%s%s", i > 0 ? "," : "", al_i.AsString().c_str());
}
}
@ -814,11 +861,20 @@ void DNS_Mgr::LoadCache(FILE* f)
for ( ; ! m->NoMapping() && ! m->InitFailed(); m = new DNS_Mapping(f) )
{
if ( m->ReqHost() )
host_mappings.Insert(m->ReqHost(), m);
{
if ( host_mappings.find(m->ReqHost()) == host_mappings.end() )
{
host_mappings[m->ReqHost()].first = 0;
host_mappings[m->ReqHost()].second = 0;
}
if ( m->Type() == AF_INET )
host_mappings[m->ReqHost()].first = m;
else
host_mappings[m->ReqHost()].second = m;
}
else
{
uint32 tmp_addr = m->ReqAddr();
HashKey h(&tmp_addr, 1);
HashKey h(m->ReqAddr());
addr_mappings.Insert(&h, m);
}
}
@ -839,9 +895,23 @@ void DNS_Mgr::Save(FILE* f, PDict(DNS_Mapping)& m)
dm->Save(f);
}
const char* DNS_Mgr::LookupAddrInCache(dns_mgr_addr_type addr)
void DNS_Mgr::Save(FILE* f, const HostMap& m)
{
HashKey h(&addr, 1);
HostMap::const_iterator it;
for ( it = m.begin(); it != m.end(); ++it )
{
if ( it->second.first )
it->second.first->Save(f);
if ( it->second.second )
it->second.second->Save(f);
}
}
const char* DNS_Mgr::LookupAddrInCache(const IPAddr& addr)
{
HashKey h(addr);
DNS_Mapping* d = dns_mgr->addr_mappings.Lookup(&h);
if ( ! d )
@ -861,23 +931,32 @@ const char* DNS_Mgr::LookupAddrInCache(dns_mgr_addr_type addr)
TableVal* DNS_Mgr::LookupNameInCache(string name)
{
DNS_Mapping* d = dns_mgr->host_mappings.Lookup(name.c_str());
if ( ! d || ! d->names )
HostMap::iterator it = dns_mgr->host_mappings.find(name);
if ( it == dns_mgr->host_mappings.end() )
return 0;
if ( d->Expired() )
DNS_Mapping* d4 = it->second.first;
DNS_Mapping* d6 = it->second.second;
if ( ! d4 || ! d4->names || ! d6 || ! d6->names )
return 0;
if ( d4->Expired() || d6->Expired() )
{
HashKey h(name.c_str());
dns_mgr->host_mappings.Remove(&h);
delete d;
dns_mgr->host_mappings.erase(it);
delete d4;
delete d6;
return 0;
}
return d->AddrsSet();
TableVal* tv4 = d4->AddrsSet();
TableVal* tv6 = d6->AddrsSet();
tv4->AddTo(tv6, false);
Unref(tv4);
return tv6;
}
void DNS_Mgr::AsyncLookupAddr(dns_mgr_addr_type host, LookupCallback* callback)
void DNS_Mgr::AsyncLookupAddr(const IPAddr& host, LookupCallback* callback)
{
if ( ! did_init )
Init();
@ -956,10 +1035,15 @@ void DNS_Mgr::IssueAsyncRequests()
++num_requests;
DNS_Mgr_Request* dr;
DNS_Mgr_Request* dr6 = 0;
if ( req->IsAddrReq() )
dr = new DNS_Mgr_Request(req->host);
else
dr = new DNS_Mgr_Request(req->name.c_str());
{
dr = new DNS_Mgr_Request(req->name.c_str(), AF_INET);
dr6 = new DNS_Mgr_Request(req->name.c_str(), AF_INET6);
}
if ( ! dr->MakeRequest(nb_dns) )
{
@ -969,6 +1053,14 @@ void DNS_Mgr::IssueAsyncRequests()
continue;
}
if ( dr6 && ! dr6->MakeRequest(nb_dns) )
{
reporter->Warning("can't issue DNS request");
++failed;
req->Timeout();
continue;
}
req->time = current_time();
asyncs_timeouts.push(req);
@ -987,7 +1079,7 @@ double DNS_Mgr::NextTimestamp(double* network_time)
return asyncs_timeouts.size() ? timer_mgr->Time() : -1.0;
}
void DNS_Mgr::CheckAsyncAddrRequest(dns_mgr_addr_type addr, bool timeout)
void DNS_Mgr::CheckAsyncAddrRequest(const IPAddr& addr, bool timeout)
{
// Note that this code is a mirror of that for CheckAsyncHostRequest.
@ -1060,10 +1152,14 @@ void DNS_Mgr::Flush()
{
DoProcess(false);
IterCookie* cookie = addr_mappings.InitForIteration();
DNS_Mapping* dm;
HostMap::iterator it;
for ( it = host_mappings.begin(); it != host_mappings.end(); ++it )
{
delete it->second.first;
delete it->second.second;
}
host_mappings.Clear();
host_mappings.clear();
addr_mappings.Clear();
}
@ -1107,6 +1203,14 @@ void DNS_Mgr::DoProcess(bool flush)
else if ( status > 0 )
{
DNS_Mgr_Request* dr = (DNS_Mgr_Request*) r.cookie;
bool do_host_timeout = true;
if ( dr->ReqHost() &&
host_mappings.find(dr->ReqHost()) == host_mappings.end() )
// Don't timeout when this is the first result in an expected pair
// (one result each for A and AAAA queries).
do_host_timeout = false;
if ( dr->RequestPending() )
{
AddResult(dr, &r);
@ -1116,7 +1220,7 @@ void DNS_Mgr::DoProcess(bool flush)
if ( ! dr->ReqHost() )
CheckAsyncAddrRequest(dr->ReqAddr(), true);
else
CheckAsyncHostRequest(dr->ReqHost(), true);
CheckAsyncHostRequest(dr->ReqHost(), do_host_timeout);
IssueAsyncRequests();
@ -1167,7 +1271,7 @@ void DNS_Mgr::GetStats(Stats* stats)
stats->successful = successful;
stats->failed = failed;
stats->pending = asyncs_pending;
stats->cached_hosts = host_mappings.Length();
stats->cached_hosts = host_mappings.size();
stats->cached_addresses = addr_mappings.Length();
}

View file

@ -6,12 +6,14 @@
#include <list>
#include <map>
#include <queue>
#include <utility>
#include "util.h"
#include "BroList.h"
#include "Dict.h"
#include "EventHandler.h"
#include "IOSource.h"
#include "IPAddr.h"
class Val;
class ListVal;
@ -39,10 +41,6 @@ enum DNS_MgrMode {
// Number of seconds we'll wait for a reply.
#define DNS_TIMEOUT 5
// ### For now, we don't support IPv6 lookups. When we do, this
// should become addr_type.
typedef uint32 dns_mgr_addr_type;
class DNS_Mgr : public IOSource {
public:
DNS_Mgr(DNS_MgrMode mode);
@ -55,7 +53,7 @@ public:
// a set of addr.
TableVal* LookupHost(const char* host);
Val* LookupAddr(uint32 addr);
Val* LookupAddr(const IPAddr& addr);
// Define the directory where to store the data.
void SetDir(const char* arg_dir) { dir = copy_string(arg_dir); }
@ -64,7 +62,7 @@ public:
void Resolve();
int Save();
const char* LookupAddrInCache(dns_mgr_addr_type addr);
const char* LookupAddrInCache(const IPAddr& addr);
TableVal* LookupNameInCache(string name);
// Support for async lookups.
@ -78,7 +76,7 @@ public:
virtual void Timeout() = 0;
};
void AsyncLookupAddr(dns_mgr_addr_type host, LookupCallback* callback);
void AsyncLookupAddr(const IPAddr& host, LookupCallback* callback);
void AsyncLookupName(string name, LookupCallback* callback);
struct Stats {
@ -107,8 +105,10 @@ protected:
ListVal* AddrListDelta(ListVal* al1, ListVal* al2);
void DumpAddrList(FILE* f, ListVal* al);
typedef map<string, pair<DNS_Mapping*, DNS_Mapping*> > HostMap;
void LoadCache(FILE* f);
void Save(FILE* f, PDict(DNS_Mapping)& m);
void Save(FILE* f, const HostMap& m);
// Selects on the fd to see if there is an answer available (timeout
// is secs). Returns 0 on timeout, -1 on EINTR or other error, and 1
@ -120,7 +120,7 @@ protected:
// Finish the request if we have a result. If not, time it out if
// requested.
void CheckAsyncAddrRequest(dns_mgr_addr_type addr, bool timeout);
void CheckAsyncAddrRequest(const IPAddr& addr, bool timeout);
void CheckAsyncHostRequest(const char* host, bool timeout);
// Process outstanding requests.
@ -136,7 +136,7 @@ protected:
PDict(ListVal) services;
PDict(DNS_Mapping) host_mappings;
HostMap host_mappings;
PDict(DNS_Mapping) addr_mappings;
DNS_mgr_request_list requests;
@ -163,7 +163,7 @@ protected:
struct AsyncRequest {
double time;
dns_mgr_addr_type host;
IPAddr host;
string name;
CallbackList callbacks;
@ -204,7 +204,7 @@ protected:
};
typedef map<dns_mgr_addr_type, AsyncRequest*> AsyncRequestAddrMap;
typedef map<IPAddr, AsyncRequest*> AsyncRequestAddrMap;
AsyncRequestAddrMap asyncs_addrs;
typedef map<string, AsyncRequest*> AsyncRequestNameMap;

View file

@ -11,52 +11,43 @@
#include "ConnSizeAnalyzer.h"
ExpectedConn::ExpectedConn(const uint32* _orig, const uint32* _resp,
ExpectedConn::ExpectedConn(const IPAddr& _orig, const IPAddr& _resp,
uint16 _resp_p, uint16 _proto)
{
if ( orig )
copy_addr(_orig, orig);
if ( _orig == IPAddr(string("0.0.0.0")) )
// don't use the IPv4 mapping, use the literal unspecified address
// to indicate a wildcard
orig = IPAddr(string("::"));
else
{
for ( int i = 0; i < NUM_ADDR_WORDS; ++i )
orig[i] = 0;
}
copy_addr(_resp, resp);
resp_p = _resp_p;
proto = _proto;
}
ExpectedConn::ExpectedConn(uint32 _orig, uint32 _resp,
uint16 _resp_p, uint16 _proto)
{
#ifdef BROv6
// Use the IPv4-within-IPv6 convention, as this is what's
// needed when we mix uint32's (like in this construction)
// with addr_type's (for example, when looking up expected
// connections).
orig[0] = orig[1] = orig[2] = 0;
resp[0] = resp[1] = resp[2] = 0;
orig[3] = _orig;
resp[3] = _resp;
#else
orig[0] = _orig;
resp[0] = _resp;
#endif
orig = _orig;
resp = _resp;
resp_p = _resp_p;
proto = _proto;
}
ExpectedConn::ExpectedConn(const ExpectedConn& c)
{
copy_addr(c.orig, orig);
copy_addr(c.resp, resp);
orig = c.orig;
resp = c.resp;
resp_p = c.resp_p;
proto = c.proto;
}
HashKey* ExpectedConn::GetKey() const
{
struct Key {
uint32 orig[4];
uint32 resp[4];
uint16 resp_p;
uint16 proto;
};
Key k;
orig.CopyIPv6(k.orig);
resp.CopyIPv6(k.resp);
k.resp_p = resp_p;
k.proto = proto;
return new HashKey(&k, sizeof(k));
}
DPM::DPM()
: expected_conns_queue(AssignedAnalyzer::compare)
@ -158,23 +149,18 @@ AnalyzerTag::Tag DPM::GetExpected(int proto, const Connection* conn)
ExpectedConn c(conn->OrigAddr(), conn->RespAddr(),
ntohs(conn->RespPort()), proto);
// Can't use sizeof(c) due to potential alignment issues.
// FIXME: I guess this is still not portable ...
HashKey key(&c, sizeof(c.orig) + sizeof(c.resp) +
sizeof(c.resp_p) + sizeof(c.proto));
AssignedAnalyzer* a = expected_conns.Lookup(&key);
HashKey* key = c.GetKey();
AssignedAnalyzer* a = expected_conns.Lookup(key);
delete key;
if ( ! a )
{
// Wildcard for originator.
for ( int i = 0; i < NUM_ADDR_WORDS; ++i )
c.orig[i] = 0;
c.orig = IPAddr(string("::"));
HashKey key(&c, sizeof(c.orig) + sizeof(c.resp) +
sizeof(c.resp_p) + sizeof(c.proto));
a = expected_conns.Lookup(&key);
HashKey* key = c.GetKey();
a = expected_conns.Lookup(key);
delete key;
}
if ( ! a )
@ -366,7 +352,8 @@ bool DPM::BuildInitialAnalyzerTree(TransportProto proto, Connection* conn,
return true;
}
void DPM::ExpectConnection(addr_type orig, addr_type resp, uint16 resp_p,
void DPM::ExpectConnection(const IPAddr& orig, const IPAddr& resp,
uint16 resp_p,
TransportProto proto, AnalyzerTag::Tag analyzer,
double timeout, void* cookie)
{
@ -378,11 +365,7 @@ void DPM::ExpectConnection(addr_type orig, addr_type resp, uint16 resp_p,
{
if ( ! a->deleted )
{
HashKey* key = new HashKey(&a->conn,
sizeof(a->conn.orig) +
sizeof(a->conn.resp) +
sizeof(a->conn.resp_p) +
sizeof(a->conn.proto));
HashKey* key = a->conn.GetKey();
expected_conns.Remove(key);
delete key;
}
@ -401,10 +384,9 @@ void DPM::ExpectConnection(addr_type orig, addr_type resp, uint16 resp_p,
ExpectedConn c(orig, resp, resp_p, proto);
HashKey key(&c, sizeof(c.orig) + sizeof(c.resp) +
sizeof(c.resp_p) + sizeof(c.proto));
HashKey* key = c.GetKey();
AssignedAnalyzer* a = expected_conns.Lookup(&key);
AssignedAnalyzer* a = expected_conns.Lookup(key);
if ( a )
a->deleted = true;
@ -416,8 +398,9 @@ void DPM::ExpectConnection(addr_type orig, addr_type resp, uint16 resp_p,
a->timeout = network_time + timeout;
a->deleted = false;
expected_conns.Insert(&key, a);
expected_conns.Insert(key, a);
expected_conns_queue.push(a);
delete key;
}
void DPM::Done()
@ -428,11 +411,7 @@ void DPM::Done()
AssignedAnalyzer* a = expected_conns_queue.top();
if ( ! a->deleted )
{
HashKey* key = new HashKey(&a->conn,
sizeof(a->conn.orig) +
sizeof(a->conn.resp) +
sizeof(a->conn.resp_p) +
sizeof(a->conn.proto));
HashKey* key = a->conn.GetKey();
expected_conns.Remove(key);
delete key;
}

View file

@ -27,19 +27,15 @@
// Map to assign expected connections to analyzers.
class ExpectedConn {
public:
// This form can be used for IPv6 as well as IPv4.
ExpectedConn(const uint32* _orig, const uint32* _resp,
ExpectedConn(const IPAddr& _orig, const IPAddr& _resp,
uint16 _resp_p, uint16 _proto);
// This form only works for expecting an IPv4 connection. Note
// that we do the right thing whether we're built IPv4-only or
// BROv6.
ExpectedConn(uint32 _orig, uint32 _resp, uint16 _resp_p, uint16 _proto);
ExpectedConn(const ExpectedConn& c);
uint32 orig[NUM_ADDR_WORDS];
uint32 resp[NUM_ADDR_WORDS];
HashKey* GetKey() const;
IPAddr orig;
IPAddr resp;
uint16 resp_p;
uint16 proto;
};
@ -90,7 +86,7 @@ public:
// Schedules a particular analyzer for an upcoming connection.
// 0 acts as a wildcard for orig. (Cookie is currently unused.
// Eventually, we may pass it on to the analyzer).
void ExpectConnection(addr_type orig, addr_type resp, uint16 resp_p,
void ExpectConnection(const IPAddr& orig, const IPAddr& resp, uint16 resp_p,
TransportProto proto, AnalyzerTag::Tag analyzer,
double timeout, void* cookie);

View file

@ -6,7 +6,9 @@
#include <stdio.h>
#include <list>
#include <utility>
#include "BroString.h"
#include "IPAddr.h"
typedef enum {
DESC_READABLE,
@ -68,11 +70,14 @@ public:
void Add(const char* s, int do_indent=1);
void AddN(const char* s, int len) { AddBytes(s, len); }
void Add(const string& s) { AddBytes(s.data(), s.size()); }
void Add(int i);
void Add(uint32 u);
void Add(int64 i);
void Add(uint64 u);
void Add(double d);
void Add(const IPAddr& addr) { Add(addr.AsString()); }
void Add(const IPPrefix& prefix) { Add(prefix.AsString()); }
// Add s as a counted string.
void AddCS(const char* s);

View file

@ -14,6 +14,7 @@
#include "Net.h"
#include "Traverse.h"
#include "Trigger.h"
#include "IPAddr.h"
const char* expr_name(BroExprTag t)
{
@ -834,30 +835,30 @@ Val* BinaryExpr::StringFold(Val* v1, Val* v2) const
Val* BinaryExpr::AddrFold(Val* v1, Val* v2) const
{
addr_type a1 = v1->AsAddr();
addr_type a2 = v2->AsAddr();
IPAddr a1 = v1->AsAddr();
IPAddr a2 = v2->AsAddr();
int result = 0;
switch ( tag ) {
#undef DO_FOLD
#ifdef BROv6
#define DO_FOLD(sense) { result = memcmp(a1, a2, 16) sense 0; break; }
#else
#define DO_FOLD(sense) \
{ \
a1 = ntohl(a1); \
a2 = ntohl(a2); \
result = (a1 < a2 ? -1 : (a1 == a2 ? 0 : 1)) sense 0; \
break; \
}
#endif
case EXPR_LT: DO_FOLD(<)
case EXPR_LE: DO_FOLD(<=)
case EXPR_EQ: DO_FOLD(==)
case EXPR_NE: DO_FOLD(!=)
case EXPR_GE: DO_FOLD(>=)
case EXPR_GT: DO_FOLD(>)
case EXPR_LT:
result = a1 < a2;
break;
case EXPR_LE:
result = a1 < a2 || a1 == a2;
break;
case EXPR_EQ:
result = a1 == a2;
break;
case EXPR_NE:
result = a1 != a2;
break;
case EXPR_GE:
result = ! ( a1 < a2 );
break;
case EXPR_GT:
result = ( ! ( a1 < a2 ) ) && ( a1 != a2 );
break;
default:
BadTag("BinaryExpr::AddrFold", expr_name(tag));
@ -868,20 +869,13 @@ Val* BinaryExpr::AddrFold(Val* v1, Val* v2) const
Val* BinaryExpr::SubNetFold(Val* v1, Val* v2) const
{
subnet_type* n1 = v1->AsSubNet();
subnet_type* n2 = v2->AsSubNet();
const IPPrefix& n1 = v1->AsSubNet();
const IPPrefix& n2 = v2->AsSubNet();
if ( n1->width != n2->width )
if ( n1 == n2 )
return new Val(1, TYPE_BOOL);
else
return new Val(0, TYPE_BOOL);
#ifdef BROv6
if ( memcmp(n1->net, n2->net, 16) )
#else
if ( n1->net != n2->net )
#endif
return new Val(0, TYPE_BOOL);
return new Val(1, TYPE_BOOL);
}
void BinaryExpr::SwapOps()
@ -1681,15 +1675,13 @@ DivideExpr::DivideExpr(Expr* arg_op1, Expr* arg_op2)
Val* DivideExpr::AddrFold(Val* v1, Val* v2) const
{
addr_type a1 = v1->AsAddr();
uint32 mask;
if ( v2->Type()->Tag() == TYPE_COUNT )
mask = static_cast<uint32>(v2->InternalUnsigned());
else
mask = static_cast<uint32>(v2->InternalInt());
return new SubNetVal(a1, mask);
return new SubNetVal(v1->AsAddr(), mask);
}
Expr* DivideExpr::DoSimplify()

View file

@ -1543,7 +1543,7 @@ void HTTP_Analyzer::HTTP_Header(int is_orig, MIME_Header* h)
}
}
void HTTP_Analyzer::ParseVersion(data_chunk_t ver, const uint32* host,
void HTTP_Analyzer::ParseVersion(data_chunk_t ver, const IPAddr& host,
bool user_agent)
{
int len = ver.length;

View file

@ -8,6 +8,7 @@
#include "MIME.h"
#include "binpac_bro.h"
#include "ZIP.h"
#include "IPAddr.h"
enum CHUNKED_TRANSFER_STATE {
NON_CHUNKED_TRANSFER,
@ -212,7 +213,7 @@ protected:
const BroString* UnansweredRequestMethod();
void ParseVersion(data_chunk_t ver, const uint32* host, bool user_agent);
void ParseVersion(data_chunk_t ver, const IPAddr& host, bool user_agent);
int HTTP_ReplyCode(const char* code_str);
int ExpectReplyMessageBody();

View file

@ -103,6 +103,16 @@ HashKey::HashKey(const BroString* s)
is_our_dynamic = 0;
}
HashKey::HashKey(const IPAddr& addr)
{
const uint32* bytes;
int len = addr.GetBytes(&bytes);
size = len * sizeof(uint32);
key = CopyKey(bytes, size);
is_our_dynamic = 1;
hash = HashBytes(key, size);
}
HashKey::HashKey(int copy_key, void* arg_key, int arg_size)
{
size = arg_size;

View file

@ -6,8 +6,9 @@
#include <stdlib.h>
#include "BroString.h"
#include "IPAddr.h"
#define UHASH_KEY_SIZE 32
#define UHASH_KEY_SIZE 36
typedef uint64 hash_t;
@ -28,6 +29,7 @@ public:
HashKey(const void* p);
HashKey(const char* s);
HashKey(const BroString* s);
HashKey(const IPAddr& addr);
~HashKey()
{
if ( is_our_dynamic )

View file

@ -55,7 +55,6 @@ void ICMP_Analyzer::DeliverPacket(int len, const u_char* data,
{
int chksum = 0;
#ifdef BROv6
switch ( ip->NextProto() )
{
case IPPROTO_ICMP:
@ -69,10 +68,6 @@ void ICMP_Analyzer::DeliverPacket(int len, const u_char* data,
default:
reporter->InternalError("unexpected IP proto in ICMP analyzer");
}
#else
// Classic v4 version.
chksum = icmp_checksum(icmpp, len);
#endif
if ( chksum != 0xffff )
{
@ -89,6 +84,9 @@ void ICMP_Analyzer::DeliverPacket(int len, const u_char* data,
matcher_state.InitEndpointMatcher(this, ip, len, is_orig, 0);
}
type = icmpp->icmp_type;
code = icmpp->icmp_code;
// Move past common portion of ICMP header.
data += 8;
caplen -= 8;
@ -96,10 +94,8 @@ void ICMP_Analyzer::DeliverPacket(int len, const u_char* data,
if ( ip->NextProto() == IPPROTO_ICMP )
NextICMP4(current_timestamp, icmpp, len, caplen, data, ip);
#ifdef BROv6
else
NextICMP6(current_timestamp, icmpp, len, caplen, data, ip);
#endif
if ( caplen >= len )
@ -130,7 +126,6 @@ void ICMP_Analyzer::NextICMP4(double t, const struct icmp* icmpp, int len, int c
}
}
#ifdef BROv6
void ICMP_Analyzer::NextICMP6(double t, const struct icmp* icmpp, int len, int caplen,
const u_char*& data, const IP_Hdr* ip_hdr )
{
@ -178,7 +173,6 @@ void ICMP_Analyzer::NextICMP6(double t, const struct icmp* icmpp, int len, int c
break;
}
}
#endif
void ICMP_Analyzer::ICMPEvent(EventHandlerPtr f, const struct icmp* icmpp, int len, int icmpv6)
{
@ -284,7 +278,7 @@ RecordVal* ICMP_Analyzer::ExtractICMP4Context(int len, const u_char*& data)
uint32 ip_len, frag_offset;
TransportProto proto = TRANSPORT_UNKNOWN;
int DF, MF, bad_hdr_len, bad_checksum;
uint32 src_addr, dst_addr,src_addr2, dst_addr2;
IPAddr src_addr, dst_addr;
uint32 src_port, dst_port;
if ( ip_hdr_len < sizeof(struct ip) || ip_hdr_len > uint32(len) )
@ -303,8 +297,8 @@ RecordVal* ICMP_Analyzer::ExtractICMP4Context(int len, const u_char*& data)
ip_len = ip_hdr->TotalLen();
bad_checksum = ones_complement_checksum((void*) ip_hdr->IP4_Hdr(), ip_hdr_len, 0) != 0xffff;
src_addr = ip_hdr->SrcAddr4();
dst_addr = ip_hdr->DstAddr4();
src_addr = ip_hdr->SrcAddr();
dst_addr = ip_hdr->DstAddr();
uint32 frag_field = ip_hdr->FragField();
DF = ip_hdr->DF();
@ -342,7 +336,6 @@ RecordVal* ICMP_Analyzer::ExtractICMP4Context(int len, const u_char*& data)
return iprec;
}
#ifdef BROv6
RecordVal* ICMP_Analyzer::ExtractICMP6Context(int len, const u_char*& data)
{
const IP_Hdr ip_hdr_data((const struct ip6_hdr*) data);
@ -351,8 +344,8 @@ RecordVal* ICMP_Analyzer::ExtractICMP6Context(int len, const u_char*& data)
TransportProto proto = TRANSPORT_UNKNOWN;
uint32 ip_hdr_len = ip_hdr->HdrLen(); //should always be 40
uint32* src_addr;
uint32* dst_addr;
IPAddr src_addr;
IPAddr dst_addr;
uint32 ip_len, frag_offset = 0;
uint32 src_port, dst_port;
@ -368,8 +361,8 @@ RecordVal* ICMP_Analyzer::ExtractICMP6Context(int len, const u_char*& data)
{
ip_len = ip_hdr->TotalLen();
src_addr = (uint32 *) ip_hdr->SrcAddr();
dst_addr = (uint32 *) ip_hdr->DstAddr();
src_addr = ip_hdr->SrcAddr();
dst_addr = ip_hdr->DstAddr();
if ( uint32(len) >= ip_hdr_len + 4 )
proto = GetContextProtocol(ip_hdr, &src_port, &dst_port);
@ -413,7 +406,6 @@ RecordVal* ICMP_Analyzer::ExtractICMP6Context(int len, const u_char*& data)
return iprec;
}
#endif
bool ICMP_Analyzer::IsReuse(double /* t */, const u_char* /* pkt */)
@ -428,18 +420,16 @@ void ICMP_Analyzer::Describe(ODesc* d) const
d->Add(Conn()->LastTime());
d->AddSP(")");
d->Add(dotted_addr(Conn()->OrigAddr()));
#if 0
d->Add(Conn()->OrigAddr());
d->Add(".");
d->Add(type);
d->Add(".");
d->Add(code);
#endif
d->SP();
d->AddSP("->");
d->Add(dotted_addr(Conn()->RespAddr()));
d->Add(Conn()->RespAddr());
}
void ICMP_Analyzer::UpdateConnVal(RecordVal *conn_val)
@ -488,11 +478,9 @@ void ICMP_Analyzer::Echo(double t, const struct icmp* icmpp, int len,
// For handling all Echo related ICMP messages
EventHandlerPtr f = 0;
#ifdef BROv6
if ( ip_hdr->NextProto() == IPPROTO_ICMPV6 )
f = (icmpp->icmp_type == ICMP6_ECHO_REQUEST) ? icmp_echo_request : icmp_echo_reply;
else
#endif
f = (icmpp->icmp_type == ICMP_ECHO) ? icmp_echo_request : icmp_echo_reply;
if ( ! f )
@ -569,7 +557,6 @@ void ICMP_Analyzer::Context4(double t, const struct icmp* icmpp,
}
#ifdef BROv6
void ICMP_Analyzer::Context6(double t, const struct icmp* icmpp,
int len, int caplen, const u_char*& data, const IP_Hdr* ip_hdr)
{
@ -598,7 +585,6 @@ void ICMP_Analyzer::Context6(double t, const struct icmp* icmpp,
ConnectionEvent(f, vl);
}
}
#endif
int ICMP4_counterpart(int icmp_type, int icmp_code, bool& is_one_way)
{

View file

@ -57,7 +57,6 @@ protected:
TransportProto GetContextProtocol(const IP_Hdr* ip_hdr, uint32* src_port,
uint32* dst_port);
#ifdef BROv6
void NextICMP6(double t, const struct icmp* icmpp, int len, int caplen,
const u_char*& data, const IP_Hdr* ip_hdr );
@ -65,9 +64,10 @@ protected:
void Context6(double t, const struct icmp* icmpp, int len, int caplen,
const u_char*& data, const IP_Hdr* ip_hdr);
#endif
RecordVal* icmp_conn_val;
int type;
int code;
int request_len, reply_len;
RuleMatcherState matcher_state;

View file

@ -4,63 +4,29 @@
#define ip_h
#include "config.h"
#include "IPAddr.h"
#include <net_util.h>
class IP_Hdr {
public:
IP_Hdr(struct ip* arg_ip4)
: ip4(arg_ip4), ip6(0), del(1)
{
ip4 = arg_ip4;
ip6 = 0;
del = 1;
#ifdef BROv6
src_addr[0] = src_addr[1] = src_addr[2] = 0;
dst_addr[0] = dst_addr[1] = dst_addr[2] = 0;
src_addr[3] = ip4->ip_src.s_addr;
dst_addr[3] = ip4->ip_dst.s_addr;
#endif
}
IP_Hdr(const struct ip* arg_ip4)
: ip4(arg_ip4), ip6(0), del(0)
{
ip4 = arg_ip4;
ip6 = 0;
del = 0;
#ifdef BROv6
src_addr[0] = src_addr[1] = src_addr[2] = 0;
dst_addr[0] = dst_addr[1] = dst_addr[2] = 0;
src_addr[3] = ip4->ip_src.s_addr;
dst_addr[3] = ip4->ip_dst.s_addr;
#endif
}
IP_Hdr(struct ip6_hdr* arg_ip6)
: ip4(0), ip6(arg_ip6), del(1)
{
ip4 = 0;
ip6 = arg_ip6;
del = 1;
#ifdef BROv6
memcpy(src_addr, ip6->ip6_src.s6_addr, 16);
memcpy(dst_addr, ip6->ip6_dst.s6_addr, 16);
#endif
}
IP_Hdr(const struct ip6_hdr* arg_ip6)
: ip4(0), ip6(arg_ip6), del(0)
{
ip4 = 0;
ip6 = arg_ip6;
del = 0;
#ifdef BROv6
memcpy(src_addr, ip6->ip6_src.s6_addr, 16);
memcpy(dst_addr, ip6->ip6_dst.s6_addr, 16);
#endif
}
~IP_Hdr()
@ -77,19 +43,12 @@ public:
const struct ip* IP4_Hdr() const { return ip4; }
const struct ip6_hdr* IP6_Hdr() const { return ip6; }
#ifdef BROv6
const uint32* SrcAddr() const { return src_addr; }
const uint32* DstAddr() const { return dst_addr; }
#else
const uint32* SrcAddr() const
{ return ip4 ? &(ip4->ip_src.s_addr) : 0; }
const uint32* DstAddr() const
{ return ip4 ? &(ip4->ip_dst.s_addr) : 0; }
#endif
uint32 SrcAddr4() const { return ip4->ip_src.s_addr; }
uint32 DstAddr4() const { return ip4->ip_dst.s_addr; }
IPAddr SrcAddr() const
{ return ip4 ? IPAddr(ip4->ip_src) : IPAddr(ip6->ip6_src); }
IPAddr DstAddr() const
{ return ip4 ? IPAddr(ip4->ip_dst) : IPAddr(ip6->ip6_dst); }
//TODO: needs adapting/replacement for IPv6 support
uint16 ID4() const { return ip4 ? ip4->ip_id : 0; }
const u_char* Payload() const
@ -131,10 +90,6 @@ public:
private:
const struct ip* ip4;
const struct ip6_hdr* ip6;
#ifdef BROv6
uint32 src_addr[NUM_ADDR_WORDS];
uint32 dst_addr[NUM_ADDR_WORDS];
#endif
int del;
};

166
src/IPAddr.cc Normal file
View file

@ -0,0 +1,166 @@
// See the file "COPYING" in the main distribution directory for copyright.
#include "IPAddr.h"
#include "Reporter.h"
const uint8_t IPAddr::v4_mapped_prefix[12] = { 0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0xff, 0xff };
void IPAddr::Mask(int top_bits_to_keep)
{
if ( top_bits_to_keep <= 0 || top_bits_to_keep > 128 )
{
reporter->Error("Bad IPAddr::Mask value %d", top_bits_to_keep);
return;
}
uint32_t tmp[4];
memcpy(tmp, in6.s6_addr, sizeof(in6.s6_addr));
int word = 3;
int bits_to_chop = 128 - top_bits_to_keep;
while ( bits_to_chop >= 32 )
{
tmp[word] = 0;
--word;
bits_to_chop -= 32;
}
uint32_t w = ntohl(tmp[word]);
w >>= bits_to_chop;
w <<= bits_to_chop;
tmp[word] = htonl(w);
memcpy(in6.s6_addr, tmp, sizeof(in6.s6_addr));
}
void IPAddr::ReverseMask(int top_bits_to_chop)
{
if ( top_bits_to_chop <= 0 || top_bits_to_chop > 128 )
{
reporter->Error("Bad IPAddr::ReverseMask value %d", top_bits_to_chop);
return;
}
uint32_t tmp[4];
memcpy(tmp, in6.s6_addr, sizeof(in6.s6_addr));
int word = 0;
int bits_to_chop = top_bits_to_chop;
while ( bits_to_chop >= 32 )
{
tmp[word] = 0;
++word;
bits_to_chop -= 32;
}
uint32_t w = ntohl(tmp[word]);
w <<= bits_to_chop;
w >>= bits_to_chop;
tmp[word] = htonl(w);
memcpy(in6.s6_addr, tmp, sizeof(in6.s6_addr));
}
void IPAddr::Init(const std::string& s)
{
if ( s.find(':') == std::string::npos ) // IPv4.
{
memcpy(in6.s6_addr, v4_mapped_prefix, sizeof(v4_mapped_prefix));
if ( inet_pton(AF_INET, s.c_str(), &in6.s6_addr[12]) <=0 )
{
reporter->Error("Bad IP address: %s", s.c_str());
memset(in6.s6_addr, 0, sizeof(in6.s6_addr));
}
}
else
{
if ( inet_pton(AF_INET6, s.c_str(), in6.s6_addr) <=0 )
{
reporter->Error("Bad IP address: %s", s.c_str());
memset(in6.s6_addr, 0, sizeof(in6.s6_addr));
}
}
}
string IPAddr::AsString() const
{
if ( GetFamily() == IPv4 )
{
char s[INET_ADDRSTRLEN];
if ( inet_ntop(AF_INET, &in6.s6_addr[12], s, INET_ADDRSTRLEN) == NULL )
return "<bad IPv4 address conversion";
else
return s;
}
else
{
char s[INET6_ADDRSTRLEN];
if ( inet_ntop(AF_INET6, in6.s6_addr, s, INET6_ADDRSTRLEN) == NULL )
return "<bad IPv6 address conversion";
else
return s;
}
}
IPPrefix::IPPrefix(const in4_addr& in4, uint8_t length)
: prefix(in4), length(96 + length)
{
if ( length > 32 )
reporter->InternalError("Bad in4_addr IPPrefix length : %d", length);
prefix.Mask(this->length);
}
IPPrefix::IPPrefix(const in6_addr& in6, uint8_t length)
: prefix(in6), length(length)
{
if ( length > 128 )
reporter->InternalError("Bad in6_addr IPPrefix length : %d", length);
prefix.Mask(this->length);
}
IPPrefix::IPPrefix(const IPAddr& addr, uint8_t length)
: prefix(addr)
{
if ( prefix.GetFamily() == IPAddr::IPv4 )
{
if ( length > 32 )
reporter->InternalError("Bad IPAddr(v4) IPPrefix length : %d",
length);
this->length = length + 96;
}
else
{
if ( length > 128 )
reporter->InternalError("Bad IPAddr(v6) IPPrefix length : %d",
length);
this->length = length;
}
prefix.Mask(this->length);
}
string IPPrefix::AsString() const
{
char l[16];
if ( prefix.GetFamily() == IPAddr::IPv4 )
modp_uitoa10(length - 96, l);
else
modp_uitoa10(length, l);
return prefix.AsString() +"/" + l;
}

460
src/IPAddr.h Normal file
View file

@ -0,0 +1,460 @@
// See the file "COPYING" in the main distribution directory for copyright.
#ifndef IPADDR_H
#define IPADDR_H
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string>
#include "BroString.h"
#include "util.h"
typedef in_addr in4_addr;
/**
* Class storing both IPv4 and IPv6 addresses.
*/
class IPAddr
{
public:
/**
* Address family.
*/
enum Family { IPv4, IPv6 };
/**
* Byte order.
*/
enum ByteOrder { Host, Network };
/**
* Constructs the unspecified IPv6 address (all 128 bits zeroed).
*/
IPAddr()
{
memset(in6.s6_addr, 0, sizeof(in6.s6_addr));
}
/**
* Constructs an address instance from an IPv4 address.
*
* @param in6 The IPv6 address.
*/
IPAddr(const in4_addr& in4)
{
memcpy(in6.s6_addr, v4_mapped_prefix, sizeof(v4_mapped_prefix));
memcpy(&in6.s6_addr[12], &in4.s_addr, sizeof(in4.s_addr));
}
/**
* Constructs an address instance from an IPv6 address.
*
* @param in6 The IPv6 address.
*/
IPAddr(const in6_addr& arg_in6) : in6(arg_in6) { }
/**
* Constructs an address instance from a string representation.
*
* @param s String containing an IP address as either a dotted IPv4
* address or a hex IPv6 address.
*/
IPAddr(const std::string& s)
{
Init(s);
}
/**
* Constructs an address instance from a string representation.
*
* @param s ASCIIZ string containing an IP address as either a
* dotted IPv4 address or a hex IPv6 address.
*/
IPAddr(const char* s)
{
Init(s);
}
/**
* Constructs an address instance from a string representation.
*
* @param s String containing an IP address as either a dotted IPv4
* address or a hex IPv6 address.
*/
IPAddr(const BroString& s)
{
Init(s.CheckString());
}
/**
* Constructs an address instance from a raw byte representation.
*
* @param family The address family.
*
* @param bytes A pointer to the raw byte representation. This must point
* to 4 bytes if \a family is IPv4, and to 16 bytes if \a family is
* IPv6.
*
* @param order Indicates whether the raw representation pointed to
* by \a bytes is stored in network or host order.
*/
IPAddr(Family family, const uint32_t* bytes, ByteOrder order);
/**
* Copy constructor.
*/
IPAddr(const IPAddr& other) : in6(other.in6) { };
/**
* Destructor.
*/
~IPAddr() { };
/**
* Returns the address' family.
*/
Family GetFamily() const
{
if ( memcmp(in6.s6_addr, v4_mapped_prefix, 12) == 0 )
return IPv4;
else
return IPv6;
}
/**
* Returns true if the address represents a loopback device.
*/
bool IsLoopback() const;
/**
* Returns true if the address represents a multicast address.
*/
bool IsMulticast() const
{
if ( GetFamily() == IPv4 )
return in6.s6_addr[12] == 224;
else
return in6.s6_addr[0] == 0xff;
}
/**
* Returns true if the address represents a broadcast address.
*/
bool IsBroadcast() const
{
if ( GetFamily() == IPv4 )
return ((in6.s6_addr[12] == 0xff) && (in6.s6_addr[13] == 0xff)
&& (in6.s6_addr[14] == 0xff) && (in6.s6_addr[15] == 0xff));
else
return false;
}
/**
* Retrieves the raw byte representation of the address.
*
* @param bytes The pointer to which \a bytes points will be set to
* the address of the raw representation in network-byte order.
* The return value indicates how many 32-bit words are valid starting at
* that address. The pointer will be valid as long as the address instance
* exists.
*
* @return The number of 32-bit words the raw representation uses. This
* will be 1 for an IPv4 address and 4 for an IPv6 address.
*/
int GetBytes(const uint32_t** bytes) const
{
if ( GetFamily() == IPv4 )
{
*bytes = (uint32_t*) &in6.s6_addr[12];
return 1;
}
else
{
*bytes = (uint32_t*) in6.s6_addr;
return 4;
}
}
/**
* Retrieves a copy of the IPv6 raw byte representation of the address.
* If the internal address is IPv4, then the copied bytes use the
* IPv4 to IPv6 address mapping to return a full 16 bytes.
*
* @param bytes The pointer to a memory location in which the
* raw bytes of the address are to be copied in network byte-order.
*/
void CopyIPv6(uint32_t* bytes) const
{
memcpy(bytes, in6.s6_addr, sizeof(in6.s6_addr));
}
/**
* Masks out lower bits of the address.
*
* @param top_bits_to_keep The number of bits \a not to mask out,
* counting from the highest order bit. The value is always
* interpreted relative to the IPv6 bit width, even if the address
* is IPv4. That means if compute ``192.168.1.2/16``, you need to
* pass in 112 (i.e., 96 + 16). The value must be in the range from
* 0 to 128.
*/
void Mask(int top_bits_to_keep);
/**
* Masks out top bits of the address.
*
* @param top_bits_to_chop The number of bits to mask out, counting
* from the highest order bit. The value is always interpreted relative
* to the IPv6 bit width, even if the address is IPv4. So to mask out
* the first 16 bits of an IPv4 address, pass in 112 (i.e., 96 + 16).
* The value must be in the range from 0 to 128.
*/
void ReverseMask(int top_bits_to_chop);
/**
* Assignment operator.
*/
IPAddr& operator=(const IPAddr& other)
{
// No self-assignment check here because it's correct without it and
// makes the common case faster.
in6 = other.in6;
return *this;
}
/**
* Returns a string representation of the address. IPv4 addresses
* will be returned in dotted representation, IPv6 addresses in
* compressed hex.
*/
string AsString() const;
/**
* Returns a string representation of the address. This returns the
* same as AsString().
*/
operator std::string() const { return AsString(); }
/**
* Comparison operator for IP address.
*/
friend bool operator==(const IPAddr& addr1, const IPAddr& addr2)
{
return memcmp(&addr1.in6, &addr2.in6, sizeof(in6_addr)) == 0;
}
friend bool operator!=(const IPAddr& addr1, const IPAddr& addr2)
{
return ! (addr1 == addr2);
}
/**
* Comparison operator IP addresses. This defines a well-defined order for
* IP addresses. However, the order does not necessarily correspond to
* their numerical values.
*/
friend bool operator<(const IPAddr& addr1, const IPAddr& addr2)
{
return memcmp(&addr1.in6, &addr2.in6, sizeof(in6_addr)) < 0;
}
unsigned int MemoryAllocation() const { return padded_sizeof(*this); }
private:
/**
* Initializes an address instance from a string representation.
*
* @param s String containing an IP address as either a dotted IPv4
* address or a hex IPv6 address.
*/
void Init(const std::string& s);
in6_addr in6; // IPv6 or v4-to-v6-mapped address
static const uint8_t v4_mapped_prefix[12]; // top 96 bits of v4-mapped-addr
};
inline IPAddr::IPAddr(Family family, const uint32_t* bytes, ByteOrder order)
{
if ( family == IPv4 )
{
memcpy(in6.s6_addr, v4_mapped_prefix, sizeof(v4_mapped_prefix));
memcpy(&in6.s6_addr[12], bytes, sizeof(uint32_t));
if ( order == Host )
{
uint32_t* p = (uint32_t*) &in6.s6_addr[12];
*p = htonl(*p);
}
}
else
{
memcpy(in6.s6_addr, bytes, sizeof(in6.s6_addr));
if ( order == Host )
{
for ( unsigned int i = 0; i < 4; ++ i)
{
uint32_t* p = (uint32_t*) &in6.s6_addr[i*4];
*p = htonl(*p);
}
}
}
}
inline bool IPAddr::IsLoopback() const
{
if ( GetFamily() == IPv4 )
return in6.s6_addr[12] == 127;
else
return ((in6.s6_addr[0] == 0) && (in6.s6_addr[1] == 0)
&& (in6.s6_addr[2] == 0) && (in6.s6_addr[3] == 0)
&& (in6.s6_addr[4] == 0) && (in6.s6_addr[5] == 0)
&& (in6.s6_addr[6] == 0) && (in6.s6_addr[7] == 0)
&& (in6.s6_addr[8] == 0) && (in6.s6_addr[9] == 0)
&& (in6.s6_addr[10] == 0) && (in6.s6_addr[11] == 0)
&& (in6.s6_addr[12] == 0) && (in6.s6_addr[13] == 0)
&& (in6.s6_addr[14] == 0) && (in6.s6_addr[15] == 1));
}
/**
* Class storing both IPv4 and IPv6 prefixes
* (i.e., \c 192.168.1.1/16 and \c FD00::/8.
*/
class IPPrefix
{
public:
/**
* Constructs a prefix 0/0.
*/
IPPrefix() : length(0) {}
/**
* Constructs a prefix instance from an IPv4 address and a prefix
* length.
*
* @param in4 The IPv4 address.
*
* @param length The prefix length in the range from 0 to 32.
*/
IPPrefix(const in4_addr& in4, uint8_t length);
/**
* Constructs a prefix instance from an IPv6 address and a prefix
* length.
*
* @param in6 The IPv6 address.
*
* @param length The prefix length in the range from 0 to 128.
*/
IPPrefix(const in6_addr& in6, uint8_t length);
/**
* Constructs a prefix instance from an IPAddr object and prefix length.
*
* @param addr The IP address.
*
* @param length The prefix length in the range from 0 to 128
*/
IPPrefix(const IPAddr& addr, uint8_t length);
/**
* Copy constructor.
*/
IPPrefix(const IPPrefix& other)
: prefix(other.prefix), length(other.length) { }
/**
* Destructor.
*/
~IPPrefix() { }
/**
* Returns the prefix in the form of an IP address. The address will
* have all bits not part of the prefixed set to zero.
*/
const IPAddr& Prefix() const { return prefix; }
/**
* Returns the bit length of the prefix, relative to the 32 bits
* of an IPv4 prefix or relative to the 128 bits of an IPv6 prefix.
*/
uint8_t Length() const
{
return prefix.GetFamily() == IPAddr::IPv4 ? length - 96 : length;
}
/**
* Returns the bit length of the prefix always relative to a full
* 128 bits of an IPv6 prefix (or IPv4 mapped to IPv6).
*/
uint8_t LengthIPv6() const { return length; }
/** Returns true if the given address is part of the prefix.
*
* @param addr The address to test.
*/
bool Contains(const IPAddr& addr) const
{
IPAddr p(addr);
p.Mask(length);
return p == prefix;
}
/**
* Assignment operator.
*/
IPPrefix& operator=(const IPPrefix& other)
{
// No self-assignment check here because it's correct without it and
// makes the common case faster.
prefix = other.prefix;
length = other.length;
return *this;
}
/**
* Returns a string representation of the prefix. IPv4 addresses
* will be returned in dotted representation, IPv6 addresses in
* compressed hex.
*/
string AsString() const;
operator std::string() const { return AsString(); }
unsigned int MemoryAllocation() const { return padded_sizeof(*this); }
/**
* Comparison operator for IP prefix.
*/
friend bool operator==(const IPPrefix& net1, const IPPrefix& net2)
{
return net1.Prefix() == net2.Prefix() && net1.Length() == net2.Length();
}
/**
* Comparison operator IP prefixes. This defines a well-defined order for
* IP prefix. However, the order does not necessarily corresponding to their
* numerical values.
*/
friend bool operator<(const IPPrefix& net1, const IPPrefix& net2)
{
if ( net1.Prefix() < net2.Prefix() )
return true;
else if ( net1.Prefix() == net2.Prefix() )
return net1.Length() < net2.Length();
else
return false;
}
private:
IPAddr prefix; // We store it as an address with the non-prefix bits masked out via Mask().
uint8_t length; // The bit length of the prefix relative to full IPv6 addr.
};
#endif

View file

@ -101,6 +101,12 @@ LogVal::~LogVal()
&& present )
delete val.string_val;
if ( type == TYPE_ADDR && present )
delete val.addr_val;
if ( type == TYPE_SUBNET && present )
delete val.subnet_val;
if ( type == TYPE_TABLE && present )
{
for ( int i = 0; i < val.set_val.size; i++ )
@ -193,40 +199,21 @@ bool LogVal::Read(SerializationFormat* fmt)
case TYPE_SUBNET:
{
uint32 net[4];
if ( ! (fmt->Read(&net[0], "net0") &&
fmt->Read(&net[1], "net1") &&
fmt->Read(&net[2], "net2") &&
fmt->Read(&net[3], "net3") &&
fmt->Read(&val.subnet_val.width, "width")) )
IPPrefix prefix;
if ( ! fmt->Read(&prefix, "subnet") )
return false;
#ifdef BROv6
val.subnet_val.net[0] = net[0];
val.subnet_val.net[1] = net[1];
val.subnet_val.net[2] = net[2];
val.subnet_val.net[3] = net[3];
#else
val.subnet_val.net = net[0];
#endif
val.subnet_val = new IPPrefix(prefix);
return true;
}
case TYPE_ADDR:
{
uint32 addr[4];
if ( ! (fmt->Read(&addr[0], "addr0") &&
fmt->Read(&addr[1], "addr1") &&
fmt->Read(&addr[2], "addr2") &&
fmt->Read(&addr[3], "addr3")) )
IPAddr addr;
if ( ! fmt->Read(&addr, "net") )
return false;
val.addr_val[0] = addr[0];
#ifdef BROv6
val.addr_val[1] = addr[1];
val.addr_val[2] = addr[2];
val.addr_val[3] = addr[3];
#endif
val.addr_val = new IPAddr(addr);
return true;
}
@ -307,40 +294,11 @@ bool LogVal::Write(SerializationFormat* fmt) const
return fmt->Write(val.uint_val, "uint");
case TYPE_SUBNET:
{
uint32 net[4];
#ifdef BROv6
net[0] = val.subnet_val.net[0];
net[1] = val.subnet_val.net[1];
net[2] = val.subnet_val.net[2];
net[3] = val.subnet_val.net[3];
#else
net[0] = val.subnet_val.net;
net[1] = net[2] = net[3] = 0;
#endif
return fmt->Write(net[0], "net0") &&
fmt->Write(net[1], "net1") &&
fmt->Write(net[2], "net2") &&
fmt->Write(net[3], "net3") &&
fmt->Write(val.subnet_val.width, "width");
}
return fmt->Write(*val.subnet_val, "subnet");
case TYPE_ADDR:
{
uint32 addr[4];
addr[0] = val.addr_val[0];
#ifdef BROv6
addr[1] = val.addr_val[1];
addr[2] = val.addr_val[2];
addr[3] = val.addr_val[3];
#else
addr[1] = addr[2] = addr[3] = 0;
#endif
return fmt->Write(addr[0], "addr0") &&
fmt->Write(addr[1], "addr1") &&
fmt->Write(addr[2], "addr2") &&
fmt->Write(addr[3], "addr3");
}
return fmt->Write(*val.addr_val, "addr");
case TYPE_DOUBLE:
case TYPE_TIME:
@ -1107,17 +1065,12 @@ LogVal* LogMgr::ValToLogVal(Val* val, BroType* ty)
break;
case TYPE_SUBNET:
lval->val.subnet_val = *val->AsSubNet();
lval->val.subnet_val = new IPPrefix(val->AsSubNet());
break;
case TYPE_ADDR:
{
addr_type t = val->AsAddr();
#ifdef BROv6
copy_addr(t, lval->val.addr_val);
#else
copy_addr(&t, lval->val.addr_val);
#endif
lval->val.addr_val = new IPAddr(val->AsAddr());
break;
}

View file

@ -8,6 +8,7 @@
#include "Val.h"
#include "EventHandler.h"
#include "RemoteSerializer.h"
#include "IPAddr.h"
class SerializationFormat;
@ -40,8 +41,8 @@ struct LogVal {
union _val {
bro_int_t int_val;
bro_uint_t uint_val;
uint32 addr_val[NUM_ADDR_WORDS];
subnet_type subnet_val;
IPAddr* addr_val;
IPPrefix* subnet_val;
double double_val;
string* string_val;
set_t set_val;

View file

@ -166,13 +166,11 @@ bool LogWriterAscii::DoWriteOne(ODesc* desc, LogVal* val, const LogField* field)
break;
case TYPE_SUBNET:
desc->Add(dotted_addr(val->val.subnet_val.net));
desc->Add("/");
desc->Add(val->val.subnet_val.width);
desc->Add(*val->val.subnet_val);
break;
case TYPE_ADDR:
desc->Add(dotted_addr(val->val.addr_val));
desc->Add(*val->val.addr_val);
break;
case TYPE_TIME:

View file

@ -63,9 +63,11 @@ OSFingerprint::OSFingerprint(FingerprintMode arg_mode)
}
}
bool OSFingerprint::CacheMatch(uint32 addr, int id)
bool OSFingerprint::CacheMatch(const IPAddr& addr, int id)
{
HashKey key = HashKey(&addr, 1);
uint32 bytes[4];
addr.CopyIPv6(bytes);
HashKey key = HashKey(bytes, 4);
int* pid = new int;
*pid=id;
int* prev = os_matches.Insert(&key, pid);

View file

@ -14,6 +14,7 @@
#include "util.h"
#include "Dict.h"
#include "Reporter.h"
#include "IPAddr.h"
// Size limit for size wildcards.
#define PACKET_BIG 100
@ -88,7 +89,7 @@ public:
int FindMatch(struct os_type* retval, uint16 tot, uint8 DF_flag,
uint8 TTL, uint16 WSS, uint8 ocnt, uint8* op, uint16 MSS,
uint8 win_scale, uint32 tstamp, uint32 quirks, uint8 ECN) const;
bool CacheMatch(uint32 addr, int id);
bool CacheMatch(const IPAddr& addr, int id);
int Get_OS_From_SYN(struct os_type* retval,
uint16 tot, uint8 DF_flag, uint8 TTL, uint16 WSS,

View file

@ -199,17 +199,21 @@ void PIA_TCP::FirstPacket(bool is_orig, const IP_Hdr* ip)
ip4_hdr = new IP_Hdr((const struct ip*) ip4);
}
const uint32* obytes;
const uint32* rbytes;
Conn()->OrigAddr().GetBytes(&obytes);
Conn()->RespAddr().GetBytes(&rbytes);
if ( is_orig )
{
copy_addr(Conn()->OrigAddr(), &ip4->ip_src.s_addr);
copy_addr(Conn()->RespAddr(), &ip4->ip_dst.s_addr);
memcpy(&ip4->ip_src.s_addr, obytes, sizeof(uint32));
memcpy(&ip4->ip_dst.s_addr, rbytes, sizeof(uint32));
tcp4->th_sport = htons(Conn()->OrigPort());
tcp4->th_dport = htons(Conn()->RespPort());
}
else
{
copy_addr(Conn()->RespAddr(), &ip4->ip_src.s_addr);
copy_addr(Conn()->OrigAddr(), &ip4->ip_dst.s_addr);
memcpy(&ip4->ip_src.s_addr, rbytes, sizeof(uint32));
memcpy(&ip4->ip_dst.s_addr, obytes, sizeof(uint32));
tcp4->th_sport = htons(Conn()->RespPort());
tcp4->th_dport = htons(Conn()->OrigPort());
}

View file

@ -1,11 +1,11 @@
#include "PacketFilter.h"
void PacketFilter::AddSrc(addr_type src, uint32 tcp_flags, double probability)
void PacketFilter::AddSrc(const IPAddr& src, uint32 tcp_flags, double probability)
{
Filter* f = new Filter;
f->tcp_flags = tcp_flags;
f->probability = uint32(probability * RAND_MAX);
src_filter.Insert(src, NUM_ADDR_WORDS * 32, f);
src_filter.Insert(src, 128, f);
}
void PacketFilter::AddSrc(Val* src, uint32 tcp_flags, double probability)
@ -16,12 +16,12 @@ void PacketFilter::AddSrc(Val* src, uint32 tcp_flags, double probability)
src_filter.Insert(src, f);
}
void PacketFilter::AddDst(addr_type dst, uint32 tcp_flags, double probability)
void PacketFilter::AddDst(const IPAddr& dst, uint32 tcp_flags, double probability)
{
Filter* f = new Filter;
f->tcp_flags = tcp_flags;
f->probability = uint32(probability * RAND_MAX);
dst_filter.Insert(dst, NUM_ADDR_WORDS * 32, f);
dst_filter.Insert(dst, 128, f);
}
void PacketFilter::AddDst(Val* dst, uint32 tcp_flags, double probability)
@ -32,9 +32,9 @@ void PacketFilter::AddDst(Val* dst, uint32 tcp_flags, double probability)
dst_filter.Insert(dst, f);
}
bool PacketFilter::RemoveSrc(addr_type src)
bool PacketFilter::RemoveSrc(const IPAddr& src)
{
return src_filter.Remove(src, NUM_ADDR_WORDS * 32) != 0;
return src_filter.Remove(src, 128) != 0;
}
bool PacketFilter::RemoveSrc(Val* src)
@ -42,9 +42,9 @@ bool PacketFilter::RemoveSrc(Val* src)
return src_filter.Remove(src) != NULL;
}
bool PacketFilter::RemoveDst(addr_type dst)
bool PacketFilter::RemoveDst(const IPAddr& dst)
{
return dst_filter.Remove(dst, NUM_ADDR_WORDS * 32) != NULL;
return dst_filter.Remove(dst, 128) != NULL;
}
bool PacketFilter::RemoveDst(Val* dst)
@ -54,21 +54,11 @@ bool PacketFilter::RemoveDst(Val* dst)
bool PacketFilter::Match(const IP_Hdr* ip, int len, int caplen)
{
#ifdef BROv6
Filter* f = (Filter*) src_filter.Lookup(ip->SrcAddr(),
NUM_ADDR_WORDS * 32);
#else
Filter* f = (Filter*) src_filter.Lookup(*ip->SrcAddr(),
NUM_ADDR_WORDS * 32);
#endif
Filter* f = (Filter*) src_filter.Lookup(ip->SrcAddr(), 128);
if ( f )
return MatchFilter(*f, *ip, len, caplen);
#ifdef BROv6
f = (Filter*) dst_filter.Lookup(ip->DstAddr(), NUM_ADDR_WORDS * 32);
#else
f = (Filter*) dst_filter.Lookup(*ip->DstAddr(), NUM_ADDR_WORDS * 32);
#endif
f = (Filter*) dst_filter.Lookup(ip->DstAddr(), 128);
if ( f )
return MatchFilter(*f, *ip, len, caplen);

View file

@ -14,16 +14,16 @@ public:
// Drops all packets from a particular source (which may be given
// as an AddrVal or a SubnetVal) which hasn't any of TCP flags set
// (TH_*) with the given probability (from 0..MAX_PROB).
void AddSrc(addr_type src, uint32 tcp_flags, double probability);
void AddSrc(const IPAddr& src, uint32 tcp_flags, double probability);
void AddSrc(Val* src, uint32 tcp_flags, double probability);
void AddDst(addr_type src, uint32 tcp_flags, double probability);
void AddDst(const IPAddr& src, uint32 tcp_flags, double probability);
void AddDst(Val* src, uint32 tcp_flags, double probability);
// Removes the filter entry for the given src/dst
// Returns false if filter doesn not exist.
bool RemoveSrc(addr_type src);
bool RemoveSrc(const IPAddr& src);
bool RemoveSrc(Val* dst);
bool RemoveDst(addr_type dst);
bool RemoveDst(const IPAddr& dst);
bool RemoveDst(Val* dst);
// Returns true if packet matches a drop filter

View file

@ -1,34 +1,21 @@
#include "PrefixTable.h"
#include "Reporter.h"
// IPv4 version.
inline static prefix_t* make_prefix(const uint32 addr, int width)
inline static prefix_t* make_prefix(const IPAddr& addr, int width)
{
prefix_t* prefix = (prefix_t*) safe_malloc(sizeof(prefix_t));
memcpy(&prefix->add.sin, &addr, sizeof(prefix->add.sin)) ;
prefix->family = AF_INET;
prefix->bitlen = width;
prefix->ref_count = 1;
return prefix;
}
#ifdef BROv6
inline static prefix_t* make_prefix(const uint32* addr, int width)
{
prefix_t* prefix = (prefix_t*) safe_malloc(sizeof(prefix_t));
memcpy(&prefix->add.sin6, addr, 4 * sizeof(uint32));
uint32 bytes[4];
addr.CopyIPv6(bytes);
memcpy(&prefix->add.sin6, bytes, 4 * sizeof(uint32));
prefix->family = AF_INET6;
prefix->bitlen = width;
prefix->ref_count = 1;
return prefix;
}
#endif
void* PrefixTable::Insert(const_addr_type addr, int width, void* data)
void* PrefixTable::Insert(const IPAddr& addr, int width, void* data)
{
prefix_t* prefix = make_prefix(addr, width);
patricia_node_t* node = patricia_lookup(tree, prefix);
@ -55,12 +42,12 @@ void* PrefixTable::Insert(const Val* value, void* data)
switch ( value->Type()->Tag() ) {
case TYPE_ADDR:
return Insert(value->AsAddr(), NUM_ADDR_WORDS * 32, data);
return Insert(value->AsAddr(), 128, data);
break;
case TYPE_SUBNET:
return Insert(value->AsSubNet()->net,
value->AsSubNet()->width, data);
return Insert(value->AsSubNet().Prefix(),
value->AsSubNet().LengthIPv6(), data);
break;
default:
@ -69,7 +56,7 @@ void* PrefixTable::Insert(const Val* value, void* data)
}
}
void* PrefixTable::Lookup(const_addr_type addr, int width, bool exact) const
void* PrefixTable::Lookup(const IPAddr& addr, int width, bool exact) const
{
prefix_t* prefix = make_prefix(addr, width);
patricia_node_t* node =
@ -89,12 +76,12 @@ void* PrefixTable::Lookup(const Val* value, bool exact) const
switch ( value->Type()->Tag() ) {
case TYPE_ADDR:
return Lookup(value->AsAddr(), NUM_ADDR_WORDS * 32, exact);
return Lookup(value->AsAddr(), 128, exact);
break;
case TYPE_SUBNET:
return Lookup(value->AsSubNet()->net,
value->AsSubNet()->width, exact);
return Lookup(value->AsSubNet().Prefix(),
value->AsSubNet().LengthIPv6(), exact);
break;
default:
@ -104,7 +91,7 @@ void* PrefixTable::Lookup(const Val* value, bool exact) const
}
}
void* PrefixTable::Remove(const_addr_type addr, int width)
void* PrefixTable::Remove(const IPAddr& addr, int width)
{
prefix_t* prefix = make_prefix(addr, width);
patricia_node_t* node = patricia_search_exact(tree, prefix);
@ -128,11 +115,12 @@ void* PrefixTable::Remove(const Val* value)
switch ( value->Type()->Tag() ) {
case TYPE_ADDR:
return Remove(value->AsAddr(), NUM_ADDR_WORDS * 32);
return Remove(value->AsAddr(), 128);
break;
case TYPE_SUBNET:
return Remove(value->AsSubNet()->net, value->AsSubNet()->width);
return Remove(value->AsSubNet().Prefix(),
value->AsSubNet().LengthIPv6());
break;
default:

View file

@ -3,6 +3,7 @@
#include "Val.h"
#include "net_util.h"
#include "IPAddr.h"
extern "C" {
#include "patricia.h"
@ -24,7 +25,7 @@ public:
// Addr in network byte order. If data is zero, acts like a set.
// Returns ptr to old data if already existing.
// For existing items without data, returns non-nil if found.
void* Insert(const_addr_type addr, int width, void* data = 0);
void* Insert(const IPAddr& addr, int width, void* data = 0);
// Value may be addr or subnet.
void* Insert(const Val* value, void* data = 0);
@ -32,11 +33,11 @@ public:
// Returns nil if not found, pointer to data otherwise.
// For items without data, returns non-nil if found.
// If exact is false, performs exact rather than longest-prefix match.
void* Lookup(const_addr_type addr, int width, bool exact = false) const;
void* Lookup(const IPAddr& addr, int width, bool exact = false) const;
void* Lookup(const Val* value, bool exact = false) const;
// Returns pointer to data or nil if not found.
void* Remove(const_addr_type addr, int width);
void* Remove(const IPAddr& addr, int width);
void* Remove(const Val* value);
void Clear() { Clear_Patricia(tree, 0); }

View file

@ -43,7 +43,7 @@ DataBlock::DataBlock(const u_char* data, int size, int arg_seq,
unsigned int Reassembler::total_size = 0;
Reassembler::Reassembler(int init_seq, const uint32* ip_addr,
Reassembler::Reassembler(int init_seq, const IPAddr& ip_addr,
ReassemblerType arg_type)
{
blocks = last_block = 0;

View file

@ -4,6 +4,7 @@
#define reassem_h
#include "Obj.h"
#include "IPAddr.h"
class DataBlock {
public:
@ -25,7 +26,7 @@ enum ReassemblerType { REASSEM_IP, REASSEM_TCP };
class Reassembler : public BroObj {
public:
Reassembler(int init_seq, const uint32* ip_addr,
Reassembler(int init_seq, const IPAddr& ip_addr,
ReassemblerType arg_type);
virtual ~Reassembler();

View file

@ -185,6 +185,7 @@
#include "Conn.h"
#include "LogMgr.h"
#include "Reporter.h"
#include "IPAddr.h"
extern "C" {
#include "setsignal.h"
@ -670,8 +671,8 @@ void RemoteSerializer::Fork()
}
}
RemoteSerializer::PeerID RemoteSerializer::Connect(addr_type ip, uint16 port,
const char* our_class, double retry, bool use_ssl)
RemoteSerializer::PeerID RemoteSerializer::Connect(const IPAddr& ip,
uint16 port, const char* our_class, double retry, bool use_ssl)
{
if ( ! using_communication )
return true;
@ -679,16 +680,12 @@ RemoteSerializer::PeerID RemoteSerializer::Connect(addr_type ip, uint16 port,
if ( ! initialized )
reporter->InternalError("remote serializer not initialized");
#ifdef BROv6
if ( ! is_v4_addr(ip) )
if ( ip.GetFamily() == IPAddr::IPv6 )
Error("inter-Bro communication not supported over IPv6");
uint32 ip4 = to_v4_addr(ip);
#else
uint32 ip4 = ip;
#endif
ip4 = ntohl(ip4);
const uint32* bytes;
ip.GetBytes(&bytes);
uint32 ip4 = ntohl(*bytes);
if ( ! child_pid )
Fork();
@ -1232,7 +1229,7 @@ bool RemoteSerializer::SendCapabilities(Peer* peer)
return caps ? SendToChild(MSG_CAPS, peer, 3, caps, 0, 0) : true;
}
bool RemoteSerializer::Listen(addr_type ip, uint16 port, bool expect_ssl)
bool RemoteSerializer::Listen(const IPAddr& ip, uint16 port, bool expect_ssl)
{
if ( ! using_communication )
return true;
@ -1240,16 +1237,12 @@ bool RemoteSerializer::Listen(addr_type ip, uint16 port, bool expect_ssl)
if ( ! initialized )
reporter->InternalError("remote serializer not initialized");
#ifdef BROv6
if ( ! is_v4_addr(ip) )
if ( ip.GetFamily() == IPAddr::IPv6 )
Error("inter-Bro communication not supported over IPv6");
uint32 ip4 = to_v4_addr(ip);
#else
uint32 ip4 = ip;
#endif
ip4 = ntohl(ip4);
const uint32* bytes;
ip.GetBytes(&bytes);
uint32 ip4 = ntohl(*bytes);
if ( ! SendToChild(MSG_LISTEN, 0, 3, ip4, port, expect_ssl) )
return false;

View file

@ -32,7 +32,7 @@ public:
static const PeerID PEER_NONE = SOURCE_LOCAL;
// Connect to host (returns PEER_NONE on error).
PeerID Connect(addr_type ip, uint16 port, const char* our_class, double retry, bool use_ssl);
PeerID Connect(const IPAddr& ip, uint16 port, const char* our_class, double retry, bool use_ssl);
// Close connection to host.
bool CloseConnection(PeerID peer);
@ -60,7 +60,7 @@ public:
bool CompleteHandshake(PeerID peer);
// Start to listen.
bool Listen(addr_type ip, uint16 port, bool expect_ssl);
bool Listen(const IPAddr& ip, uint16 port, bool expect_ssl);
// Stop it.
bool StopListening();

View file

@ -155,7 +155,7 @@ void Reporter::WeirdHelper(EventHandlerPtr event, Val* conn_val, const char* add
delete vl;
}
void Reporter::WeirdFlowHelper(const uint32* orig, const uint32* resp, const char* fmt_name, ...)
void Reporter::WeirdFlowHelper(const IPAddr& orig, const IPAddr& resp, const char* fmt_name, ...)
{
val_list* vl = new val_list(2);
vl->append(new AddrVal(orig));
@ -184,7 +184,7 @@ void Reporter::Weird(Val* conn_val, const char* name, const char* addl)
WeirdHelper(conn_weird, conn_val, addl, "%s", name);
}
void Reporter::Weird(const uint32* orig, const uint32* resp, const char* name)
void Reporter::Weird(const IPAddr& orig, const IPAddr& resp, const char* name)
{
WeirdFlowHelper(orig, resp, "%s", name);
}

View file

@ -11,6 +11,7 @@
#include "util.h"
#include "net_util.h"
#include "EventHandler.h"
#include "IPAddr.h"
class Connection;
class Location;
@ -74,7 +75,7 @@ public:
void Weird(const char* name); // Raises net_weird().
void Weird(Connection* conn, const char* name, const char* addl = ""); // Raises conn_weird().
void Weird(Val* conn_val, const char* name, const char* addl = ""); // Raises conn_weird().
void Weird(const uint32* orig, const uint32* resp, const char* name); // Raises flow_weird().
void Weird(const IPAddr& orig, const IPAddr& resp, const char* name); // Raises flow_weird().
// Syslog a message. This methods does nothing if we're running
// offline from a trace.
@ -121,7 +122,7 @@ private:
// The order if addl, name needs to be like that since fmt_name can
// contain format specifiers
void WeirdHelper(EventHandlerPtr event, Val* conn_val, const char* addl, const char* fmt_name, ...);
void WeirdFlowHelper(const uint32* orig, const uint32* resp, const char* fmt_name, ...);
void WeirdFlowHelper(const IPAddr& orig, const IPAddr& resp, const char* fmt_name, ...);
int errors;
bool via_events;

View file

@ -1067,16 +1067,22 @@ static bool val_to_maskedval(Val* v, maskedvalue_list* append_to)
break;
case TYPE_SUBNET:
#ifdef BROv6
{
uint32* n = v->AsSubNet()->net;
uint32* m = v->AsSubNetVal()->Mask();
const uint32* n;
uint32 m[4];
v->AsSubNet().Prefix().GetBytes(&n);
v->AsSubNetVal()->Mask().CopyIPv6(m);
for ( unsigned int i = 0; i < 4; ++i )
m[i] = ntohl(m[i]);
bool is_v4_mask = m[0] == 0xffffffff &&
m[1] == m[0] && m[2] == m[0];
if ( is_v4_addr(n) && is_v4_mask )
if ( v->AsSubNet().Prefix().GetFamily() == IPAddr::IPv4 &&
is_v4_mask )
{
mval->val = ntohl(to_v4_addr(n));
mval->val = ntohl(*n);
mval->mask = m[3];
}
@ -1087,10 +1093,6 @@ static bool val_to_maskedval(Val* v, maskedvalue_list* append_to)
mval->mask = 0;
}
}
#else
mval->val = ntohl(v->AsSubNet()->net);
mval->mask = v->AsSubNetVal()->Mask();
#endif
break;
default:

View file

@ -50,23 +50,24 @@ void SSH_Analyzer::DeliverStream(int length, const u_char* data, bool is_orig)
// SSH-<protocolmajor>.<protocolminor>-<version>\n
//
// We're interested in the "version" part here.
if ( length < 4 || memcmp(line, "SSH-", 4) != 0 )
{
Weird("malformed_ssh_identification");
ProtocolViolation("malformed ssh identification", line, length);
return;
}
int i;
for ( i = 4; i < length && line[i] != '-'; ++i )
;
if ( TCP() )
{
if ( length >= i )
{
const uint32* dst;
IPAddr dst;
if ( is_orig )
dst = TCP()->Orig()->dst_addr;
else

View file

@ -230,6 +230,45 @@ bool BinarySerializationFormat::Read(string* v, const char* tag)
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(IPAddr::IPv4, raw, IPAddr::Network);
else
*addr = IPAddr(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::Write(char v, const char* tag)
{
DBG_LOG(DBG_SERIAL, "Write char %s [%s]", fmt_bytes(&v, 1), tag);
@ -299,6 +338,30 @@ 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::WriteOpenTag(const char* tag)
{
return true;
@ -389,6 +452,18 @@ bool XMLSerializationFormat::Read(string* s, const char* tag)
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::Write(char v, const char* tag)
{
return WriteElem(tag, "char", &v, 1);
@ -469,6 +544,18 @@ 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::WriteEncodedString(const char* s, int len)
{
while ( len-- )

View file

@ -28,6 +28,8 @@ public:
virtual bool Read(bool* v, const char* tag) = 0;
virtual bool Read(double* d, const char* tag) = 0;
virtual bool Read(string* s, const char* tag) = 0;
virtual bool Read(IPAddr* addr, const char* tag) = 0;
virtual bool Read(IPPrefix* prefix, const char* tag) = 0;
// Returns number of raw bytes read since last call to StartRead().
int BytesRead() const { return bytes_read; }
@ -50,6 +52,8 @@ public:
virtual bool Write(const char* s, const char* tag) = 0;
virtual bool Write(const char* buf, int len, const char* tag) = 0;
virtual bool Write(const string& s, const char* tag) = 0;
virtual bool Write(const IPAddr& addr, const char* tag) = 0;
virtual bool Write(const IPPrefix& prefix, const char* tag) = 0;
virtual bool WriteOpenTag(const char* tag) = 0;
virtual bool WriteCloseTag(const char* tag) = 0;
@ -90,6 +94,8 @@ public:
virtual bool Read(double* d, const char* tag);
virtual bool Read(char** str, int* len, const char* tag);
virtual bool Read(string* s, const char* tag);
virtual bool Read(IPAddr* addr, const char* tag);
virtual bool Read(IPPrefix* prefix, const char* tag);
virtual bool Write(int v, const char* tag);
virtual bool Write(uint16 v, const char* tag);
virtual bool Write(uint32 v, const char* tag);
@ -101,6 +107,8 @@ public:
virtual bool Write(const char* s, const char* tag);
virtual bool Write(const char* buf, int len, const char* tag);
virtual bool Write(const string& s, const char* tag);
virtual bool Write(const IPAddr& addr, const char* tag);
virtual bool Write(const IPPrefix& prefix, const char* tag);
virtual bool WriteOpenTag(const char* tag);
virtual bool WriteCloseTag(const char* tag);
virtual bool WriteSeparator();
@ -123,6 +131,8 @@ public:
virtual bool Write(const char* s, const char* tag);
virtual bool Write(const char* buf, int len, const char* tag);
virtual bool Write(const string& s, const char* tag);
virtual bool Write(const IPAddr& addr, const char* tag);
virtual bool Write(const IPPrefix& prefix, const char* tag);
virtual bool WriteOpenTag(const char* tag);
virtual bool WriteCloseTag(const char* tag);
virtual bool WriteSeparator();
@ -138,6 +148,8 @@ public:
virtual bool Read(double* d, const char* tag);
virtual bool Read(char** str, int* len, const char* tag);
virtual bool Read(string* s, const char* tag);
virtual bool Read(IPAddr* addr, const char* tag);
virtual bool Read(IPPrefix* prefix, const char* tag);
private:
// Encodes non-printable characters.

View file

@ -1103,9 +1103,9 @@ void EventPlayer::Process()
void Packet::Describe(ODesc* d) const
{
const IP_Hdr ip = IP();
d->Add(dotted_addr(ip.SrcAddr()));
d->Add(ip.SrcAddr());
d->Add("->");
d->Add(dotted_addr(ip.DstAddr()));
d->Add(ip.DstAddr());
}
bool Packet::Serialize(SerialInfo* info) const

View file

@ -69,6 +69,8 @@ public:
{ return format->Read(const_cast<char**>(str), len, tag); }
bool Read(string* s, const char* tag);
bool Read(IPAddr* a, const char* tag) { return format->Read(a, tag); }
bool Read(IPPrefix* p, const char* tag) { return format->Read(p, tag); }
bool Write(const char* s, const char* tag)
{ return format->Write(s, tag); }
@ -76,6 +78,8 @@ public:
{ return format->Write(buf, len, tag); }
bool Write(const string& s, const char* tag)
{ return format->Write(s.data(), s.size(), tag); }
bool Write(const IPAddr& a, const char* tag) { return format->Write(a, tag); }
bool Write(const IPPrefix& p, const char* tag) { return format->Write(p, tag); }
bool WriteOpenTag(const char* tag)
{ return format->WriteOpenTag(tag); }

View file

@ -71,8 +71,8 @@ void TimerMgrExpireTimer::Dispatch(double t, int is_expire)
NetSessions::NetSessions()
{
TypeList* t = new TypeList();
t->Append(base_type(TYPE_COUNT)); // source IP address
t->Append(base_type(TYPE_COUNT)); // dest IP address
t->Append(base_type(TYPE_ADDR)); // source IP address
t->Append(base_type(TYPE_ADDR)); // dest IP address
t->Append(base_type(TYPE_COUNT)); // source and dest ports
ch = new CompositeHash(t);
@ -280,18 +280,22 @@ void NetSessions::NextPacket(double t, const struct pcap_pkthdr* hdr,
DoNextPacket(t, hdr, &ip_hdr, pkt, hdr_size);
}
else if ( arp_analyzer && arp_analyzer->IsARP(pkt, hdr_size) )
arp_analyzer->NextPacket(t, hdr, pkt, hdr_size);
else if ( ip->ip_v == 6 )
{
IP_Hdr ip_hdr((const struct ip6_hdr*) (pkt + hdr_size));
DoNextPacket(t, hdr, &ip_hdr, pkt, hdr_size);
}
else if ( ARP_Analyzer::IsARP(pkt, hdr_size) )
{
if ( arp_analyzer )
arp_analyzer->NextPacket(t, hdr, pkt, hdr_size);
}
else
{
#ifdef BROv6
IP_Hdr ip_hdr((const struct ip6_hdr*) (pkt + hdr_size));
DoNextPacket(t, hdr, &ip_hdr, pkt, hdr_size);
#else
Weird("non_IPv4_packet", hdr, pkt);
Weird("unknown_packet_type", hdr, pkt);
return;
#endif
}
}
@ -629,8 +633,8 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr,
int record_packet = 1; // whether to record the packet at all
int record_content = 1; // whether to record its data
int is_orig = addr_eq(id.src_addr, conn->OrigAddr()) &&
id.src_port == conn->OrigPort();
int is_orig = (id.src_addr == conn->OrigAddr()) &&
(id.src_port == conn->OrigPort());
if ( new_packet && ip4 )
conn->Event(new_packet, 0, BuildHeader(ip4));
@ -769,13 +773,11 @@ Val* NetSessions::BuildHeader(const struct ip* ip)
FragReassembler* NetSessions::NextFragment(double t, const IP_Hdr* ip,
const u_char* pkt, uint32 frag_field)
{
uint32 src_addr = uint32(ip->SrcAddr4());
uint32 dst_addr = uint32(ip->DstAddr4());
uint32 frag_id = ntohs(ip->ID4()); // we actually could skip conv.
ListVal* key = new ListVal(TYPE_ANY);
key->Append(new Val(src_addr, TYPE_COUNT));
key->Append(new Val(dst_addr, TYPE_COUNT));
key->Append(new AddrVal(ip->SrcAddr()));
key->Append(new AddrVal(ip->DstAddr()));
key->Append(new Val(frag_id, TYPE_COUNT));
HashKey* h = ch->ComputeHash(key, 1);
@ -810,7 +812,7 @@ int NetSessions::Get_OS_From_SYN(struct os_type* retval,
quirks, ECN) : 0;
}
bool NetSessions::CompareWithPreviousOSMatch(uint32 addr, int id) const
bool NetSessions::CompareWithPreviousOSMatch(const IPAddr& addr, int id) const
{
return SYN_OS_Fingerprinter ?
SYN_OS_Fingerprinter->CacheMatch(addr, id) : 0;
@ -851,21 +853,16 @@ Connection* NetSessions::FindConnection(Val* v)
// types, too.
}
addr_type orig_addr = (*vl)[orig_h]->AsAddr();
addr_type resp_addr = (*vl)[resp_h]->AsAddr();
const IPAddr& orig_addr = (*vl)[orig_h]->AsAddr();
const IPAddr& resp_addr = (*vl)[resp_h]->AsAddr();
PortVal* orig_portv = (*vl)[orig_p]->AsPortVal();
PortVal* resp_portv = (*vl)[resp_p]->AsPortVal();
ConnID id;
#ifdef BROv6
id.src_addr = orig_addr;
id.dst_addr = resp_addr;
#else
id.src_addr = &orig_addr;
id.dst_addr = &resp_addr;
#endif
id.src_port = htons((unsigned short) orig_portv->Port());
id.dst_port = htons((unsigned short) resp_portv->Port());
@ -1133,7 +1130,7 @@ Connection* NetSessions::NewConn(HashKey* k, double t, const ConnID* id,
// an analyzable connection.
ConnID flip_id = *id;
const uint32* ta = flip_id.src_addr;
const IPAddr ta = flip_id.src_addr;
flip_id.src_addr = flip_id.dst_addr;
flip_id.dst_addr = ta;

View file

@ -87,7 +87,7 @@ public:
uint32 tstamp, /* uint8 TOS, */ uint32 quirks,
uint8 ECN) const;
bool CompareWithPreviousOSMatch(uint32 addr, int id) const;
bool CompareWithPreviousOSMatch(const IPAddr& addr, int id) const;
// Looks up the connection referred to by the given Val,
// which should be a conn_id record. Returns nil if there's

View file

@ -276,7 +276,7 @@ void TCP_Analyzer::ProcessSYN(const IP_Hdr* ip, const struct tcphdr* tp,
uint32 tcp_hdr_len, int& seq_len,
TCP_Endpoint* endpoint, TCP_Endpoint* peer,
uint32 base_seq, uint32 ack_seq,
const uint32* orig_addr,
const IPAddr& orig_addr,
int is_orig, TCP_Flags flags)
{
int len = seq_len;
@ -346,7 +346,7 @@ void TCP_Analyzer::ProcessSYN(const IP_Hdr* ip, const struct tcphdr* tp,
// is_orig will be removed once we can do SYN-ACK fingerprinting.
if ( OS_version_found && is_orig )
{
Val src_addr_val(orig_addr, TYPE_ADDR);
AddrVal src_addr_val(orig_addr);
if ( generate_OS_version_event->Size() == 0 ||
generate_OS_version_event->Lookup(&src_addr_val) )
{
@ -414,7 +414,7 @@ int TCP_Analyzer::ProcessFlags(double t,
uint32 tcp_hdr_len, int len, int& seq_len,
TCP_Endpoint* endpoint, TCP_Endpoint* peer,
uint32 base_seq, uint32 ack_seq,
const uint32* orig_addr,
const IPAddr& orig_addr,
int is_orig, TCP_Flags flags)
{
if ( flags.SYN() )
@ -989,8 +989,8 @@ void TCP_Analyzer::DeliverPacket(int len, const u_char* data, bool is_orig,
if ( ! orig->did_close || ! resp->did_close )
Conn()->SetLastTime(t);
const uint32* orig_addr = Conn()->OrigAddr();
const uint32* resp_addr = Conn()->RespAddr();
const IPAddr orig_addr = Conn()->OrigAddr();
const IPAddr resp_addr = Conn()->RespAddr();
uint32 tcp_hdr_len = data - (const u_char*) tp;
@ -1331,7 +1331,7 @@ RecordVal* TCP_Analyzer::BuildOSVal(int is_orig, const IP_Hdr* ip,
tstamp, quirks,
uint8(tcp->th_flags & (TH_ECE|TH_CWR)));
if ( sessions->CompareWithPreviousOSMatch(ip->SrcAddr4(), id) )
if ( sessions->CompareWithPreviousOSMatch(ip->SrcAddr(), id) )
{
RecordVal* os = new RecordVal(OS_version);

View file

@ -6,6 +6,7 @@
#include "Analyzer.h"
#include "TCP.h"
#include "PacketDumper.h"
#include "IPAddr.h"
// We define two classes here:
// - TCP_Analyzer is the analyzer for the TCP protocol itself.
@ -128,7 +129,7 @@ protected:
uint32 tcp_hdr_len, int& seq_len,
TCP_Endpoint* endpoint, TCP_Endpoint* peer,
uint32 base_seq, uint32 ack_seq,
const uint32* orig_addr,
const IPAddr& orig_addr,
int is_orig, TCP_Flags flags);
void ProcessFIN(double t, TCP_Endpoint* endpoint, int& seq_len,
@ -144,7 +145,7 @@ protected:
uint32 tcp_hdr_len, int len, int& seq_len,
TCP_Endpoint* endpoint, TCP_Endpoint* peer,
uint32 base_seq, uint32 ack_seq,
const uint32* orig_addr,
const IPAddr& orig_addr,
int is_orig, TCP_Flags flags);
void TransitionFromInactive(double t, TCP_Endpoint* endpoint,

View file

@ -32,13 +32,12 @@ TCP_Endpoint::TCP_Endpoint(TCP_Analyzer* arg_analyzer, int arg_is_orig)
dst_addr = is_orig ? tcp_analyzer->Conn()->OrigAddr() :
tcp_analyzer->Conn()->RespAddr();
#ifdef BROv6
checksum_base = ones_complement_checksum((void*) src_addr, 16, 0);
checksum_base = ones_complement_checksum((void*) dst_addr, 16, checksum_base);
#else
checksum_base = ones_complement_checksum((void*) src_addr, 4, 0);
checksum_base = ones_complement_checksum((void*) dst_addr, 4, checksum_base);
#endif
const uint32* src_bytes;
const uint32* dst_bytes;
int n = src_addr.GetBytes(&src_bytes);
int m = dst_addr.GetBytes(&dst_bytes);
checksum_base = ones_complement_checksum((void*) src_bytes, n*4, 0);
checksum_base = ones_complement_checksum((void*) dst_bytes, m*4, checksum_base);
// Note, for IPv6, strictly speaking this field is 32 bits
// rather than 16 bits. But because the upper bits are all zero,
// we get the same checksum either way. The same applies to

View file

@ -3,6 +3,8 @@
#ifndef tcpendpoint_h
#define tcpendpoint_h
#include "IPAddr.h"
typedef enum {
TCP_ENDPOINT_INACTIVE, // no SYN (or other packets) seen for this side
TCP_ENDPOINT_SYN_SENT, // SYN seen, but no ack
@ -128,8 +130,8 @@ public:
uint32 checksum_base;
double start_time, last_time;
const uint32* src_addr; // the other endpoint
const uint32* dst_addr; // this endpoint
IPAddr src_addr; // the other endpoint
IPAddr dst_addr; // this endpoint
uint32 window; // current congestion window (*scaled*, not pre-scaling)
int window_scale; // from the TCP option
uint32 window_ack_seq; // at which ack_seq number did we record 'window'

View file

@ -61,11 +61,9 @@ void UDP_Analyzer::DeliverPacket(int len, const u_char* data, bool is_orig,
udp_checksum(ip->IP4_Hdr(), up, len) != 0xffff )
bad = true;
#ifdef BROv6
if ( ip->IP6_Hdr() && /* checksum is not optional for IPv6 */
udp6_checksum(ip->IP6_Hdr(), up, len) != 0xffff )
bad = true;
#endif
if ( bad )
{

View file

@ -25,7 +25,7 @@
#include "PrefixTable.h"
#include "Conn.h"
#include "Reporter.h"
#include "IPAddr.h"
Val::Val(Func* f)
{
@ -205,29 +205,10 @@ bool Val::DoSerialize(SerialInfo* info) const
val.string_val->Len());
case TYPE_INTERNAL_ADDR:
return SERIALIZE(NUM_ADDR_WORDS)
#ifdef BROv6
&& SERIALIZE(uint32(ntohl(val.addr_val[0])))
&& SERIALIZE(uint32(ntohl(val.addr_val[1])))
&& SERIALIZE(uint32(ntohl(val.addr_val[2])))
&& SERIALIZE(uint32(ntohl(val.addr_val[3])));
#else
&& SERIALIZE(uint32(ntohl(val.addr_val)));
#endif
return SERIALIZE(*val.addr_val);
case TYPE_INTERNAL_SUBNET:
return info->s->WriteOpenTag("subnet")
&& SERIALIZE(NUM_ADDR_WORDS)
#ifdef BROv6
&& SERIALIZE(uint32(ntohl(val.subnet_val.net[0])))
&& SERIALIZE(uint32(ntohl(val.subnet_val.net[1])))
&& SERIALIZE(uint32(ntohl(val.subnet_val.net[2])))
&& SERIALIZE(uint32(ntohl(val.subnet_val.net[3])))
#else
&& SERIALIZE(uint32(ntohl(val.subnet_val.net)))
#endif
&& SERIALIZE(val.subnet_val.width)
&& info->s->WriteCloseTag("subnet");
return SERIALIZE(*val.subnet_val);
case TYPE_INTERNAL_OTHER:
// Derived classes are responsible for this.
@ -294,94 +275,15 @@ bool Val::DoUnserialize(UnserialInfo* info)
case TYPE_INTERNAL_ADDR:
{
int num_words;
if ( ! UNSERIALIZE(&num_words) )
return false;
if ( num_words != 1 && num_words != 4 )
{
info->s->Error("bad address type");
return false;
}
uint32 a[4]; // big enough to hold either
for ( int i = 0; i < num_words; ++i )
{
if ( ! UNSERIALIZE(&a[i]) )
return false;
a[i] = htonl(a[i]);
}
#ifndef BROv6
if ( num_words == 4 )
{
if ( a[0] || a[1] || a[2] )
info->s->Warning("received IPv6 address, ignoring");
((AddrVal*) this)->Init(a[3]);
}
else
((AddrVal*) this)->Init(a[0]);
#else
if ( num_words == 1 )
((AddrVal*) this)->Init(a[0]);
else
((AddrVal*) this)->Init(a);
#endif
val.addr_val = new IPAddr();
return UNSERIALIZE(val.addr_val);
}
return true;
case TYPE_INTERNAL_SUBNET:
{
int num_words;
if ( ! UNSERIALIZE(&num_words) )
return false;
if ( num_words != 1 && num_words != 4 )
{
info->s->Error("bad subnet type");
return false;
}
uint32 a[4]; // big enough to hold either
for ( int i = 0; i < num_words; ++i )
{
if ( ! UNSERIALIZE(&a[i]) )
return false;
a[i] = htonl(a[i]);
}
int width;
if ( ! UNSERIALIZE(&width) )
return false;
#ifdef BROv6
if ( num_words == 1 )
{
a[3] = a[0];
a[0] = a[1] = a[2] = 0;
}
((SubNetVal*) this)->Init(a, width);
#else
if ( num_words == 4 )
{
if ( a[0] || a[1] || a[2] )
info->s->Warning("received IPv6 subnet, ignoring");
a[0] = a[3];
if ( width > 32 )
width -= 96;
}
((SubNetVal*) this)->Init(a[0], width);
#endif
val.subnet_val = new IPPrefix();
return UNSERIALIZE(val.subnet_val);
}
return true;
case TYPE_INTERNAL_OTHER:
// Derived classes are responsible for this.
@ -590,12 +492,10 @@ void Val::ValDescribe(ODesc* d) const
case TYPE_INTERNAL_UNSIGNED: d->Add(val.uint_val); break;
case TYPE_INTERNAL_DOUBLE: d->Add(val.double_val); break;
case TYPE_INTERNAL_STRING: d->AddBytes(val.string_val); break;
case TYPE_INTERNAL_ADDR: d->Add(dotted_addr(val.addr_val)); break;
case TYPE_INTERNAL_ADDR: d->Add(val.addr_val->AsString().c_str()); break;
case TYPE_INTERNAL_SUBNET:
d->Add(dotted_addr(val.subnet_val.net));
d->Add("/");
d->Add(val.subnet_val.width);
d->Add(val.subnet_val->AsString().c_str());
break;
case TYPE_INTERNAL_ERROR: d->AddCS("error"); break;
@ -706,7 +606,8 @@ ID* MutableVal::Bind() const
ip = htonl(0x7f000001); // 127.0.0.1
safe_snprintf(name, MAX_NAME_SIZE, "#%s#%d#",
dotted_addr(ip), getpid());
IPAddr(IPAddr::IPv4, &ip, IPAddr::Network)->AsString().c_str(),
getpid());
#else
safe_snprintf(name, MAX_NAME_SIZE, "#%s#%d#", host, getpid());
#endif
@ -956,92 +857,41 @@ bool PortVal::DoUnserialize(UnserialInfo* info)
AddrVal::AddrVal(const char* text) : Val(TYPE_ADDR)
{
const char* colon = strchr(text, ':');
if ( colon )
{
#ifdef BROv6
Init(dotted_to_addr6(text));
#else
reporter->Error("bro wasn't compiled with IPv6 support");
Init(uint32(0));
#endif
}
else
Init(dotted_to_addr(text));
val.addr_val = new IPAddr(text);
}
AddrVal::AddrVal(uint32 addr) : Val(TYPE_ADDR)
{
// ### perhaps do gethostbyaddr here?
Init(addr);
val.addr_val = new IPAddr(IPAddr::IPv4, &addr, IPAddr::Network);
}
AddrVal::AddrVal(const uint32* addr) : Val(TYPE_ADDR)
AddrVal::AddrVal(const uint32 addr[4]) : Val(TYPE_ADDR)
{
Init(addr);
val.addr_val = new IPAddr(IPAddr::IPv6, addr, IPAddr::Network);
}
AddrVal::AddrVal(const IPAddr& addr) : Val(TYPE_ADDR)
{
val.addr_val = new IPAddr(addr);
}
AddrVal::~AddrVal()
{
#ifdef BROv6
delete [] val.addr_val;
#endif
}
Val* AddrVal::SizeVal() const
{
uint32 addr;
#ifdef BROv6
if ( ! is_v4_addr(val.addr_val) )
{
Error("|addr| for IPv6 addresses not supported");
return new Val(0, TYPE_COUNT);
}
addr = to_v4_addr(val.addr_val);
#else
addr = val.addr_val;
#endif
addr = ntohl(addr);
return new Val(addr, TYPE_COUNT);
}
void AddrVal::Init(uint32 addr)
{
#ifdef BROv6
val.addr_val = new uint32[4];
val.addr_val[0] = val.addr_val[1] = val.addr_val[2] = 0;
val.addr_val[3] = addr;
#else
val.addr_val = addr;
#endif
}
void AddrVal::Init(const uint32* addr)
{
#ifdef BROv6
val.addr_val = new uint32[4];
val.addr_val[0] = addr[0];
val.addr_val[1] = addr[1];
val.addr_val[2] = addr[2];
val.addr_val[3] = addr[3];
#else
val.addr_val = addr[0];
#endif
delete val.addr_val;
}
unsigned int AddrVal::MemoryAllocation() const
{
#ifdef BROv6
return padded_sizeof(*this) + pad_size(4 * sizeof(uint32));
#else
return padded_sizeof(*this);
#endif
return padded_sizeof(*this) + val.addr_val->MemoryAllocation();
}
Val* AddrVal::SizeVal() const
{
if ( val.addr_val->GetFamily() == IPAddr::IPv4 )
return new Val(32, TYPE_COUNT);
else
return new Val(128, TYPE_COUNT);
}
IMPLEMENT_SERIAL(AddrVal, SER_ADDR_VAL);
@ -1058,209 +908,91 @@ bool AddrVal::DoUnserialize(UnserialInfo* info)
return true;
}
static uint32 parse_dotted(const char* text, int& dots)
{
int addr[4];
uint32 a = 0;
dots = 0;
if ( sscanf(text, "%d.%d.%d.%d", addr+0, addr+1, addr+2, addr+3) == 4 )
{
a = (addr[0] << 24) | (addr[1] << 16) |
(addr[2] << 8) | addr[3];
dots = 3;
}
else if ( sscanf(text, "%d.%d.%d", addr+0, addr+1, addr+2) == 3 )
{
a = (addr[0] << 24) | (addr[1] << 16) | (addr[2] << 8);
dots = 2;
}
else if ( sscanf(text, "%d.%d", addr+0, addr+1) == 2 )
{
a = (addr[0] << 24) | (addr[1] << 16);
dots = 1;
}
else
reporter->InternalError("scanf failed in parse_dotted()");
for ( int i = 0; i <= dots; ++i )
{
if ( addr[i] < 0 || addr[i] > 255 )
{
reporter->Error("bad dotted address %s", text);
break;
}
}
return a;
}
SubNetVal::SubNetVal(const char* text) : Val(TYPE_SUBNET)
{
const char* sep = strchr(text, '/');
if ( ! sep )
Internal("separator missing in SubNetVal::SubNetVal");
Init(text, atoi(sep+1));
val.subnet_val = new IPPrefix(text, atoi(sep+1));
}
SubNetVal::SubNetVal(const char* text, int width) : Val(TYPE_SUBNET)
{
Init(text, width);
val.subnet_val = new IPPrefix(text, width);
}
SubNetVal::SubNetVal(uint32 addr, int width) : Val(TYPE_SUBNET)
{
Init(addr, width);
IPAddr a(IPAddr::IPv4, &addr, IPAddr::Network);
val.subnet_val = new IPPrefix(a, width);
}
#ifdef BROv6
SubNetVal::SubNetVal(const uint32* addr, int width) : Val(TYPE_SUBNET)
{
Init(addr, width);
}
#endif
void SubNetVal::Init(const char* text, int width)
{
#ifdef BROv6
if ( width <= 0 || width > 128 )
#else
if ( width <= 0 || width > 32 )
#endif
Error("bad subnet width");
int dots;
uint32 a = parse_dotted(text, dots);
Init(uint32(htonl(a)), width);
IPAddr a(IPAddr::IPv6, addr, IPAddr::Network);
val.subnet_val = new IPPrefix(a, width);
}
void SubNetVal::Init(uint32 addr, int width)
SubNetVal::SubNetVal(const IPAddr& addr, int width) : Val(TYPE_SUBNET)
{
#ifdef BROv6
Internal("SubNetVal::Init called on 4-byte address w/ BROv6");
#else
val.subnet_val.net = mask_addr(addr, uint32(width));
val.subnet_val.width = width;
#endif
val.subnet_val = new IPPrefix(addr, width);
}
void SubNetVal::Init(const uint32* addr, int width)
SubNetVal::~SubNetVal()
{
#ifdef BROv6
const uint32* a = mask_addr(addr, uint32(width));
delete val.subnet_val;
}
val.subnet_val.net[0] = a[0];
val.subnet_val.net[1] = a[1];
val.subnet_val.net[2] = a[2];
val.subnet_val.net[3] = a[3];
if ( is_v4_addr(addr) && width <= 32 )
val.subnet_val.width = width + 96;
else
val.subnet_val.width = width;
#else
Internal("SubNetVal::Init called on 16-byte address w/o BROv6");
#endif
unsigned int SubNetVal::MemoryAllocation() const
{
return padded_sizeof(*this) + val.subnet_val->MemoryAllocation();
}
Val* SubNetVal::SizeVal() const
{
int retained;
#ifdef BROv6
retained = 128 - Width();
#else
retained = 32 - Width();
#endif
int retained = 128 - val.subnet_val->LengthIPv6();
return new Val(pow(2.0, double(retained)), TYPE_DOUBLE);
}
void SubNetVal::ValDescribe(ODesc* d) const
{
d->Add(dotted_addr(val.subnet_val.net, d->Style() == ALTERNATIVE_STYLE));
d->Add("/");
#ifdef BROv6
if ( is_v4_addr(val.subnet_val.net) )
d->Add(val.subnet_val.width - 96);
else
#endif
d->Add(val.subnet_val.width);
d->Add(string(*val.subnet_val).c_str());
}
addr_type SubNetVal::Mask() const
IPAddr SubNetVal::Mask() const
{
if ( val.subnet_val.width == 0 )
if ( val.subnet_val->Length() == 0 )
{
// We need to special-case a mask width of zero, since
// the compiler doesn't guarantee that 1 << 32 yields 0.
#ifdef BROv6
uint32* m = new uint32[4];
for ( int i = 0; i < 4; ++i )
uint32 m[4];
for ( unsigned int i = 0; i < 4; ++i )
m[i] = 0;
return m;
#else
return 0;
#endif
IPAddr rval(IPAddr::IPv6, m, IPAddr::Host);
return rval;
}
#ifdef BROv6
uint32* m = new uint32[4];
uint32 m[4];
uint32* mp = m;
uint32 w;
for ( w = val.subnet_val.width; w >= 32; w -= 32 )
*(mp++) = 0xffffffff;
for ( w = val.subnet_val->Length(); w >= 32; w -= 32 )
*(mp++) = 0xffffffff;
*mp = ~((1 << (32 - w)) - 1);
while ( ++mp < m + 4 )
*mp = 0;
*mp = 0;
return m;
#else
return ~((1 << (32 - val.subnet_val.width)) - 1);
#endif
IPAddr rval(IPAddr::IPv6, m, IPAddr::Host);
return rval;
}
bool SubNetVal::Contains(const uint32 addr) const
bool SubNetVal::Contains(const IPAddr& addr) const
{
#ifdef BROv6
Internal("SubNetVal::Contains called on 4-byte address w/ BROv6");
return false;
#else
return ntohl(val.subnet_val.net) == (ntohl(addr) & Mask());
#endif
}
bool SubNetVal::Contains(const uint32* addr) const
{
#ifdef BROv6
const uint32* net = val.subnet_val.net;
const uint32* a = addr;
uint32 m;
for ( m = val.subnet_val.width; m > 32; m -= 32 )
{
if ( *net != *a )
return false;
++net;
++a;
}
uint32 mask = ~((1 << (32 - m)) - 1);
return ntohl(*net) == (ntohl(*a) & mask);
#else
return Contains(addr[3]);
#endif
IPAddr a(addr);
return val.subnet_val->Contains(a);
}
IMPLEMENT_SERIAL(SubNetVal, SER_SUBNET_VAL);
@ -3475,20 +3207,10 @@ int same_atomic_val(const Val* v1, const Val* v2)
return v1->InternalDouble() == v2->InternalDouble();
case TYPE_INTERNAL_STRING:
return Bstr_eq(v1->AsString(), v2->AsString());
case TYPE_INTERNAL_ADDR:
{
const addr_type& a1 = v1->AsAddr();
const addr_type& a2 = v2->AsAddr();
#ifdef BROv6
return addr_eq(a1, a2);
#else
return addr_eq(&a1, &a2);
#endif
}
return v1->AsAddr() == v2->AsAddr();
case TYPE_INTERNAL_SUBNET:
return subnet_eq(v1->AsSubNet(), v2->AsSubNet());
return v1->AsSubNet() == v2->AsSubNet();
default:
reporter->InternalError("same_atomic_val called for non-atomic value");

View file

@ -18,6 +18,7 @@
#include "ID.h"
#include "Scope.h"
#include "StateAccess.h"
#include "IPAddr.h"
class Val;
class Func;
@ -53,11 +54,11 @@ typedef union {
// Used for count, counter, port, subnet.
bro_uint_t uint_val;
// Used for addr, net
addr_type addr_val;
// Used for addr
IPAddr* addr_val;
// Used for subnet
subnet_type subnet_val;
IPPrefix* subnet_val;
// Used for double, time, interval.
double double_val;
@ -226,10 +227,10 @@ public:
CONST_ACCESSOR(TYPE_PATTERN, RE_Matcher*, re_val, AsPattern)
CONST_ACCESSOR(TYPE_VECTOR, vector<Val*>*, vector_val, AsVector)
const subnet_type* AsSubNet() const
const IPPrefix& AsSubNet() const
{
CHECK_TAG(type->Tag(), TYPE_SUBNET, "Val::SubNet", type_name)
return &val.subnet_val;
return *val.subnet_val;
}
BroType* AsType() const
@ -238,12 +239,11 @@ public:
return type;
}
// ... in network byte order
const addr_type AsAddr() const
const IPAddr& AsAddr() const
{
if ( type->Tag() != TYPE_ADDR )
BadTag("Val::AsAddr", type_name(type->Tag()));
return val.addr_val;
return *val.addr_val;
}
#define ACCESSOR(tag, ctype, accessor, name) \
@ -261,10 +261,17 @@ public:
ACCESSOR(TYPE_PATTERN, RE_Matcher*, re_val, AsPattern)
ACCESSOR(TYPE_VECTOR, vector<Val*>*, vector_val, AsVector)
subnet_type* AsSubNet()
const IPPrefix& AsSubNet()
{
CHECK_TAG(type->Tag(), TYPE_SUBNET, "Val::SubNet", type_name)
return &val.subnet_val;
return *val.subnet_val;
}
const IPAddr& AsAddr()
{
if ( type->Tag() != TYPE_ADDR )
BadTag("Val::AsAddr", type_name(type->Tag()));
return *val.addr_val;
}
// Gives fast access to the bits of something that is one of
@ -282,6 +289,7 @@ public:
CONVERTER(TYPE_PATTERN, PatternVal*, AsPatternVal)
CONVERTER(TYPE_PORT, PortVal*, AsPortVal)
CONVERTER(TYPE_SUBNET, SubNetVal*, AsSubNetVal)
CONVERTER(TYPE_ADDR, AddrVal*, AsAddrVal)
CONVERTER(TYPE_TABLE, TableVal*, AsTableVal)
CONVERTER(TYPE_RECORD, RecordVal*, AsRecordVal)
CONVERTER(TYPE_LIST, ListVal*, AsListVal)
@ -299,6 +307,7 @@ public:
CONST_CONVERTER(TYPE_PATTERN, PatternVal*, AsPatternVal)
CONST_CONVERTER(TYPE_PORT, PortVal*, AsPortVal)
CONST_CONVERTER(TYPE_SUBNET, SubNetVal*, AsSubNetVal)
CONST_CONVERTER(TYPE_ADDR, AddrVal*, AsAddrVal)
CONST_CONVERTER(TYPE_TABLE, TableVal*, AsTableVal)
CONST_CONVERTER(TYPE_RECORD, RecordVal*, AsRecordVal)
CONST_CONVERTER(TYPE_LIST, ListVal*, AsListVal)
@ -555,8 +564,9 @@ public:
Val* SizeVal() const;
// Constructor for address already in network order.
AddrVal(uint32 addr);
AddrVal(const uint32* addr);
AddrVal(uint32 addr); // IPv4.
AddrVal(const uint32 addr[4]); // IPv6.
AddrVal(const IPAddr& addr);
unsigned int MemoryAllocation() const;
@ -566,9 +576,6 @@ protected:
AddrVal(TypeTag t) : Val(t) { }
AddrVal(BroType* t) : Val(t) { }
void Init(uint32 addr);
void Init(const uint32* addr);
DECLARE_SERIAL(AddrVal);
};
@ -576,30 +583,25 @@ class SubNetVal : public Val {
public:
SubNetVal(const char* text);
SubNetVal(const char* text, int width);
SubNetVal(uint32 addr, int width); // for address already massaged
SubNetVal(const uint32* addr, int width); // ditto
SubNetVal(uint32 addr, int width); // IPv4.
SubNetVal(const uint32 addr[4], int width); // IPv6.
SubNetVal(const IPAddr& addr, int width);
~SubNetVal();
Val* SizeVal() const;
int Width() const { return val.subnet_val.width; }
addr_type Mask() const; // returns host byte order
const IPAddr& Prefix() const { return val.subnet_val->Prefix(); }
int Width() const { return val.subnet_val->Length(); }
IPAddr Mask() const;
bool Contains(const uint32 addr) const;
bool Contains(const uint32* addr) const;
bool Contains(const IPAddr& addr) const;
unsigned int MemoryAllocation() const
{
return Val::MemoryAllocation() + padded_sizeof(*this) - padded_sizeof(Val);
}
unsigned int MemoryAllocation() const;
protected:
friend class Val;
SubNetVal() {}
void Init(const char* text, int width);
void Init(uint32 addr, int width);
void Init(const uint32 *addr, int width);
void ValDescribe(ODesc* d) const;
DECLARE_SERIAL(SubNetVal);

View file

@ -1,6 +1,6 @@
// DEFINE_BIF_TYPE(id, bif_type, bro_type, c_type, accessor, constructor)
DEFINE_BIF_TYPE(TYPE_ADDR, "addr", "addr", "addr_type", "%s->AsAddr()", "new AddrVal(%s)")
DEFINE_BIF_TYPE(TYPE_ADDR, "addr", "addr", "AddrVal*", "%s->AsAddrVal()", "%s")
DEFINE_BIF_TYPE(TYPE_ANY, "any", "any", "Val*", "%s", "%s")
DEFINE_BIF_TYPE(TYPE_BOOL, "bool", "bool", "int", "%s->AsBool()", "new Val(%s, TYPE_BOOL)")
DEFINE_BIF_TYPE(TYPE_CONN_ID, "conn_id", "conn_id", "Val*", "%s", "%s")

View file

@ -14,6 +14,7 @@
#include <cstdio>
#include "Reporter.h"
#include "IPAddr.h"
using namespace std;
@ -178,35 +179,38 @@ static void do_fmt(const char*& fmt, Val* v, ODesc* d)
// This makes only a very slight difference, so not
// clear it would e worth the hassle.
addr_type u = v->AsAddr();
#ifdef BROv6
// We explicitly convert the address to host order
// in a copy, because if we just call ntohl() for
// our invocation on snprintf() below, on some systems
// it turns a 32-bit value (Linux), whereas on
// others it returns a long (FreeBSD); the latter
// gets us in trouble if we have longs > 32 bits,
// because then the format specifier needs to be %lx
// rather than %x ....... what a pain!
//
// Also note that we don't change u in-place because
// that would alter the byte order of the underlying
// value. (Speaking of which, I'm not clear on why
// we're allowed to assign a const addr_type to an
// addr_type above, both g++ allows it.)
uint32 host_order_u[4];
host_order_u[0] = ntohl(u[0]);
host_order_u[1] = ntohl(u[1]);
host_order_u[2] = ntohl(u[2]);
host_order_u[3] = ntohl(u[3]);
const IPAddr& u = v->AsAddr();
const uint32* net_order_u;
int len = u.GetBytes(&net_order_u);
snprintf(out_buf, sizeof(out_buf), "%08x%08x%08x%08x",
host_order_u[0], host_order_u[1],
host_order_u[2], host_order_u[3]);
#else
u = ntohl(u);
snprintf(out_buf, sizeof(out_buf), "%08x", u);
#endif
if ( len == 4 )
{
// We explicitly convert the address to host order
// in a copy, because if we just call ntohl() for
// our invocation on snprintf() below, on some systems
// it turns a 32-bit value (Linux), whereas on
// others it returns a long (FreeBSD); the latter
// gets us in trouble if we have longs > 32 bits,
// because then the format specifier needs to be %lx
// rather than %x ....... what a pain!
//
// Also note that we don't change u in-place because
// that would alter the byte order of the underlying
// value.
uint32 host_order_u[4];
host_order_u[0] = ntohl(net_order_u[0]);
host_order_u[1] = ntohl(net_order_u[1]);
host_order_u[2] = ntohl(net_order_u[2]);
host_order_u[3] = ntohl(net_order_u[3]);
snprintf(out_buf, sizeof(out_buf), "%08x%08x%08x%08x",
host_order_u[0], host_order_u[1],
host_order_u[2], host_order_u[3]);
}
else
{
snprintf(out_buf, sizeof(out_buf), "%08x", ntohl(net_order_u[0]));
}
}
else if ( ! check_fmt_type(t, ok_d_fmt) )
@ -1959,44 +1963,41 @@ function do_profiling%(%) : any
## Returns: True if *ip* belongs to a local interface.
function is_local_interface%(ip: addr%) : bool
%{
static uint32* addrs;
static int len = -1;
if ( ip->AsAddr().IsLoopback() )
return new Val(1, TYPE_BOOL);
if ( len < 0 )
list<IPAddr> addrs;
char host[MAXHOSTNAMELEN];
strcpy(host, "localhost");
gethostname(host, MAXHOSTNAMELEN);
host[MAXHOSTNAMELEN-1] = '\0';
struct hostent* ent = gethostbyname2(host, AF_INET);
if ( ent )
{
char host[MAXHOSTNAMELEN];
strcpy(host, "localhost");
gethostname(host, MAXHOSTNAMELEN);
host[MAXHOSTNAMELEN-1] = '\0';
struct hostent* ent = gethostbyname(host);
for ( len = 0; ent->h_addr_list[len]; ++len )
;
addrs = new uint32[len + 1];
for ( int i = 0; i < len; i++ )
addrs[i] = *(uint32*) ent->h_addr_list[i];
addrs[len++] = 0x0100007f; // 127.0.0.1
for ( unsigned int len = 0; ent->h_addr_list[len]; ++len )
addrs.push_back(IPAddr(IPAddr::IPv4, (uint32*)ent->h_addr_list[len],
IPAddr::Network));
}
#ifdef BROv6
if ( ! is_v4_addr(ip) )
ent = gethostbyname2(host, AF_INET6);
if ( ent )
{
builtin_error("is_local_interface() only supports IPv4 addresses");
return new Val(0, TYPE_BOOL);
for ( unsigned int len = 0; ent->h_addr_list[len]; ++len )
addrs.push_back(IPAddr(IPAddr::IPv6, (uint32*)ent->h_addr_list[len],
IPAddr::Network));
}
uint32 ip4 = to_v4_addr(ip);
#else
uint32 ip4 = ip;
#endif
for ( int i = 0; i < len; i++ )
if ( addrs[i] == ip4 )
list<IPAddr>::const_iterator it;
for ( it = addrs.begin(); it != addrs.end(); ++it )
{
if ( *it == ip->AsAddr() )
return new Val(1, TYPE_BOOL);
}
return new Val(0, TYPE_BOOL);
%}
@ -2046,12 +2047,88 @@ function gethostname%(%) : string
return new StringVal(buffer);
%}
## Returns whether an address is IPv4 or not.
##
## a: the address to check.
##
## Returns: true if *a* is an IPv4 address, else false.
function is_v4_addr%(a: addr%): bool
%{
if ( a->AsAddr().GetFamily() == IPAddr::IPv4 )
return new Val(1, TYPE_BOOL);
else
return new Val(0, TYPE_BOOL);
%}
## Returns whether an address is IPv6 or not.
##
## a: the address to check.
##
## Returns: true if *a* is an IPv6 address, else false.
function is_v6_addr%(a: addr%): bool
%{
if ( a->AsAddr().GetFamily() == IPAddr::IPv6 )
return new Val(1, TYPE_BOOL);
else
return new Val(0, TYPE_BOOL);
%}
# ===========================================================================
#
# Conversion
#
# ===========================================================================
## Converts a :bro:type:`addr` to a :bro:type:`index_vec`.
##
## a: The address to convert into a vector of counts.
##
## Returns: A vector containing the host-order address representation,
## four elements in size for IPv6 addresses, or one element for IPv4.
##
## .. bro:see:: counts_to_addr
function addr_to_counts%(a: addr%): index_vec
%{
VectorVal* rval = new VectorVal(new VectorType(base_type(TYPE_COUNT)));
const uint32* bytes;
int len = a->AsAddr().GetBytes(&bytes);
for ( int i = 0; i < len; ++i )
rval->Assign(i, new Val(ntohl(bytes[i]), TYPE_COUNT), 0);
return rval;
%}
## Converts a :bro:type:`index_vec` to a :bro:type:`addr`.
##
## v: The vector containing host-order IP address representation,
## one element for IPv4 addresses, four elements for IPv6 addresses.
##
## Returns: An IP address.
##
## .. bro:see:: addr_to_counts
function counts_to_addr%(v: index_vec%): addr
%{
if ( v->AsVector()->size() == 1 )
{
return new AddrVal(htonl((*v->AsVector())[0]->AsCount()));
}
else if ( v->AsVector()->size() == 4 )
{
uint32 bytes[4];
for ( int i = 0; i < 4; ++i )
bytes[i] = htonl((*v->AsVector())[i]->AsCount());
return new AddrVal(bytes);
}
else
{
builtin_error("invalid vector size", @ARG@[0]);
uint32 bytes[4];
memset(bytes, 0, sizeof(bytes));
return new AddrVal(bytes);
}
%}
## Converts a :bro:type:`string` to a :bro:type:`int`.
##
## str: The :bro:type:`string` to convert.
@ -2180,29 +2257,6 @@ function double_to_interval%(d: double%): interval
return new Val(d, TYPE_INTERVAL);
%}
## Converts a :bro:type:`addr` to a :bro:type:`count`.
##
## a: The :bro:type:`addr` to convert.
##
## Returns: The :bro:type:`addr` *a* as :bro:type:`count`.
##
## .. bro:see:: addr_to_ptr_name
function addr_to_count%(a: addr%): count
%{
#ifdef BROv6
if ( ! is_v4_addr(a) )
{
builtin_error("conversion of non-IPv4 address to count", @ARG@[0]);
return new Val(0, TYPE_COUNT);
}
uint32 addr = to_v4_addr(a);
#else
uint32 addr = a;
#endif
return new Val(ntohl(addr), TYPE_COUNT);
%}
## Converts a :bro:type:`port` to a :bro:type:`count`.
##
## p: The :bro:type:`port` to convert.
@ -2327,20 +2381,58 @@ function to_port%(s: string%): port
## .. bro:see:: addr_to_ptr_name parse_dotted_addr
function ptr_name_to_addr%(s: string%): addr
%{
int a[4];
uint32 addr;
if ( sscanf(s->CheckString(),
"%d.%d.%d.%d.in-addr.arpa",
a, a+1, a+2, a+3) != 4 )
if ( s->Len() != 72 )
{
builtin_error("bad PTR name", @ARG@[0]);
addr = 0;
int a[4];
uint32 addr;
char ss[13]; // this will contain "in-addr.arpa"
if ( sscanf(s->CheckString(),
"%d.%d.%d.%d.%12s",
a, a+1, a+2, a+3, ss) != 5
|| strcmp(ss, "in-addr.arpa") != 0 )
{
builtin_error("bad PTR name", @ARG@[0]);
addr = 0;
}
else
addr = (a[3] << 24) | (a[2] << 16) | (a[1] << 8) | a[0];
return new AddrVal(htonl(addr));
}
else
addr = (a[3] << 24) | (a[2] << 16) | (a[1] << 8) | a[0];
{
uint32 addr6[4];
uint32 b[32];
char ss[9]; // this will contain "ip6.arpa"
if ( sscanf(s->CheckString(),
"%1x.%1x.%1x.%1x.%1x.%1x.%1x.%1x."
"%1x.%1x.%1x.%1x.%1x.%1x.%1x.%1x."
"%1x.%1x.%1x.%1x.%1x.%1x.%1x.%1x."
"%1x.%1x.%1x.%1x.%1x.%1x.%1x.%1x.%8s",
b+31, b+30, b+29, b+28, b+27, b+26, b+25, b+24,
b+23, b+22, b+21, b+20, b+19, b+18, b+17, b+16,
b+15, b+14, b+13, b+12, b+11, b+10, b+9, b+8,
b+7, b+6, b+5, b+4, b+3, b+2, b+1, b, ss) != 33
|| strcmp(ss, "ip6.arpa") != 0 )
{
builtin_error("bad PTR name", @ARG@[0]);
memset(addr6, 0, sizeof addr6);
}
else
{
for ( unsigned int i = 0; i < 4; ++i )
{
uint32 a = 0;
for ( unsigned int j = 1; j <= 8; ++j )
a |= b[8*i+j-1] << (32-j*4);
return new AddrVal(htonl(addr));
addr6[i] = htonl(a);
}
}
return new AddrVal(addr6);
}
%}
## Converts an IP address to a reverse pointer name. For example,
@ -2350,34 +2442,38 @@ function ptr_name_to_addr%(s: string%): addr
##
## Returns: The reverse pointer representation of *a*.
##
## .. bro:see:: addr_to_count ptr_name_to_addr parse_dotted_addr
## .. bro:see:: ptr_name_to_addr parse_dotted_addr
function addr_to_ptr_name%(a: addr%): string
%{
// ## Question:
// uint32 addr = ntohl((*args)[0]->InternalUnsigned());
uint32 addr;
#ifdef BROv6
if ( is_v4_addr(a) )
addr = a[3];
const uint32* addr;
int len = a->AsAddr().GetBytes(&addr);
if ( len == 1 )
{
char buf[256];
uint32 a = ntohl(addr[0]);
uint32 a3 = (a >> 24) & 0xff;
uint32 a2 = (a >> 16) & 0xff;
uint32 a1 = (a >> 8) & 0xff;
uint32 a0 = a & 0xff;
sprintf(buf, "%u.%u.%u.%u.in-addr.arpa", a0, a1, a2, a3);
return new StringVal(buf);
}
else
{
builtin_error("conversion of non-IPv4 address to net", @ARG@[0]);
addr = 0;
static const char hex_digit[] = "0123456789abcdef";
string ptr_name("ip6.arpa");
for ( unsigned int i = 0; i < 4; ++i )
{
uint32 a = ntohl(addr[i]);
for ( unsigned int j = 1; j <=8; ++j )
{
ptr_name.insert(0, 1, '.');
ptr_name.insert(0, 1, hex_digit[(a >> (32-j*4)) & 0x0f]);
}
}
return new StringVal(ptr_name.c_str());
}
#else
addr = a;
#endif
addr = ntohl(addr);
uint32 a3 = (addr >> 24) & 0xff;
uint32 a2 = (addr >> 16) & 0xff;
uint32 a1 = (addr >> 8) & 0xff;
uint32 a0 = addr & 0xff;
char buf[256];
sprintf(buf, "%u.%u.%u.%u.in-addr.arpa", a0, a1, a2, a3);
return new StringVal(buf);
%}
# Transforms n0.n1.n2.n3 -> addr.
@ -2389,10 +2485,11 @@ function addr_to_ptr_name%(a: addr%): string
##
## Returns: The IP address as type :bro:type:`addr`.
##
## .. bro:see:: addr_to_ptr_name parse_dotted_addr addr_to_count
## .. bro:see:: addr_to_ptr_name parse_dotted_addr
function parse_dotted_addr%(s: string%): addr
%{
return new AddrVal(dotted_to_addr(s->CheckString()));
IPAddr a(s->CheckString());
return new AddrVal(a);
%}
%%{
@ -2465,7 +2562,11 @@ static Val* parse_eftp(const char* line)
line = next_delim + 1;
if ( *line != delimiter ) // default of 0 is ok
{
addr = dotted_to_addr(line);
string s(line);
IPAddr tmp(s);
const uint32* bytes;
tmp.GetBytes(&bytes);
addr = *bytes;
if ( addr == 0 )
good = 0;
}
@ -2570,20 +2671,23 @@ function parse_ftp_epsv%(str: string%): ftp_port
## .. bro:see:: parse_ftp_port parse_eftp_port parse_ftp_pasv parse_ftp_epsv
function fmt_ftp_port%(a: addr, p: port%): string
%{
#ifdef BROv6
if ( ! is_v4_addr(a) )
builtin_error("conversion of non-IPv4 address to net", @ARG@[0]);
uint32 addr = to_v4_addr(a);
#else
uint32 addr = a;
#endif
addr = ntohl(addr);
uint32 pn = p->Port();
return new StringVal(fmt("%d,%d,%d,%d,%d,%d",
addr >> 24, (addr >> 16) & 0xff,
(addr >> 8) & 0xff, addr & 0xff,
pn >> 8, pn & 0xff));
const uint32* addr;
int len = a->AsAddr().GetBytes(&addr);
if ( len == 1 )
{
uint32 a = ntohl(addr[0]);
uint32 pn = p->Port();
return new StringVal(fmt("%d,%d,%d,%d,%d,%d",
a >> 24, (a >> 16) & 0xff,
(a >> 8) & 0xff, a & 0xff,
pn >> 8, pn & 0xff));
}
else
{
builtin_error("conversion of non-IPv4 address in fmt_ftp_port",
@ARG@[0]);
return new StringVal("");
}
%}
## Decode a NetBIOS name. See http://support.microsoft.com/kb/194203.
@ -2896,7 +3000,7 @@ function strftime%(fmt: string, d: time%) : string
## .. bro:see:: remask_addr
function mask_addr%(a: addr, top_bits_to_keep: count%): subnet
%{
return new SubNetVal(mask_addr(a, top_bits_to_keep), top_bits_to_keep);
return new SubNetVal(a->AsAddr(), top_bits_to_keep);
%}
## Takes some top bits (e.g., subnet address) from one address and the other
@ -2909,29 +3013,26 @@ function mask_addr%(a: addr, top_bits_to_keep: count%): subnet
## a2: The address to take the remaining bits from.
##
## top_bits_from_a1: The number of top bits to keep in *a1*; must be greater
## than 0 and less than 33.
## than 0 and less than 129. This value is always interpreted
## relative to the IPv6 bit width (v4-mapped addresses start
## at bit number 96).
##
## Returns: The address *a* masked down to *top_bits_to_keep* bits.
##
## .. bro:see:: mask_addr
function remask_addr%(a1: addr, a2: addr, top_bits_from_a1: count%): addr
%{
#ifdef BROv6
if ( ! is_v4_addr(a1) || ! is_v4_addr(a2) )
{
builtin_error("cannot use remask_addr on IPv6 addresses");
return new AddrVal(a1);
}
uint32 x1 = to_v4_addr(a1);
uint32 x2 = to_v4_addr(a2);
#else
uint32 x1 = a1;
uint32 x2 = a2;
#endif
return new AddrVal(
mask_addr(x1, top_bits_from_a1) |
(x2 ^ mask_addr(x2, top_bits_from_a1)) );
IPAddr addr1(a1->AsAddr());
addr1.Mask(top_bits_from_a1);
IPAddr addr2(a2->AsAddr());
addr1.ReverseMask(top_bits_from_a1);
uint32 x1[4];
uint32 x2[4];
addr1.CopyIPv6(x1);
addr2.CopyIPv6(x2);
for ( unsigned int i = 0; i < 4; ++i )
x1[i] = x1[i] | x2[i];
return new AddrVal(x1);
%}
## Checks whether a given :bro:type:`port` has TCP as transport protocol.
@ -3104,12 +3205,13 @@ const char* conn_id_string(Val* c)
Val* id = (*(c->AsRecord()))[0];
const val_list* vl = id->AsRecord();
addr_type orig_h = (*vl)[0]->AsAddr();
const IPAddr& orig_h = (*vl)[0]->AsAddr();
uint32 orig_p = (*vl)[1]->AsPortVal()->Port();
addr_type resp_h = (*vl)[2]->AsAddr();
const IPAddr& resp_h = (*vl)[2]->AsAddr();
uint32 resp_p = (*vl)[3]->AsPortVal()->Port();
return fmt("%s/%u -> %s/%u\n", dotted_addr(orig_h), orig_p, dotted_addr(resp_h), resp_p);
return fmt("%s/%u -> %s/%u\n", orig_h.AsString().c_str(), orig_p,
resp_h.AsString().c_str(), resp_p);
}
%%}
@ -3339,29 +3441,8 @@ function lookup_addr%(host: addr%) : string
frame->SetDelayed();
trigger->Hold();
#ifdef BROv6
if ( ! is_v4_addr(host) )
{
// FIXME: This is a temporary work-around until we get this
// fixed. We warn the user once, and always trigger a timeout.
// Ticket #355 records the problem.
static bool warned = false;
if ( ! warned )
{
reporter->Warning("lookup_addr() only supports IPv4 addresses currently");
warned = true;
}
trigger->Timeout();
return 0;
}
dns_mgr->AsyncLookupAddr(to_v4_addr(host),
dns_mgr->AsyncLookupAddr(host->AsAddr(),
new LookupHostCallback(trigger, frame->GetCall(), true));
#else
dns_mgr->AsyncLookupAddr(host,
new LookupHostCallback(trigger, frame->GetCall(), true));
#endif
return 0;
%}
@ -3453,8 +3534,6 @@ function lookup_location%(a: addr%) : geo_location
else
have_city_db = true;
#ifdef BROv6
#ifdef HAVE_GEOIP_CITY_EDITION_REV0_V6
geoip_v6 = open_geoip_db(GEOIP_CITY_EDITION_REV0_V6);
if ( geoip_v6 )
@ -3467,16 +3546,15 @@ function lookup_location%(a: addr%) : geo_location
#endif
if ( ! geoip_v6 )
builtin_error("Can't initialize GeoIPv6 City/Country database");
#endif
}
#ifdef BROv6
#ifdef HAVE_GEOIP_COUNTRY_EDITION_V6
if ( geoip_v6 && ! is_v4_addr(a) )
if ( geoip_v6 && a->AsAddr().GetFamily() == IPAddr::IPv6 )
{
const uint32* bytes;
a->AsAddr().GetBytes(&bytes);
geoipv6_t ga;
memcpy(&ga, a, 16);
memcpy(&ga, bytes, 16);
if ( have_cityv6_db )
gir = GeoIP_record_by_ipnum_v6(geoip_v6, ga);
else
@ -3485,25 +3563,16 @@ function lookup_location%(a: addr%) : geo_location
else
#endif
if ( geoip && is_v4_addr(a) )
if ( geoip && a->AsAddr().GetFamily() == IPAddr::IPv4 )
{
uint32 addr = to_v4_addr(a);
const uint32* bytes;
a->AsAddr().GetBytes(&bytes);
if ( have_city_db )
gir = GeoIP_record_by_ipnum(geoip, ntohl(addr));
gir = GeoIP_record_by_ipnum(geoip, ntohl(*bytes));
else
cc = GeoIP_country_code_by_ipnum(geoip, ntohl(addr));
cc = GeoIP_country_code_by_ipnum(geoip, ntohl(*bytes));
}
#else // not BROv6
if ( geoip )
{
if ( have_city_db )
gir = GeoIP_record_by_ipnum(geoip, ntohl(a));
else
cc = GeoIP_country_code_by_ipnum(geoip, ntohl(a));
}
#endif
if ( gir )
{
if ( gir->country_code )
@ -3575,28 +3644,25 @@ function lookup_asn%(a: addr%) : count
if ( geoip_asn )
{
#ifdef BROv6
// IPv6 support showed up in 1.4.5.
#ifdef HAVE_GEOIP_COUNTRY_EDITION_V6
if ( ! is_v4_addr(a) )
if ( a->AsAddr().GetFamily() == IPAddr::IPv6 )
{
const uint32* bytes;
a->AsAddr().GetBytes(&bytes);
geoipv6_t ga;
memcpy(&ga, a, 16);
memcpy(&ga, bytes, 16);
gir = GeoIP_name_by_ipnum_v6(geoip_asn, ga);
}
else
#endif
if ( is_v4_addr(a) )
if ( a->AsAddr().GetFamily() == IPAddr::IPv4 )
{
uint32 addr = to_v4_addr(a);
gir = GeoIP_name_by_ipnum(geoip_asn, ntohl(addr));
const uint32* bytes;
a->AsAddr().GetBytes(&bytes);
gir = GeoIP_name_by_ipnum(geoip_asn, ntohl(*bytes));
}
#else // not BROv6
gir = GeoIP_name_by_ipnum(geoip_asn, ntohl(a));
#endif
}
if ( gir )
@ -3878,9 +3944,9 @@ function file_mode%(mode: count%): string
function expect_connection%(orig: addr, resp: addr, resp_p: port,
analyzer: count, tout: interval%) : any
%{
dpm->ExpectConnection(orig, resp, resp_p->Port(), resp_p->PortType(),
(AnalyzerTag::Tag) analyzer, tout, 0);
return 0;
dpm->ExpectConnection(orig->AsAddr(), resp->AsAddr(), resp_p->Port(),
resp_p->PortType(), (AnalyzerTag::Tag) analyzer, tout, 0);
return new Val(1, TYPE_BOOL);
%}
## Disables the analyzer which raised the current event (if the analyzer
@ -4652,7 +4718,7 @@ function pcap_error%(%): string
## .. todo:: The return value should be changed to any.
function install_src_addr_filter%(ip: addr, tcp_flags: count, prob: double%) : bool
%{
sessions->GetPacketFilter()->AddSrc(ip, tcp_flags, prob);
sessions->GetPacketFilter()->AddSrc(ip->AsAddr(), tcp_flags, prob);
return new Val(1, TYPE_BOOL);
%}
@ -4704,7 +4770,7 @@ function install_src_net_filter%(snet: subnet, tcp_flags: count, prob: double%)
## pcap_error
function uninstall_src_addr_filter%(ip: addr%) : bool
%{
return new Val(sessions->GetPacketFilter()->RemoveSrc(ip), TYPE_BOOL);
return new Val(sessions->GetPacketFilter()->RemoveSrc(ip->AsAddr()), TYPE_BOOL);
%}
## Removes a source subnet filter.
@ -4754,7 +4820,7 @@ function uninstall_src_net_filter%(snet: subnet%) : bool
## .. todo:: The return value should be changed to any.
function install_dst_addr_filter%(ip: addr, tcp_flags: count, prob: double%) : bool
%{
sessions->GetPacketFilter()->AddDst(ip, tcp_flags, prob);
sessions->GetPacketFilter()->AddDst(ip->AsAddr(), tcp_flags, prob);
return new Val(1, TYPE_BOOL);
%}
@ -4806,7 +4872,7 @@ function install_dst_net_filter%(snet: subnet, tcp_flags: count, prob: double%)
## pcap_error
function uninstall_dst_addr_filter%(ip: addr%) : bool
%{
return new Val(sessions->GetPacketFilter()->RemoveDst(ip), TYPE_BOOL);
return new Val(sessions->GetPacketFilter()->RemoveDst(ip->AsAddr()), TYPE_BOOL);
%}
## Removes a destination subnet filter.
@ -4947,7 +5013,7 @@ function capture_state_updates%(filename: string%) : bool
## send_id
function connect%(ip: addr, p: port, our_class: string, retry: interval, ssl: bool%) : count
%{
return new Val(uint32(remote_serializer->Connect(ip, p->Port(),
return new Val(uint32(remote_serializer->Connect(ip->AsAddr(), p->Port(),
our_class->CheckString(), retry, ssl)),
TYPE_COUNT);
%}
@ -5062,7 +5128,7 @@ function set_compression_level%(p: event_peer, level: count%) : bool
## .. bro:see:: connect disconnect
function listen%(ip: addr, p: port, ssl: bool %) : bool
%{
return new Val(remote_serializer->Listen(ip, p->Port(), ssl), TYPE_BOOL);
return new Val(remote_serializer->Listen(ip->AsAddr(), p->Port(), ssl), TYPE_BOOL);
%}
## Checks whether the last raised event came from a remote peer.
@ -5318,14 +5384,14 @@ function preserve_prefix%(a: addr, width: count%): any
AnonymizeIPAddr* ip_anon = ip_anonymizer[PREFIX_PRESERVING_A50];
if ( ip_anon )
{
#ifdef BROv6
if ( ! is_v4_addr(a) )
if ( a->AsAddr().GetFamily() == IPAddr::IPv6 )
builtin_error("preserve_prefix() not supported for IPv6 addresses");
else
ip_anon->PreservePrefix(a[3], width);
#else
ip_anon->PreservePrefix(a, width);
#endif
{
const uint32* bytes;
a->AsAddr().GetBytes(&bytes);
ip_anon->PreservePrefix(*bytes, width);
}
}
@ -5343,18 +5409,18 @@ function preserve_prefix%(a: addr, width: count%): any
## .. todo:: Currently dysfunctional.
function preserve_subnet%(a: subnet%): any
%{
DEBUG_MSG("%s/%d\n", dotted_addr(a->AsAddr()), a->Width());
DEBUG_MSG("%s/%d\n", a->Prefix().AsString().c_str(), a->Width());
AnonymizeIPAddr* ip_anon = ip_anonymizer[PREFIX_PRESERVING_A50];
if ( ip_anon )
{
#ifdef BROv6
if ( ! is_v4_addr(a->AsAddr()) )
if ( a->AsSubNet().Prefix().GetFamily() == IPAddr::IPv6 )
builtin_error("preserve_subnet() not supported for IPv6 addresses");
else
ip_anon->PreservePrefix(a->AsAddr()[3], a->Width());
#else
ip_anon->PreservePrefix(a->AsAddr(), a->Width());
#endif
{
const uint32* bytes;
a->AsSubNet().Prefix().GetBytes(&bytes);
ip_anon->PreservePrefix(*bytes, a->AsSubNet().Length());
}
}
return 0;
@ -5383,19 +5449,18 @@ function anonymize_addr%(a: addr, cl: IPAddrAnonymizationClass%): addr
if ( anon_class < 0 || anon_class >= NUM_ADDR_ANONYMIZATION_CLASSES )
builtin_error("anonymize_addr(): invalid ip addr anonymization class");
#ifdef BROv6
if ( ! is_v4_addr(a) )
if ( a->AsAddr().GetFamily() == IPAddr::IPv6 )
{
builtin_error("anonymize_addr() not supported for IPv6 addresses");
return 0;
}
else
return new AddrVal(anonymize_ip(a[3],
{
const uint32* bytes;
a->AsAddr().GetBytes(&bytes);
return new AddrVal(anonymize_ip(*bytes,
(enum ip_addr_anonymization_class_t) anon_class));
#else
return new AddrVal(anonymize_ip(a,
(enum ip_addr_anonymization_class_t) anon_class));
#endif
}
%}
## Deprecated. Will be removed.
@ -5445,7 +5510,7 @@ function generate_idmef%(src_ip: addr, src_port: port,
newNode(newAddress(
newAttribute("category","ipv4-addr"),
newSimpleElement("address",
copy_string(dotted_addr(src_ip))),
copy_string(src_ip->AsAddr().AsString().c_str())),
NULL), NULL),
newService(
newSimpleElement("port",
@ -5455,7 +5520,7 @@ function generate_idmef%(src_ip: addr, src_port: port,
newNode(newAddress(
newAttribute("category","ipv4-addr"),
newSimpleElement("address",
copy_string(dotted_addr(dst_ip))),
copy_string(dst_ip->AsAddr().AsString().c_str())),
NULL), NULL),
newService(
newSimpleElement("port",
@ -5470,13 +5535,3 @@ function generate_idmef%(src_ip: addr, src_port: port,
return new Val(0, TYPE_BOOL);
#endif
%}
## Deprecated. Will be removed.
function bro_has_ipv6%(%) : bool
%{
#ifdef BROv6
return new Val(1, TYPE_BOOL);
#else
return new Val(0, TYPE_BOOL);
#endif
%}

View file

@ -55,33 +55,18 @@ flow DHCP_Flow(is_orig: bool) {
vector<DHCP_Option*>::const_iterator ptr;
// Requested IP address to the server.
#ifdef BROv6
::uint32 req_addr[4], serv_addr[4];
req_addr[0] = req_addr[1] = req_addr[2] = req_addr[3] = 0;
serv_addr[0] = serv_addr[1] = serv_addr[2] = serv_addr[3] = 0;
#else
addr_type req_addr = 0, serv_addr = 0;
#endif
::uint32 req_addr = 0, serv_addr = 0;
for ( ptr = options->begin();
ptr != options->end() && ! (*ptr)->last(); ++ptr )
{
switch ( (*ptr)->code() ) {
case REQ_IP_OPTION:
#ifdef BROv6
req_addr[3] = htonl((*ptr)->info()->req_addr());
#else
req_addr = htonl((*ptr)->info()->req_addr());
#endif
break;
case SERV_ID_OPTION:
#ifdef BROv6
serv_addr[3] = htonl((*ptr)->info()->serv_addr());
#else
serv_addr = htonl((*ptr)->info()->serv_addr());
#endif
break;
}
}
@ -91,13 +76,14 @@ flow DHCP_Flow(is_orig: bool) {
case DHCPDISCOVER:
BifEvent::generate_dhcp_discover(connection()->bro_analyzer(),
connection()->bro_analyzer()->Conn(),
dhcp_msg_val_->Ref(), req_addr);
dhcp_msg_val_->Ref(), new AddrVal(req_addr));
break;
case DHCPREQUEST:
BifEvent::generate_dhcp_request(connection()->bro_analyzer(),
connection()->bro_analyzer()->Conn(),
dhcp_msg_val_->Ref(), req_addr, serv_addr);
dhcp_msg_val_->Ref(), new AddrVal(req_addr),
new AddrVal(serv_addr));
break;
case DHCPDECLINE:
@ -129,15 +115,7 @@ flow DHCP_Flow(is_orig: bool) {
// RFC 1533 allows a list of router addresses.
TableVal* router_list = 0;
#ifdef BROv6
::uint32 subnet_mask[4], serv_addr[4];
subnet_mask[0] = subnet_mask[1] =
subnet_mask[2] = subnet_mask[3] = 0;
serv_addr[0] = serv_addr[1] = serv_addr[2] = serv_addr[3] = 0;
#else
addr_type subnet_mask = 0, serv_addr = 0;
#endif
::uint32 subnet_mask = 0, serv_addr = 0;
uint32 lease = 0;
@ -146,13 +124,7 @@ flow DHCP_Flow(is_orig: bool) {
{
switch ( (*ptr)->code() ) {
case SUBNET_OPTION:
#ifdef BROv6
subnet_mask[0] =
subnet_mask[1] = subnet_mask[2] = 0;
subnet_mask[3] = htonl((*ptr)->info()->mask());
#else
subnet_mask = htonl((*ptr)->info()->mask());
#endif
break;
case ROUTER_OPTION:
@ -170,14 +142,8 @@ flow DHCP_Flow(is_orig: bool) {
vector<uint32>* rlist =
(*ptr)->info()->router_list();
uint32 raddr = (*rlist)[i];
#ifdef BROv6
::uint32 tmp_addr[4];
tmp_addr[0] = tmp_addr[1] = tmp_addr[2] = 0;
tmp_addr[3] = htonl(raddr);
#else
::uint32 tmp_addr;
tmp_addr = htonl(raddr);
#endif
// index starting from 1
Val* index = new Val(i + 1, TYPE_COUNT);
router_list->Assign(index, new AddrVal(tmp_addr));
@ -191,11 +157,7 @@ flow DHCP_Flow(is_orig: bool) {
break;
case SERV_ID_OPTION:
#ifdef BROv6
serv_addr[3] = htonl((*ptr)->info()->serv_addr());
#else
serv_addr = htonl((*ptr)->info()->serv_addr());
#endif
break;
}
}
@ -204,15 +166,15 @@ flow DHCP_Flow(is_orig: bool) {
case DHCPOFFER:
BifEvent::generate_dhcp_offer(connection()->bro_analyzer(),
connection()->bro_analyzer()->Conn(),
dhcp_msg_val_->Ref(), subnet_mask,
router_list, lease, serv_addr);
dhcp_msg_val_->Ref(), new AddrVal(subnet_mask),
router_list, lease, new AddrVal(serv_addr));
break;
case DHCPACK:
BifEvent::generate_dhcp_ack(connection()->bro_analyzer(),
connection()->bro_analyzer()->Conn(),
dhcp_msg_val_->Ref(), subnet_mask,
router_list, lease, serv_addr);
dhcp_msg_val_->Ref(), new AddrVal(subnet_mask),
router_list, lease, new AddrVal(serv_addr));
break;
case DHCPNAK:

View file

@ -216,44 +216,42 @@ flow DNS_Flow
switch ( rr->rr_type() ) {
case TYPE_A:
if ( dns_A_reply )
{
::uint32 addr = rd->type_a();
BifEvent::generate_dns_A_reply(connection()->bro_analyzer(),
connection()->bro_analyzer()->Conn(),
dns_msg_val_->Ref(), build_dns_answer(rr),
new AddrVal(htonl(addr)));
}
break;
case TYPE_A6:
case TYPE_AAAA:
if ( ! dns_A_reply )
break;
#ifdef BROv6
::uint32 addr[4];
#else
addr_type addr;
#endif
if ( rr->rr_type() == TYPE_A )
if ( dns_A6_reply )
{
#ifdef BROv6
addr[0] = addr[1] = addr[2] = 0;
addr[3] = htonl(rd->type_a());
#else
addr = htonl(rd->type_a());
#endif
}
else
{
#ifdef BROv6
for ( int i = 0; i < 4; ++i )
::uint32 addr[4];
for ( unsigned int i = 0; i < 4; ++i )
addr[i] = htonl((*rd->type_aaaa())[i]);
#else
addr = htonl((*rd->type_aaaa())[3]);
#endif
}
// For now, we treat A6 and AAAA as A's. Given the
// above fixes for BROv6, we can probably now introduce
// their own events. (It's not clear A6 is needed -
// do we actually encounter it in practice?)
BifEvent::generate_dns_A_reply(connection()->bro_analyzer(),
connection()->bro_analyzer()->Conn(),
dns_msg_val_->Ref(), build_dns_answer(rr), addr);
BifEvent::generate_dns_A6_reply(connection()->bro_analyzer(),
connection()->bro_analyzer()->Conn(),
dns_msg_val_->Ref(), build_dns_answer(rr),
new AddrVal(addr));
}
break;
case TYPE_AAAA:
if ( dns_AAAA_reply )
{
::uint32 addr[4];
for ( unsigned int i = 0; i < 4; ++i )
addr[i] = htonl((*rd->type_aaaa())[i]);
BifEvent::generate_dns_AAAA_reply(connection()->bro_analyzer(),
connection()->bro_analyzer()->Conn(),
dns_msg_val_->Ref(), build_dns_answer(rr),
new AddrVal(addr));
}
break;
case TYPE_NS:

View file

@ -3740,19 +3740,13 @@ event non_dns_request%(c: connection, msg: string%) &group="dns";
##
## a: The address returned by the reply.
##
## .. bro:see:: dns_AAAA_reply dns_CNAME_reply dns_EDNS_addl dns_HINFO_reply
## .. bro:see:: dns_AAAA_reply dns_A6_reply dns_CNAME_reply dns_EDNS_addl dns_HINFO_reply
## dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply dns_SRV_reply
## dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end dns_full_request
## dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name
## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply
## dns_rejected dns_request non_dns_request dns_max_queries dns_session_timeout
## dns_skip_addl dns_skip_all_addl dns_skip_all_auth dns_skip_auth
##
## .. note: This event is currently also raised for ``AAAA`` records. In that
## case, the address *a* will correspond to the lower-order 4 bytes of the
## IPv6 address. This will go away once IPv6 support is improved.
##
## .. todo: IPv6 handling is obviously very broken here ...
event dns_A_reply%(c: connection, msg: dns_msg, ans: dns_answer, a: addr%) &group="dns";
## Generated for DNS replies of type *AAAA*. For replies with multiple answers, an
@ -3770,18 +3764,38 @@ event dns_A_reply%(c: connection, msg: dns_msg, ans: dns_answer, a: addr%) &grou
##
## a: The address returned by the reply.
##
## .. bro:see:: dns_A_reply dns_CNAME_reply dns_EDNS_addl dns_HINFO_reply dns_MX_reply
## .. bro:see:: dns_A_reply dns_A6_reply dns_CNAME_reply dns_EDNS_addl dns_HINFO_reply dns_MX_reply
## dns_NS_reply dns_PTR_reply dns_SOA_reply dns_SRV_reply dns_TSIG_addl
## dns_TXT_reply dns_WKS_reply dns_end dns_full_request dns_mapping_altered
## dns_mapping_lost_name dns_mapping_new_name dns_mapping_unverified
## dns_mapping_valid dns_message dns_query_reply dns_rejected dns_request
## non_dns_request dns_max_queries dns_session_timeout dns_skip_addl
## dns_skip_all_addl dns_skip_all_auth dns_skip_auth
event dns_AAAA_reply%(c: connection, msg: dns_msg, ans: dns_answer, a: addr%) &group="dns";
## Generated for DNS replies of type *A6*. For replies with multiple answers, an
## individual event of the corresponding type is raised for each.
##
## .. todo: Raising this event is not implemented currently, not even when
## Bro's compiled IPv6 support. ``AAAA`` are currently always turned into
## :bro:id:`dns_A_reply` events.
event dns_AAAA_reply%(c: connection, msg: dns_msg, ans: dns_answer, a: addr, astr: string%) &group="dns";
## See `Wikipedia <http://en.wikipedia.org/wiki/Domain_Name_System>`__ for more
## information about the DNS protocol. Bro analyzes both UDP and TCP DNS sessions.
##
## c: The connection, which may be UDP or TCP depending on the type of the
## transport-layer session being analyzed.
##
## msg: The parsed DNS message header.
##
## ans: The type-independent part of the parsed answer record.
##
## a: The address returned by the reply.
##
## .. bro:see:: dns_A_reply dns_AAAA_reply dns_CNAME_reply dns_EDNS_addl dns_HINFO_reply dns_MX_reply
## dns_NS_reply dns_PTR_reply dns_SOA_reply dns_SRV_reply dns_TSIG_addl
## dns_TXT_reply dns_WKS_reply dns_end dns_full_request dns_mapping_altered
## dns_mapping_lost_name dns_mapping_new_name dns_mapping_unverified
## dns_mapping_valid dns_message dns_query_reply dns_rejected dns_request
## non_dns_request dns_max_queries dns_session_timeout dns_skip_addl
## dns_skip_all_addl dns_skip_all_auth dns_skip_auth
event dns_A6_reply%(c: connection, msg: dns_msg, ans: dns_answer, a: addr%) &group="dns";
## Generated for DNS replies of type *NS*. For replies with multiple answers, an
## individual event of the corresponding type is raised for each.

View file

@ -186,7 +186,7 @@ _nb_dns_cmpsockaddr(register struct sockaddr *sa1,
#endif
static const char serr[] = "answer from wrong nameserver (%d)";
if (sa1->sa_family != sa1->sa_family) {
if (sa1->sa_family != sa2->sa_family) {
snprintf(errstr, NB_DNS_ERRSIZE, serr, 1);
return (-1);
}
@ -381,7 +381,7 @@ nb_dns_addr_request2(register struct nb_dns_info *nd, char *addrp,
size -= i;
cp += i;
}
snprintf(cp, size, "ip6.int");
snprintf(cp, size, "ip6.arpa");
break;
#endif

View file

@ -2,17 +2,16 @@
#include "config.h"
#ifdef BROv6
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#endif
#include "Reporter.h"
#include "net_util.h"
#include "IPAddr.h"
// - adapted from tcpdump
// Returns the ones-complement checksum of a chunk of b short-aligned bytes.
@ -81,7 +80,6 @@ int udp_checksum(const struct ip* ip, const struct udphdr* up, int len)
return sum;
}
#ifdef BROv6
int udp6_checksum(const struct ip6_hdr* ip6, const struct udphdr* up, int len)
{
// UDP over IPv6 uses the same checksum function as over IPv4 but a
@ -135,7 +133,6 @@ int icmp6_checksum(const struct icmp* icmpp, const struct ip6_hdr* ip6, int len)
return sum;
}
#endif
int icmp_checksum(const struct icmp* icmpp, int len)
{
@ -172,225 +169,27 @@ char addr_to_class(uint32 addr)
return 'A';
}
uint32 addr_to_net(uint32 addr)
const char* fmt_conn_id(const IPAddr& src_addr, uint32 src_port,
const IPAddr& dst_addr, uint32 dst_port)
{
if ( CHECK_CLASS(addr, CLASS_D) )
; // class D's are left alone ###
else if ( CHECK_CLASS(addr, CLASS_C) )
addr = addr & 0xffffff00;
else if ( CHECK_CLASS(addr, CLASS_B) )
addr = addr & 0xffff0000;
else
addr = addr & 0xff000000;
static char buffer[512];
return addr;
}
safe_snprintf(buffer, sizeof(buffer), "%s:%d > %s:%d",
string(src_addr).c_str(), src_port,
string(dst_addr).c_str(), dst_port);
const char* dotted_addr(uint32 addr, int alternative)
{
addr = ntohl(addr);
const char* fmt = alternative ? "%d,%d.%d.%d" : "%d.%d.%d.%d";
static char buf[32];
snprintf(buf, sizeof(buf), fmt,
addr >> 24, (addr >> 16) & 0xff,
(addr >> 8) & 0xff, addr & 0xff);
return buf;
}
const char* dotted_addr(const uint32* addr, int alternative)
{
#ifdef BROv6
if ( is_v4_addr(addr) )
return dotted_addr(addr[3], alternative);
static char buf[256];
if ( inet_ntop(AF_INET6, addr, buf, sizeof buf) == NULL )
return "<bad IPv6 address conversion>";
return buf;
#else
return dotted_addr(to_v4_addr(addr), alternative);
#endif
}
const char* dotted_net(uint32 addr)
{
addr = ntohl(addr);
static char buf[32];
if ( CHECK_CLASS(addr, CLASS_D) )
sprintf(buf, "%d.%d.%d.%d",
addr >> 24, (addr >> 16) & 0xff,
(addr >> 8) & 0xff, addr & 0xff);
else if ( CHECK_CLASS(addr, CLASS_C) )
sprintf(buf, "%d.%d.%d",
addr >> 24, (addr >> 16) & 0xff, (addr >> 8) & 0xff);
else
// Same for class A's and B's.
sprintf(buf, "%d.%d", addr >> 24, (addr >> 16) & 0xff);
return buf;
}
#ifdef BROv6
const char* dotted_net6(const uint32* addr)
{
if ( is_v4_addr(addr) )
return dotted_net(to_v4_addr(addr));
else
// ### this isn't right, but net's should go away eventually ...
return dotted_addr(addr);
}
#endif
uint32 dotted_to_addr(const char* addr_text)
{
int addr[4];
if ( sscanf(addr_text,
"%d.%d.%d.%d", addr+0, addr+1, addr+2, addr+3) != 4 )
{
reporter->Error("bad dotted address: %s", addr_text );
return 0;
}
if ( addr[0] < 0 || addr[1] < 0 || addr[2] < 0 || addr[3] < 0 ||
addr[0] > 255 || addr[1] > 255 || addr[2] > 255 || addr[3] > 255 )
{
reporter->Error("bad dotted address: %s", addr_text);
return 0;
}
uint32 a = (addr[0] << 24) | (addr[1] << 16) | (addr[2] << 8) | addr[3];
// ### perhaps do gethostbyaddr here?
return uint32(htonl(a));
}
#ifdef BROv6
uint32* dotted_to_addr6(const char* addr_text)
{
uint32* addr = new uint32[4];
if ( inet_pton(AF_INET6, addr_text, addr) <= 0 )
{
reporter->Error("bad IPv6 address: %s", addr_text );
addr[0] = addr[1] = addr[2] = addr[3] = 0;
}
return addr;
}
#endif
#ifdef BROv6
int is_v4_addr(const uint32 addr[4])
{
return addr[0] == 0 && addr[1] == 0 && addr[2] == 0;
}
#endif
uint32 to_v4_addr(const uint32* addr)
{
#ifdef BROv6
if ( ! is_v4_addr(addr) )
reporter->InternalError("conversion of non-IPv4 address to IPv4 address");
return addr[3];
#else
return addr[0];
#endif
}
uint32 mask_addr(uint32 a, uint32 top_bits_to_keep)
{
if ( top_bits_to_keep > 32 )
{
reporter->Error("bad address mask value %d", top_bits_to_keep);
return a;
}
if ( top_bits_to_keep == 0 )
// The shifts below don't have any effect with 0, i.e.,
// 1 << 32 does not yield 0; either due to compiler
// misoptimization or language semantics.
return 0;
uint32 addr = ntohl(a);
int shift = 32 - top_bits_to_keep;
addr >>= shift;
addr <<= shift;
return htonl(addr);
}
const uint32* mask_addr(const uint32* a, uint32 top_bits_to_keep)
{
#ifdef BROv6
static uint32 addr[4];
addr[0] = a[0];
addr[1] = a[1];
addr[2] = a[2];
addr[3] = a[3];
// This is a bit dicey: if it's a v4 address, then we interpret
// the mask as being with respect to 32 bits total, even though
// strictly speaking, the v4 address comprises the least-significant
// bits out of 128, rather than the most significant. However,
// we only do this if the mask itself is consistent for a 32-bit
// address.
uint32 max_bits = (is_v4_addr(a) && top_bits_to_keep <= 32) ? 32 : 128;
if ( top_bits_to_keep == 0 || top_bits_to_keep > max_bits )
{
reporter->Error("bad address mask value %s", top_bits_to_keep);
return addr;
}
int word = 3; // start zeroing out with word #3
int bits_to_chop = max_bits - top_bits_to_keep; // bits to discard
while ( bits_to_chop >= 32 )
{ // there's an entire word to discard
addr[word] = 0;
--word; // move on to next, more significant word
bits_to_chop -= 32; // we just go rid of 32 bits
}
// All that's left to work with now is the word pointed to by "word".
uint32 addr32 = ntohl(addr[word]);
addr32 >>= bits_to_chop;
addr32 <<= bits_to_chop;
addr[word] = htonl(addr32);
return addr;
#else
return a;
#endif
return buffer;
}
const char* fmt_conn_id(const uint32* src_addr, uint32 src_port,
const uint32* dst_addr, uint32 dst_port)
{
char addr1[128], addr2[128];
static char buffer[512];
strcpy(addr1, dotted_addr(src_addr));
strcpy(addr2, dotted_addr(dst_addr));
safe_snprintf(buffer, sizeof(buffer), "%s:%d > %s:%d",
addr1, src_port, addr2, dst_port);
return buffer;
IPAddr src(IPAddr::IPv6, src_addr, IPAddr::Network);
IPAddr dst(IPAddr::IPv6, dst_addr, IPAddr::Network);
return fmt_conn_id(src, src_port, dst, dst_port);
}
uint32 extract_uint32(const u_char* data)
{
uint32 val;

View file

@ -21,6 +21,7 @@
#include <netinet/ip_icmp.h>
#include "util.h"
#include "IPAddr.h"
#ifdef HAVE_NETINET_IP6_H
#include <netinet/ip6.h>
@ -32,30 +33,6 @@ struct ip6_hdr {
};
#endif
#include "util.h"
#ifdef BROv6
typedef uint32* addr_type; // a pointer to 4 uint32's
typedef const uint32* const_addr_type;
#define NUM_ADDR_WORDS 4
typedef struct {
uint32 net[4];
uint32 width;
} subnet_type;
#else
typedef uint32 addr_type;
typedef const uint32 const_addr_type;
#define NUM_ADDR_WORDS 1
typedef struct {
uint32 net;
uint32 width;
} subnet_type;
#endif
// For Solaris.
#if !defined(TCPOPT_WINDOW) && defined(TCPOPT_WSCALE)
#define TCPOPT_WINDOW TCPOPT_WSCALE
@ -86,81 +63,20 @@ extern int ones_complement_checksum(const void* p, int b, uint32 sum);
extern int tcp_checksum(const struct ip* ip, const struct tcphdr* tp, int len);
extern int udp_checksum(const struct ip* ip, const struct udphdr* up, int len);
extern int icmp_checksum(const struct icmp* icmpp, int len);
#ifdef BROv6
extern int udp6_checksum(const struct ip6_hdr* ip, const struct udphdr* up,
int len);
extern int icmp6_checksum(const struct icmp* icmpp, const struct ip6_hdr* ip6,
int len);
#endif
extern int icmp_checksum(const struct icmp* icmpp, int len);
// Given an address in host order, returns its "classical network prefix",
// also in host order.
extern uint32 addr_to_net(uint32 addr);
// Returns 'A', 'B', 'C' or 'D'
extern char addr_to_class(uint32 addr);
// Returns a pointer to static storage giving the ASCII dotted representation
// of the given address, which should be passed in network order.
extern const char* dotted_addr(uint32 addr, int alternative=0);
extern const char* dotted_addr(const uint32* addr, int alternative=0);
// Same, but for the network prefix.
extern const char* dotted_net(uint32 addr);
extern const char* dotted_net6(const uint32* addr);
// Given an ASCII dotted representation, returns the corresponding address
// in network order.
extern uint32 dotted_to_addr(const char* addr_text);
extern uint32* dotted_to_addr6(const char* addr_text);
extern int is_v4_addr(const uint32 addr[4]);
extern uint32 to_v4_addr(const uint32* addr);
extern uint32 mask_addr(uint32 a, uint32 top_bits_to_keep);
extern const uint32* mask_addr(const uint32* a, uint32 top_bits_to_keep);
extern const char* fmt_conn_id(const IPAddr& src_addr, uint32 src_port,
const IPAddr& dst_addr, uint32 dst_port);
extern const char* fmt_conn_id(const uint32* src_addr, uint32 src_port,
const uint32* dst_addr, uint32 dst_port);
inline void copy_addr(const uint32* src_a, uint32* dst_a)
{
#ifdef BROv6
dst_a[0] = src_a[0];
dst_a[1] = src_a[1];
dst_a[2] = src_a[2];
dst_a[3] = src_a[3];
#else
dst_a[0] = src_a[0];
#endif
}
inline int addr_eq(const uint32* a1, const uint32* a2)
{
#ifdef BROv6
return a1[0] == a2[0] &&
a1[1] == a2[1] &&
a1[2] == a2[2] &&
a1[3] == a2[3];
#else
return a1[0] == a2[0];
#endif
}
inline int subnet_eq(const subnet_type* s1, const subnet_type* s2)
{
#ifdef BROv6
return s1->net[0] == s2->net[0] &&
s1->net[1] == s2->net[1] &&
s1->net[2] == s2->net[2] &&
s1->net[3] == s2->net[3] &&
s1->width == s2->width;
#else
return s1->net == s2->net && s1->width == s2->width;
#endif
}
// Read 4 bytes from data and return in network order.
extern uint32 extract_uint32(const u_char* data);

View file

@ -259,7 +259,7 @@ New_Prefix2 (int family, void *dest, int bitlen, prefix_t *prefix)
if (family == AF_INET6) {
default_bitlen = 128;
if (prefix == NULL) {
prefix = calloc(1, sizeof (prefix6_t));
prefix = calloc(1, sizeof (prefix_t));
dynamic_allocated++;
}
memcpy (&prefix->add.sin6, dest, 16);

View file

@ -53,11 +53,9 @@
#include <sys/types.h>
#ifdef BROv6
#ifndef HAVE_IPV6
#define HAVE_IPV6
#endif
#endif
/* typedef unsigned int u_int; */
typedef void (*void_fn_t)();