mirror of
https://github.com/zeek/zeek.git
synced 2025-10-14 04:28:20 +00:00
Changes to IPv6 ext. header parsing (addresses #795).
In response to feedback from Robin: - rename "ip_hdr" to "ip4_hdr" - pkt_hdr$ip6 is now of type "ip6_hdr" instead of "ip6_hdr_chain" - "ip6_hdr_chain" no longer contains an "ip6_hdr" field, instead it's the other way around, "ip6_hdr" contains an "ip6_hdr_chain" - other internal refactoring
This commit is contained in:
parent
f11fca588e
commit
1c1d657039
10 changed files with 491 additions and 449 deletions
345
src/IP.cc
345
src/IP.cc
|
@ -5,7 +5,7 @@
|
|||
#include "Val.h"
|
||||
#include "Var.h"
|
||||
|
||||
static RecordType* ip_hdr_type = 0;
|
||||
static RecordType* ip4_hdr_type = 0;
|
||||
static RecordType* ip6_hdr_type = 0;
|
||||
static RecordType* ip6_hdr_chain_type = 0;
|
||||
static RecordType* ip6_option_type = 0;
|
||||
|
@ -22,20 +22,6 @@ static inline RecordType* hdrType(RecordType*& type, const char* name)
|
|||
return type;
|
||||
}
|
||||
|
||||
RecordVal* IPv6_Hdr::BuildRecordVal() const
|
||||
{
|
||||
RecordVal* rv = new RecordVal(hdrType(ip6_hdr_type, "ip6_hdr"));
|
||||
const struct ip6_hdr* ip6 = (const struct ip6_hdr*)data;
|
||||
rv->Assign(0, new Val((ntohl(ip6->ip6_flow) & 0x0ff00000)>>20, TYPE_COUNT));
|
||||
rv->Assign(1, new Val(ntohl(ip6->ip6_flow) & 0x000fffff, TYPE_COUNT));
|
||||
rv->Assign(2, new Val(ntohs(ip6->ip6_plen), TYPE_COUNT));
|
||||
rv->Assign(3, new Val(ip6->ip6_nxt, TYPE_COUNT));
|
||||
rv->Assign(4, new Val(ip6->ip6_hlim, TYPE_COUNT));
|
||||
rv->Assign(5, new AddrVal(ip6->ip6_src));
|
||||
rv->Assign(6, new AddrVal(ip6->ip6_dst));
|
||||
return rv;
|
||||
}
|
||||
|
||||
static VectorVal* BuildOptionsVal(const u_char* data, uint16 len)
|
||||
{
|
||||
VectorVal* vv = new VectorVal(new VectorType(
|
||||
|
@ -71,73 +57,100 @@ static VectorVal* BuildOptionsVal(const u_char* data, uint16 len)
|
|||
return vv;
|
||||
}
|
||||
|
||||
RecordVal* IPv6_HopOpts::BuildRecordVal() const
|
||||
RecordVal* IPv6_Hdr::BuildRecordVal() const
|
||||
{
|
||||
RecordVal* rv = new RecordVal(hdrType(ip6_hopopts_type, "ip6_hopopts"));
|
||||
const struct ip6_hbh* hbh = (const struct ip6_hbh*)data;
|
||||
rv->Assign(0, new Val(hbh->ip6h_nxt, TYPE_COUNT));
|
||||
rv->Assign(1, new Val(hbh->ip6h_len, TYPE_COUNT));
|
||||
uint16 off = 2 * sizeof(uint8);
|
||||
rv->Assign(2, BuildOptionsVal(data + off, Length() - off));
|
||||
return rv;
|
||||
RecordVal* rv = 0;
|
||||
|
||||
switch ( type ) {
|
||||
case IPPROTO_IPV6:
|
||||
{
|
||||
rv = new RecordVal(hdrType(ip6_hdr_type, "ip6_hdr"));
|
||||
const struct ip6_hdr* ip6 = (const struct ip6_hdr*)data;
|
||||
rv->Assign(0, new Val((ntohl(ip6->ip6_flow) & 0x0ff00000)>>20, TYPE_COUNT));
|
||||
rv->Assign(1, new Val(ntohl(ip6->ip6_flow) & 0x000fffff, TYPE_COUNT));
|
||||
rv->Assign(2, new Val(ntohs(ip6->ip6_plen), TYPE_COUNT));
|
||||
rv->Assign(3, new Val(ip6->ip6_nxt, TYPE_COUNT));
|
||||
rv->Assign(4, new Val(ip6->ip6_hlim, TYPE_COUNT));
|
||||
rv->Assign(5, new AddrVal(ip6->ip6_src));
|
||||
rv->Assign(6, new AddrVal(ip6->ip6_dst));
|
||||
}
|
||||
break;
|
||||
|
||||
case IPPROTO_HOPOPTS:
|
||||
{
|
||||
rv = new RecordVal(hdrType(ip6_hopopts_type, "ip6_hopopts"));
|
||||
const struct ip6_hbh* hbh = (const struct ip6_hbh*)data;
|
||||
rv->Assign(0, new Val(hbh->ip6h_nxt, TYPE_COUNT));
|
||||
rv->Assign(1, new Val(hbh->ip6h_len, TYPE_COUNT));
|
||||
uint16 off = 2 * sizeof(uint8);
|
||||
rv->Assign(2, BuildOptionsVal(data + off, Length() - off));
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case IPPROTO_DSTOPTS:
|
||||
{
|
||||
rv = new RecordVal(hdrType(ip6_dstopts_type, "ip6_dstopts"));
|
||||
const struct ip6_dest* dst = (const struct ip6_dest*)data;
|
||||
rv->Assign(0, new Val(dst->ip6d_nxt, TYPE_COUNT));
|
||||
rv->Assign(1, new Val(dst->ip6d_len, TYPE_COUNT));
|
||||
uint16 off = 2 * sizeof(uint8);
|
||||
rv->Assign(2, BuildOptionsVal(data + off, Length() - off));
|
||||
}
|
||||
break;
|
||||
|
||||
case IPPROTO_ROUTING:
|
||||
{
|
||||
rv = new RecordVal(hdrType(ip6_routing_type, "ip6_routing"));
|
||||
const struct ip6_rthdr* rt = (const struct ip6_rthdr*)data;
|
||||
rv->Assign(0, new Val(rt->ip6r_nxt, TYPE_COUNT));
|
||||
rv->Assign(1, new Val(rt->ip6r_len, TYPE_COUNT));
|
||||
rv->Assign(2, new Val(rt->ip6r_type, TYPE_COUNT));
|
||||
rv->Assign(3, new Val(rt->ip6r_segleft, TYPE_COUNT));
|
||||
uint16 off = 4 * sizeof(uint8);
|
||||
rv->Assign(4, new StringVal(new BroString(data + off, Length() - off, 1)));
|
||||
}
|
||||
break;
|
||||
|
||||
case IPPROTO_FRAGMENT:
|
||||
{
|
||||
rv = new RecordVal(hdrType(ip6_fragment_type, "ip6_fragment"));
|
||||
const struct ip6_frag* frag = (const struct ip6_frag*)data;
|
||||
rv->Assign(0, new Val(frag->ip6f_nxt, TYPE_COUNT));
|
||||
rv->Assign(1, new Val(frag->ip6f_reserved, TYPE_COUNT));
|
||||
rv->Assign(2, new Val((ntohs(frag->ip6f_offlg) & 0xfff8)>>3, TYPE_COUNT));
|
||||
rv->Assign(3, new Val((ntohs(frag->ip6f_offlg) & 0x0006)>>1, TYPE_COUNT));
|
||||
rv->Assign(4, new Val(ntohs(frag->ip6f_offlg) & 0x0001, TYPE_BOOL));
|
||||
rv->Assign(5, new Val(ntohl(frag->ip6f_ident), TYPE_COUNT));
|
||||
}
|
||||
break;
|
||||
|
||||
case IPPROTO_AH:
|
||||
{
|
||||
rv = new RecordVal(hdrType(ip6_ah_type, "ip6_ah"));
|
||||
rv->Assign(0, new Val(((ip6_ext*)data)->ip6e_nxt, TYPE_COUNT));
|
||||
rv->Assign(1, new Val(((ip6_ext*)data)->ip6e_len, TYPE_COUNT));
|
||||
rv->Assign(2, new Val(ntohs(((uint16*)data)[1]), TYPE_COUNT));
|
||||
rv->Assign(3, new Val(ntohl(((uint32*)data)[1]), TYPE_COUNT));
|
||||
rv->Assign(4, new Val(ntohl(((uint32*)data)[2]), TYPE_COUNT));
|
||||
uint16 off = 3 * sizeof(uint32);
|
||||
rv->Assign(5, new StringVal(new BroString(data + off, Length() - off, 1)));
|
||||
}
|
||||
break;
|
||||
|
||||
case IPPROTO_ESP:
|
||||
{
|
||||
rv = new RecordVal(hdrType(ip6_esp_type, "ip6_esp"));
|
||||
const uint32* esp = (const uint32*)data;
|
||||
rv->Assign(0, new Val(ntohl(esp[0]), TYPE_COUNT));
|
||||
rv->Assign(1, new Val(ntohl(esp[1]), TYPE_COUNT));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
RecordVal* IPv6_DstOpts::BuildRecordVal() const
|
||||
{
|
||||
RecordVal* rv = new RecordVal(hdrType(ip6_dstopts_type, "ip6_dstopts"));
|
||||
const struct ip6_dest* dst = (const struct ip6_dest*)data;
|
||||
rv->Assign(0, new Val(dst->ip6d_nxt, TYPE_COUNT));
|
||||
rv->Assign(1, new Val(dst->ip6d_len, TYPE_COUNT));
|
||||
uint16 off = 2 * sizeof(uint8);
|
||||
rv->Assign(2, BuildOptionsVal(data + off, Length() - off));
|
||||
return rv;
|
||||
}
|
||||
|
||||
RecordVal* IPv6_Routing::BuildRecordVal() const
|
||||
{
|
||||
RecordVal* rv = new RecordVal(hdrType(ip6_routing_type, "ip6_routing"));
|
||||
const struct ip6_rthdr* rt = (const struct ip6_rthdr*)data;
|
||||
rv->Assign(0, new Val(rt->ip6r_nxt, TYPE_COUNT));
|
||||
rv->Assign(1, new Val(rt->ip6r_len, TYPE_COUNT));
|
||||
rv->Assign(2, new Val(rt->ip6r_type, TYPE_COUNT));
|
||||
rv->Assign(3, new Val(rt->ip6r_segleft, TYPE_COUNT));
|
||||
uint16 off = 4 * sizeof(uint8);
|
||||
rv->Assign(4, new StringVal(new BroString(data + off, Length() - off, 1)));
|
||||
return rv;
|
||||
}
|
||||
|
||||
RecordVal* IPv6_Fragment::BuildRecordVal() const
|
||||
{
|
||||
RecordVal* rv = new RecordVal(hdrType(ip6_fragment_type, "ip6_fragment"));
|
||||
const struct ip6_frag* frag = (const struct ip6_frag*)data;
|
||||
rv->Assign(0, new Val(frag->ip6f_nxt, TYPE_COUNT));
|
||||
rv->Assign(1, new Val(frag->ip6f_reserved, TYPE_COUNT));
|
||||
rv->Assign(2, new Val((ntohs(frag->ip6f_offlg) & 0xfff8)>>3, TYPE_COUNT));
|
||||
rv->Assign(3, new Val((ntohs(frag->ip6f_offlg) & 0x0006)>>1, TYPE_COUNT));
|
||||
rv->Assign(4, new Val(ntohs(frag->ip6f_offlg) & 0x0001, TYPE_BOOL));
|
||||
rv->Assign(5, new Val(ntohl(frag->ip6f_ident), TYPE_COUNT));
|
||||
return rv;
|
||||
}
|
||||
|
||||
RecordVal* IPv6_AH::BuildRecordVal() const
|
||||
{
|
||||
RecordVal* rv = new RecordVal(hdrType(ip6_ah_type, "ip6_ah"));
|
||||
rv->Assign(0, new Val(((ip6_ext*)data)->ip6e_nxt, TYPE_COUNT));
|
||||
rv->Assign(1, new Val(((ip6_ext*)data)->ip6e_len, TYPE_COUNT));
|
||||
rv->Assign(2, new Val(ntohs(((uint16*)data)[1]), TYPE_COUNT));
|
||||
rv->Assign(3, new Val(ntohl(((uint32*)data)[1]), TYPE_COUNT));
|
||||
rv->Assign(4, new Val(ntohl(((uint32*)data)[2]), TYPE_COUNT));
|
||||
uint16 off = 3 * sizeof(uint32);
|
||||
rv->Assign(5, new StringVal(new BroString(data + off, Length() - off, 1)));
|
||||
return rv;
|
||||
}
|
||||
|
||||
RecordVal* IPv6_ESP::BuildRecordVal() const
|
||||
{
|
||||
RecordVal* rv = new RecordVal(hdrType(ip6_esp_type, "ip6_esp"));
|
||||
const uint32* esp = (const uint32*)data;
|
||||
rv->Assign(0, new Val(ntohl(esp[0]), TYPE_COUNT));
|
||||
rv->Assign(1, new Val(ntohl(esp[1]), TYPE_COUNT));
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -145,22 +158,9 @@ RecordVal* IP_Hdr::BuildIPHdrVal() const
|
|||
{
|
||||
RecordVal* rval = 0;
|
||||
|
||||
if ( ! ip_hdr_type )
|
||||
{
|
||||
ip_hdr_type = internal_type("ip_hdr")->AsRecordType();
|
||||
ip6_hdr_type = internal_type("ip6_hdr")->AsRecordType();
|
||||
ip6_hdr_chain_type = internal_type("ip6_hdr_chain")->AsRecordType();
|
||||
ip6_hopopts_type = internal_type("ip6_hopopts")->AsRecordType();
|
||||
ip6_dstopts_type = internal_type("ip6_dstopts")->AsRecordType();
|
||||
ip6_routing_type = internal_type("ip6_routing")->AsRecordType();
|
||||
ip6_fragment_type = internal_type("ip6_fragment")->AsRecordType();
|
||||
ip6_ah_type = internal_type("ip6_ah")->AsRecordType();
|
||||
ip6_esp_type = internal_type("ip6_esp")->AsRecordType();
|
||||
}
|
||||
|
||||
if ( ip4 )
|
||||
{
|
||||
rval = new RecordVal(ip_hdr_type);
|
||||
rval = new RecordVal(hdrType(ip4_hdr_type, "ip4_hdr"));
|
||||
rval->Assign(0, new Val(ip4->ip_hl * 4, TYPE_COUNT));
|
||||
rval->Assign(1, new Val(ip4->ip_tos, TYPE_COUNT));
|
||||
rval->Assign(2, new Val(ntohs(ip4->ip_len), TYPE_COUNT));
|
||||
|
@ -172,55 +172,8 @@ RecordVal* IP_Hdr::BuildIPHdrVal() const
|
|||
}
|
||||
else
|
||||
{
|
||||
rval = new RecordVal(ip6_hdr_chain_type);
|
||||
|
||||
VectorVal* hopopts = new VectorVal(new VectorType(ip6_hopopts_type->Ref()));
|
||||
VectorVal* dstopts = new VectorVal(new VectorType(ip6_dstopts_type->Ref()));
|
||||
VectorVal* routing = new VectorVal(new VectorType(ip6_routing_type->Ref()));
|
||||
VectorVal* fragment = new VectorVal(new VectorType(ip6_fragment_type->Ref()));
|
||||
VectorVal* ah = new VectorVal(new VectorType(ip6_ah_type->Ref()));
|
||||
VectorVal* esp = new VectorVal(new VectorType(ip6_esp_type->Ref()));
|
||||
VectorVal* order = new VectorVal(new VectorType(base_type(TYPE_COUNT)));
|
||||
|
||||
for ( size_t i = 1; i < ip6_hdrs->Size(); ++i )
|
||||
{
|
||||
RecordVal* v = ((*ip6_hdrs)[i])->BuildRecordVal();
|
||||
uint8 type = ((*ip6_hdrs)[i])->Type();
|
||||
switch (type) {
|
||||
case IPPROTO_HOPOPTS:
|
||||
hopopts->Assign(hopopts->Size(), v, 0);
|
||||
break;
|
||||
case IPPROTO_ROUTING:
|
||||
routing->Assign(routing->Size(), v, 0);
|
||||
break;
|
||||
case IPPROTO_DSTOPTS:
|
||||
dstopts->Assign(dstopts->Size(), v, 0);
|
||||
break;
|
||||
case IPPROTO_FRAGMENT:
|
||||
fragment->Assign(fragment->Size(), v, 0);
|
||||
break;
|
||||
case IPPROTO_AH:
|
||||
ah->Assign(ah->Size(), v, 0);
|
||||
break;
|
||||
case IPPROTO_ESP:
|
||||
esp->Assign(esp->Size(), v, 0);
|
||||
break;
|
||||
case IPPROTO_IPV6:
|
||||
default:
|
||||
reporter->InternalError("pkt_hdr assigned bad header %d", type);
|
||||
break;
|
||||
}
|
||||
order->Assign(i-1, new Val(type, TYPE_COUNT), 0);
|
||||
}
|
||||
|
||||
rval->Assign(0, ((*ip6_hdrs)[0])->BuildRecordVal());
|
||||
rval->Assign(1, hopopts);
|
||||
rval->Assign(2, dstopts);
|
||||
rval->Assign(3, routing);
|
||||
rval->Assign(4, fragment);
|
||||
rval->Assign(5, ah);
|
||||
rval->Assign(6, esp);
|
||||
rval->Assign(7, order);
|
||||
rval = ((*ip6_hdrs)[0])->BuildRecordVal();
|
||||
rval->Assign(7, ip6_hdrs->BuildRecordVal());
|
||||
}
|
||||
|
||||
return rval;
|
||||
|
@ -308,34 +261,6 @@ RecordVal* IP_Hdr::BuildPktHdrVal() const
|
|||
return pkt_hdr;
|
||||
}
|
||||
|
||||
static inline IPv6_Hdr* getIPv6Header(uint8 type, const u_char* d,
|
||||
bool set_next = false, uint16 nxt = 0)
|
||||
{
|
||||
switch (type) {
|
||||
case IPPROTO_IPV6:
|
||||
return set_next ? new IPv6_Hdr(d, nxt) : new IPv6_Hdr(d);
|
||||
case IPPROTO_HOPOPTS:
|
||||
return set_next ? new IPv6_HopOpts(d, nxt) : new IPv6_HopOpts(d);
|
||||
case IPPROTO_ROUTING:
|
||||
return set_next ? new IPv6_Routing(d, nxt) : new IPv6_Routing(d);
|
||||
case IPPROTO_DSTOPTS:
|
||||
return set_next ? new IPv6_DstOpts(d, nxt) : new IPv6_DstOpts(d);
|
||||
case IPPROTO_FRAGMENT:
|
||||
return set_next ? new IPv6_Fragment(d, nxt) : new IPv6_Fragment(d);
|
||||
case IPPROTO_AH:
|
||||
return set_next ? new IPv6_AH(d, nxt) : new IPv6_AH(d);
|
||||
case IPPROTO_ESP:
|
||||
return new IPv6_ESP(d); // never able to set ESP header's next
|
||||
default:
|
||||
// should never get here if calls are protected by isIPv6ExtHeader()
|
||||
reporter->InternalError("Unknown IPv6 header type: %d", type);
|
||||
break;
|
||||
}
|
||||
// can't be reached
|
||||
assert(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline bool isIPv6ExtHeader(uint8 type)
|
||||
{
|
||||
switch (type) {
|
||||
|
@ -361,12 +286,86 @@ void IPv6_Hdr_Chain::Init(const struct ip6_hdr* ip6, bool set_next, uint16 next)
|
|||
do
|
||||
{
|
||||
current_type = next_type;
|
||||
chain.push_back(getIPv6Header(current_type, hdrs, set_next, next));
|
||||
next_type = chain[chain.size()-1]->NextHdr();
|
||||
uint16 len = chain[chain.size()-1]->Length();
|
||||
IPv6_Hdr* p = new IPv6_Hdr(current_type, hdrs);
|
||||
|
||||
next_type = p->NextHdr();
|
||||
uint16 len = p->Length();
|
||||
|
||||
if ( set_next && next_type == IPPROTO_FRAGMENT )
|
||||
{
|
||||
p->ChangeNext(next);
|
||||
next_type = next;
|
||||
}
|
||||
|
||||
chain.push_back(p);
|
||||
|
||||
hdrs += len;
|
||||
length += len;
|
||||
} while ( current_type != IPPROTO_FRAGMENT &&
|
||||
current_type != IPPROTO_ESP &&
|
||||
isIPv6ExtHeader(next_type) );
|
||||
}
|
||||
|
||||
RecordVal* IPv6_Hdr_Chain::BuildRecordVal() const
|
||||
{
|
||||
if ( ! ip6_hdr_chain_type )
|
||||
{
|
||||
ip6_hdr_chain_type = internal_type("ip6_hdr_chain")->AsRecordType();
|
||||
ip6_hopopts_type = internal_type("ip6_hopopts")->AsRecordType();
|
||||
ip6_dstopts_type = internal_type("ip6_dstopts")->AsRecordType();
|
||||
ip6_routing_type = internal_type("ip6_routing")->AsRecordType();
|
||||
ip6_fragment_type = internal_type("ip6_fragment")->AsRecordType();
|
||||
ip6_ah_type = internal_type("ip6_ah")->AsRecordType();
|
||||
ip6_esp_type = internal_type("ip6_esp")->AsRecordType();
|
||||
}
|
||||
|
||||
RecordVal* rval = new RecordVal(ip6_hdr_chain_type);
|
||||
|
||||
VectorVal* hopopts = new VectorVal(new VectorType(ip6_hopopts_type->Ref()));
|
||||
VectorVal* dstopts = new VectorVal(new VectorType(ip6_dstopts_type->Ref()));
|
||||
VectorVal* routing = new VectorVal(new VectorType(ip6_routing_type->Ref()));
|
||||
VectorVal* fragment = new VectorVal(new VectorType(ip6_fragment_type->Ref()));
|
||||
VectorVal* ah = new VectorVal(new VectorType(ip6_ah_type->Ref()));
|
||||
VectorVal* esp = new VectorVal(new VectorType(ip6_esp_type->Ref()));
|
||||
VectorVal* order = new VectorVal(new VectorType(base_type(TYPE_COUNT)));
|
||||
|
||||
for ( size_t i = 1; i < chain.size(); ++i )
|
||||
{
|
||||
RecordVal* v = chain[i]->BuildRecordVal();
|
||||
uint8 type = chain[i]->Type();
|
||||
switch (type) {
|
||||
case IPPROTO_HOPOPTS:
|
||||
hopopts->Assign(hopopts->Size(), v, 0);
|
||||
break;
|
||||
case IPPROTO_ROUTING:
|
||||
routing->Assign(routing->Size(), v, 0);
|
||||
break;
|
||||
case IPPROTO_DSTOPTS:
|
||||
dstopts->Assign(dstopts->Size(), v, 0);
|
||||
break;
|
||||
case IPPROTO_FRAGMENT:
|
||||
fragment->Assign(fragment->Size(), v, 0);
|
||||
break;
|
||||
case IPPROTO_AH:
|
||||
ah->Assign(ah->Size(), v, 0);
|
||||
break;
|
||||
case IPPROTO_ESP:
|
||||
esp->Assign(esp->Size(), v, 0);
|
||||
break;
|
||||
case IPPROTO_IPV6:
|
||||
default:
|
||||
reporter->InternalError("pkt_hdr assigned bad header %d", type);
|
||||
break;
|
||||
}
|
||||
order->Assign(i-1, new Val(type, TYPE_COUNT), 0);
|
||||
}
|
||||
|
||||
rval->Assign(0, hopopts);
|
||||
rval->Assign(1, dstopts);
|
||||
rval->Assign(2, routing);
|
||||
rval->Assign(3, fragment);
|
||||
rval->Assign(4, ah);
|
||||
rval->Assign(5, esp);
|
||||
rval->Assign(6, order);
|
||||
return rval;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue