mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 14:48:21 +00:00
Add IPv6 fragment reassembly.
This commit is contained in:
parent
a0e07018f4
commit
9d590456b0
4 changed files with 180 additions and 61 deletions
57
src/Frag.cc
57
src/Frag.cc
|
@ -33,13 +33,23 @@ FragReassembler::FragReassembler(NetSessions* arg_s,
|
||||||
s = arg_s;
|
s = arg_s;
|
||||||
key = k;
|
key = k;
|
||||||
const struct ip* ip4 = ip->IP4_Hdr();
|
const struct ip* ip4 = ip->IP4_Hdr();
|
||||||
proto_hdr_len = ip4->ip_hl * 4;
|
if ( ip4 )
|
||||||
proto_hdr = (struct ip*) new u_char[64]; // max IP header + slop
|
{
|
||||||
// Don't do a structure copy - need to pick up options, too.
|
proto_hdr_len = ip4->ip_hl * 4;
|
||||||
memcpy((void*) proto_hdr, (const void*) ip4, proto_hdr_len);
|
proto_hdr = new u_char[64]; // max IP header + slop
|
||||||
|
// Don't do a structure copy - need to pick up options, too.
|
||||||
|
memcpy((void*) proto_hdr, (const void*) ip4, proto_hdr_len);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
proto_hdr_len = ip->HdrLen() - 8; // minus length of fragment header
|
||||||
|
proto_hdr = new u_char[proto_hdr_len];
|
||||||
|
memcpy(proto_hdr, ip->IP6_Hdr(), proto_hdr_len);
|
||||||
|
}
|
||||||
|
|
||||||
reassembled_pkt = 0;
|
reassembled_pkt = 0;
|
||||||
frag_size = 0; // flag meaning "not known"
|
frag_size = 0; // flag meaning "not known"
|
||||||
|
next_proto = ip->NextProto();
|
||||||
|
|
||||||
AddFragment(t, ip, pkt);
|
AddFragment(t, ip, pkt);
|
||||||
|
|
||||||
|
@ -64,22 +74,37 @@ void FragReassembler::AddFragment(double t, const IP_Hdr* ip, const u_char* pkt)
|
||||||
{
|
{
|
||||||
const struct ip* ip4 = ip->IP4_Hdr();
|
const struct ip* ip4 = ip->IP4_Hdr();
|
||||||
|
|
||||||
if ( ip4->ip_p != proto_hdr->ip_p || ip4->ip_hl != proto_hdr->ip_hl )
|
if ( ip4 )
|
||||||
|
{
|
||||||
|
if ( ip4->ip_p != ((const struct ip*)proto_hdr)->ip_p ||
|
||||||
|
ip4->ip_hl != ((const struct ip*)proto_hdr)->ip_hl )
|
||||||
// || ip4->ip_tos != proto_hdr->ip_tos
|
// || ip4->ip_tos != proto_hdr->ip_tos
|
||||||
// don't check TOS, there's at least one stack that actually
|
// don't check TOS, there's at least one stack that actually
|
||||||
// uses different values, and it's hard to see an associated
|
// uses different values, and it's hard to see an associated
|
||||||
// attack.
|
// attack.
|
||||||
s->Weird("fragment_protocol_inconsistency", ip);
|
s->Weird("fragment_protocol_inconsistency", ip);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ( ip->NextProto() != next_proto ||
|
||||||
|
ip->HdrLen() - 8 != proto_hdr_len )
|
||||||
|
s->Weird("fragment_protocol_inconsistency", ip);
|
||||||
|
//TODO: more detailed unfrag header consistency checks?
|
||||||
|
}
|
||||||
|
|
||||||
if ( ip->DF() )
|
if ( ip->DF() )
|
||||||
// Linux MTU discovery for UDP can do this, for example.
|
// Linux MTU discovery for UDP can do this, for example.
|
||||||
s->Weird("fragment_with_DF", ip);
|
s->Weird("fragment_with_DF", ip);
|
||||||
|
|
||||||
int offset = ip->FragOffset();
|
int offset = ip->FragOffset();
|
||||||
int len = ntohs(ip4->ip_len);
|
int len = ip->TotalLen();
|
||||||
int hdr_len = proto_hdr->ip_hl * 4;
|
int hdr_len = ip->HdrLen();
|
||||||
int upper_seq = offset + len - hdr_len;
|
int upper_seq = offset + len - hdr_len;
|
||||||
|
|
||||||
|
if ( ! offset )
|
||||||
|
// Make sure to use the first fragment header's next field.
|
||||||
|
next_proto = ip->NextProto();
|
||||||
|
|
||||||
if ( ! ip->MF() )
|
if ( ! ip->MF() )
|
||||||
{
|
{
|
||||||
// Last fragment.
|
// Last fragment.
|
||||||
|
@ -192,8 +217,7 @@ void FragReassembler::BlockInserted(DataBlock* /* start_block */)
|
||||||
u_char* pkt = new u_char[n];
|
u_char* pkt = new u_char[n];
|
||||||
memcpy((void*) pkt, (const void*) proto_hdr, proto_hdr_len);
|
memcpy((void*) pkt, (const void*) proto_hdr, proto_hdr_len);
|
||||||
|
|
||||||
struct ip* reassem4 = (struct ip*) pkt;
|
u_char* pkt_start = pkt;
|
||||||
reassem4->ip_len = htons(frag_size + proto_hdr_len);
|
|
||||||
|
|
||||||
pkt += proto_hdr_len;
|
pkt += proto_hdr_len;
|
||||||
|
|
||||||
|
@ -213,7 +237,20 @@ void FragReassembler::BlockInserted(DataBlock* /* start_block */)
|
||||||
}
|
}
|
||||||
|
|
||||||
delete reassembled_pkt;
|
delete reassembled_pkt;
|
||||||
reassembled_pkt = new IP_Hdr(reassem4, true);
|
|
||||||
|
if ( ((const struct ip*)pkt_start)->ip_v == 4 )
|
||||||
|
{
|
||||||
|
struct ip* reassem4 = (struct ip*) pkt_start;
|
||||||
|
reassem4->ip_len = htons(frag_size + proto_hdr_len);
|
||||||
|
reassembled_pkt = new IP_Hdr(reassem4, true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
struct ip6_hdr* reassem6 = (struct ip6_hdr*) pkt_start;
|
||||||
|
reassem6->ip6_plen = htons(frag_size + proto_hdr_len - 40);
|
||||||
|
const IPv6_Hdr_Chain* chain = new IPv6_Hdr_Chain(reassem6, next_proto);
|
||||||
|
reassembled_pkt = new IP_Hdr(reassem6, true, chain);
|
||||||
|
}
|
||||||
|
|
||||||
DeleteTimer();
|
DeleteTimer();
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,11 +36,12 @@ protected:
|
||||||
void BlockInserted(DataBlock* start_block);
|
void BlockInserted(DataBlock* start_block);
|
||||||
void Overlap(const u_char* b1, const u_char* b2, int n);
|
void Overlap(const u_char* b1, const u_char* b2, int n);
|
||||||
|
|
||||||
struct ip* proto_hdr;
|
u_char* proto_hdr;
|
||||||
IP_Hdr* reassembled_pkt;
|
IP_Hdr* reassembled_pkt;
|
||||||
int proto_hdr_len;
|
int proto_hdr_len;
|
||||||
NetSessions* s;
|
NetSessions* s;
|
||||||
int frag_size; // size of fully reassembled fragment
|
int frag_size; // size of fully reassembled fragment
|
||||||
|
uint16 next_proto; // first IPv6 fragment header's next proto field
|
||||||
HashKey* key;
|
HashKey* key;
|
||||||
|
|
||||||
FragTimer* expire_timer;
|
FragTimer* expire_timer;
|
||||||
|
|
27
src/IP.cc
27
src/IP.cc
|
@ -26,7 +26,7 @@ RecordVal* IPv6_Hdr::BuildRecordVal() const
|
||||||
{
|
{
|
||||||
RecordVal* rv = new RecordVal(hdrType(ip6_hdr_type, "ip6_hdr"));
|
RecordVal* rv = new RecordVal(hdrType(ip6_hdr_type, "ip6_hdr"));
|
||||||
const struct ip6_hdr* ip6 = (const struct ip6_hdr*)data;
|
const struct ip6_hdr* ip6 = (const struct ip6_hdr*)data;
|
||||||
rv->Assign(0, new Val(ntohl(ip6->ip6_flow) & 0x0ff00000, TYPE_COUNT));
|
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(1, new Val(ntohl(ip6->ip6_flow) & 0x000fffff, TYPE_COUNT));
|
||||||
rv->Assign(2, new Val(ntohs(ip6->ip6_plen), 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(3, new Val(ip6->ip6_nxt, TYPE_COUNT));
|
||||||
|
@ -96,8 +96,8 @@ RecordVal* IPv6_Fragment::BuildRecordVal() const
|
||||||
const struct ip6_frag* frag = (const struct ip6_frag*)data;
|
const struct ip6_frag* frag = (const struct ip6_frag*)data;
|
||||||
rv->Assign(0, new Val(frag->ip6f_nxt, TYPE_COUNT));
|
rv->Assign(0, new Val(frag->ip6f_nxt, TYPE_COUNT));
|
||||||
rv->Assign(1, new Val(frag->ip6f_reserved, TYPE_COUNT));
|
rv->Assign(1, new Val(frag->ip6f_reserved, TYPE_COUNT));
|
||||||
rv->Assign(2, new Val(ntohs(frag->ip6f_offlg) & 0xfff8, 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, 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(4, new Val(ntohs(frag->ip6f_offlg) & 0x0001, TYPE_BOOL));
|
||||||
rv->Assign(5, new Val(ntohl(frag->ip6f_ident), TYPE_COUNT));
|
rv->Assign(5, new Val(ntohl(frag->ip6f_ident), TYPE_COUNT));
|
||||||
return rv;
|
return rv;
|
||||||
|
@ -210,23 +210,24 @@ RecordVal* IP_Hdr::BuildRecordVal() const
|
||||||
return rval;
|
return rval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline IPv6_Hdr* getIPv6Header(uint8 type, const u_char* d)
|
static inline IPv6_Hdr* getIPv6Header(uint8 type, const u_char* d,
|
||||||
|
bool set_next = false, uint16 nxt = 0)
|
||||||
{
|
{
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case IPPROTO_IPV6:
|
case IPPROTO_IPV6:
|
||||||
return new IPv6_Hdr(d);
|
return set_next ? new IPv6_Hdr(d, nxt) : new IPv6_Hdr(d);
|
||||||
case IPPROTO_HOPOPTS:
|
case IPPROTO_HOPOPTS:
|
||||||
return new IPv6_HopOpts(d);
|
return set_next ? new IPv6_HopOpts(d, nxt) : new IPv6_HopOpts(d);
|
||||||
case IPPROTO_ROUTING:
|
case IPPROTO_ROUTING:
|
||||||
return new IPv6_Routing(d);
|
return set_next ? new IPv6_Routing(d, nxt) : new IPv6_Routing(d);
|
||||||
case IPPROTO_DSTOPTS:
|
case IPPROTO_DSTOPTS:
|
||||||
return new IPv6_DstOpts(d);
|
return set_next ? new IPv6_DstOpts(d, nxt) : new IPv6_DstOpts(d);
|
||||||
case IPPROTO_FRAGMENT:
|
case IPPROTO_FRAGMENT:
|
||||||
return new IPv6_Fragment(d);
|
return set_next ? new IPv6_Fragment(d, nxt) : new IPv6_Fragment(d);
|
||||||
case IPPROTO_AH:
|
case IPPROTO_AH:
|
||||||
return new IPv6_AH(d);
|
return set_next ? new IPv6_AH(d, nxt) : new IPv6_AH(d);
|
||||||
case IPPROTO_ESP:
|
case IPPROTO_ESP:
|
||||||
return new IPv6_ESP(d);
|
return new IPv6_ESP(d); // never able to set ESP header's next
|
||||||
default:
|
default:
|
||||||
// should never get here if calls are protected by isIPv6ExtHeader()
|
// should never get here if calls are protected by isIPv6ExtHeader()
|
||||||
reporter->InternalError("Unknown IPv6 header type: %d", type);
|
reporter->InternalError("Unknown IPv6 header type: %d", type);
|
||||||
|
@ -252,7 +253,7 @@ static inline bool isIPv6ExtHeader(uint8 type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IPv6_Hdr_Chain::IPv6_Hdr_Chain(const struct ip6_hdr* ip6)
|
void IPv6_Hdr_Chain::Init(const struct ip6_hdr* ip6, bool set_next, uint16 next)
|
||||||
{
|
{
|
||||||
length = 0;
|
length = 0;
|
||||||
uint8 current_type, next_type;
|
uint8 current_type, next_type;
|
||||||
|
@ -262,7 +263,7 @@ IPv6_Hdr_Chain::IPv6_Hdr_Chain(const struct ip6_hdr* ip6)
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
current_type = next_type;
|
current_type = next_type;
|
||||||
chain.push_back(getIPv6Header(current_type, hdrs));
|
chain.push_back(getIPv6Header(current_type, hdrs, set_next, next));
|
||||||
next_type = chain[chain.size()-1]->NextHdr();
|
next_type = chain[chain.size()-1]->NextHdr();
|
||||||
uint16 len = chain[chain.size()-1]->Length();
|
uint16 len = chain[chain.size()-1]->Length();
|
||||||
hdrs += len;
|
hdrs += len;
|
||||||
|
|
154
src/IP.h
154
src/IP.h
|
@ -26,6 +26,16 @@ public:
|
||||||
*/
|
*/
|
||||||
IPv6_Hdr(const u_char* d) : type(IPPROTO_IPV6), data(d) {}
|
IPv6_Hdr(const u_char* d) : type(IPPROTO_IPV6), data(d) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct the main IPv6 header, but replace the next protocol field
|
||||||
|
* if it points to a fragment.
|
||||||
|
*/
|
||||||
|
IPv6_Hdr(const u_char* d, uint16 nxt) : type(IPPROTO_IPV6), data(d)
|
||||||
|
{
|
||||||
|
if ( ((ip6_hdr*)data)->ip6_nxt == IPPROTO_FRAGMENT )
|
||||||
|
((ip6_hdr*)data)->ip6_nxt = nxt;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct an IPv6 header or extension header from assigned type number.
|
* Construct an IPv6 header or extension header from assigned type number.
|
||||||
*/
|
*/
|
||||||
|
@ -49,6 +59,11 @@ public:
|
||||||
*/
|
*/
|
||||||
uint8 Type() const { return type; }
|
uint8 Type() const { return type; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns pointer to the start of where header structure resides in memory.
|
||||||
|
*/
|
||||||
|
const u_char* Data() const { return data; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the script-layer record representation of the header.
|
* Returns the script-layer record representation of the header.
|
||||||
*/
|
*/
|
||||||
|
@ -59,50 +74,63 @@ protected:
|
||||||
const u_char* data;
|
const u_char* data;
|
||||||
};
|
};
|
||||||
|
|
||||||
class IPv6_HopOpts : public IPv6_Hdr {
|
class IPv6_Ext : public IPv6_Hdr {
|
||||||
public:
|
public:
|
||||||
IPv6_HopOpts(const u_char* d) : IPv6_Hdr(IPPROTO_HOPOPTS, d) {}
|
IPv6_Ext(uint16 type, const u_char* d) : IPv6_Hdr(type, d) {}
|
||||||
|
IPv6_Ext(uint16 type, const u_char* d, uint16 nxt) : IPv6_Hdr(type, d)
|
||||||
|
{
|
||||||
|
if ( ((ip6_ext*)data)->ip6e_nxt == IPPROTO_FRAGMENT )
|
||||||
|
((ip6_ext*)data)->ip6e_nxt = nxt;
|
||||||
|
}
|
||||||
uint8 NextHdr() const { return ((ip6_ext*)data)->ip6e_nxt; }
|
uint8 NextHdr() const { return ((ip6_ext*)data)->ip6e_nxt; }
|
||||||
|
virtual uint16 Length() const = 0;
|
||||||
|
virtual RecordVal* BuildRecordVal() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class IPv6_HopOpts : public IPv6_Ext {
|
||||||
|
public:
|
||||||
|
IPv6_HopOpts(const u_char* d) : IPv6_Ext(IPPROTO_HOPOPTS, d) {}
|
||||||
|
IPv6_HopOpts(const u_char* d, uint16 n) : IPv6_Ext(IPPROTO_HOPOPTS, d, n) {}
|
||||||
uint16 Length() const { return 8 + 8 * ((ip6_ext*)data)->ip6e_len; }
|
uint16 Length() const { return 8 + 8 * ((ip6_ext*)data)->ip6e_len; }
|
||||||
RecordVal* BuildRecordVal() const;
|
RecordVal* BuildRecordVal() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class IPv6_DstOpts : public IPv6_Hdr {
|
class IPv6_DstOpts : public IPv6_Ext {
|
||||||
public:
|
public:
|
||||||
IPv6_DstOpts(const u_char* d) : IPv6_Hdr(IPPROTO_DSTOPTS, d) {}
|
IPv6_DstOpts(const u_char* d) : IPv6_Ext(IPPROTO_DSTOPTS, d) {}
|
||||||
uint8 NextHdr() const { return ((ip6_ext*)data)->ip6e_nxt; }
|
IPv6_DstOpts(const u_char* d, uint16 n) : IPv6_Ext(IPPROTO_DSTOPTS, d, n) {}
|
||||||
uint16 Length() const { return 8 + 8 * ((ip6_ext*)data)->ip6e_len; }
|
uint16 Length() const { return 8 + 8 * ((ip6_ext*)data)->ip6e_len; }
|
||||||
RecordVal* BuildRecordVal() const;
|
RecordVal* BuildRecordVal() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class IPv6_Routing : public IPv6_Hdr {
|
class IPv6_Routing : public IPv6_Ext {
|
||||||
public:
|
public:
|
||||||
IPv6_Routing(const u_char* d) : IPv6_Hdr(IPPROTO_ROUTING, d) {}
|
IPv6_Routing(const u_char* d) : IPv6_Ext(IPPROTO_ROUTING, d) {}
|
||||||
uint8 NextHdr() const { return ((ip6_ext*)data)->ip6e_nxt; }
|
IPv6_Routing(const u_char* d, uint16 n) : IPv6_Ext(IPPROTO_ROUTING, d, n) {}
|
||||||
uint16 Length() const { return 8 + 8 * ((ip6_ext*)data)->ip6e_len; }
|
uint16 Length() const { return 8 + 8 * ((ip6_ext*)data)->ip6e_len; }
|
||||||
RecordVal* BuildRecordVal() const;
|
RecordVal* BuildRecordVal() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class IPv6_Fragment : public IPv6_Hdr {
|
class IPv6_Fragment : public IPv6_Ext {
|
||||||
public:
|
public:
|
||||||
IPv6_Fragment(const u_char* d) : IPv6_Hdr(IPPROTO_FRAGMENT, d) {}
|
IPv6_Fragment(const u_char* d) : IPv6_Ext(IPPROTO_FRAGMENT, d) {}
|
||||||
uint8 NextHdr() const { return ((ip6_ext*)data)->ip6e_nxt; }
|
IPv6_Fragment(const u_char* d, uint16 n) : IPv6_Ext(IPPROTO_FRAGMENT, d, n)
|
||||||
|
{}
|
||||||
uint16 Length() const { return 8; }
|
uint16 Length() const { return 8; }
|
||||||
RecordVal* BuildRecordVal() const;
|
RecordVal* BuildRecordVal() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class IPv6_AH : public IPv6_Hdr {
|
class IPv6_AH : public IPv6_Ext {
|
||||||
public:
|
public:
|
||||||
IPv6_AH(const u_char* d) : IPv6_Hdr(IPPROTO_AH, d) {}
|
IPv6_AH(const u_char* d) : IPv6_Ext(IPPROTO_AH, d) {}
|
||||||
uint8 NextHdr() const { return ((ip6_ext*)data)->ip6e_nxt; }
|
IPv6_AH(const u_char* d, uint16 n) : IPv6_Ext(IPPROTO_AH, d, n) {}
|
||||||
uint16 Length() const { return 8 + 4 * ((ip6_ext*)data)->ip6e_len; }
|
uint16 Length() const { return 8 + 4 * ((ip6_ext*)data)->ip6e_len; }
|
||||||
RecordVal* BuildRecordVal() const;
|
RecordVal* BuildRecordVal() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class IPv6_ESP : public IPv6_Hdr {
|
class IPv6_ESP : public IPv6_Ext {
|
||||||
public:
|
public:
|
||||||
IPv6_ESP(const u_char* d) : IPv6_Hdr(IPPROTO_ESP, d) {}
|
IPv6_ESP(const u_char* d) : IPv6_Ext(IPPROTO_ESP, d) {}
|
||||||
uint8 NextHdr() const { return ((ip6_ext*)data)->ip6e_nxt; }
|
|
||||||
// encrypted payload begins after 8 bytes
|
// encrypted payload begins after 8 bytes
|
||||||
uint16 Length() const { return 8; }
|
uint16 Length() const { return 8; }
|
||||||
RecordVal* BuildRecordVal() const;
|
RecordVal* BuildRecordVal() const;
|
||||||
|
@ -113,7 +141,14 @@ public:
|
||||||
/**
|
/**
|
||||||
* Initializes the header chain from an IPv6 header structure.
|
* Initializes the header chain from an IPv6 header structure.
|
||||||
*/
|
*/
|
||||||
IPv6_Hdr_Chain(const struct ip6_hdr* ip6);
|
IPv6_Hdr_Chain(const struct ip6_hdr* ip6) { Init(ip6, false); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the header chain from an IPv6 header structure, and replaces
|
||||||
|
* the first next protocol pointer field that points to a fragment header.
|
||||||
|
*/
|
||||||
|
IPv6_Hdr_Chain(const struct ip6_hdr* ip6, uint16 next)
|
||||||
|
{ Init(ip6, true, next); }
|
||||||
|
|
||||||
~IPv6_Hdr_Chain()
|
~IPv6_Hdr_Chain()
|
||||||
{ for ( size_t i = 0; i < chain.size(); ++i ) delete chain[i]; }
|
{ for ( size_t i = 0; i < chain.size(); ++i ) delete chain[i]; }
|
||||||
|
@ -133,22 +168,73 @@ public:
|
||||||
*/
|
*/
|
||||||
const IPv6_Hdr* operator[](const size_t i) const { return chain[i]; }
|
const IPv6_Hdr* operator[](const size_t i) const { return chain[i]; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the header chain indicates a fragmented packet.
|
||||||
|
*/
|
||||||
|
bool IsFragment() const
|
||||||
|
{ return chain[chain.size()-1]->Type() == IPPROTO_FRAGMENT; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns pointer to fragment header structure if the chain contains one.
|
||||||
|
*/
|
||||||
|
const struct ip6_frag* GetFragHdr() const
|
||||||
|
{ return IsFragment() ?
|
||||||
|
(const struct ip6_frag*)chain[chain.size()-1]->Data(): 0; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the header chain is a fragment, returns the offset in number of bytes
|
||||||
|
* relative to the start of the Fragmentable Part of the original packet.
|
||||||
|
*/
|
||||||
|
uint16 FragOffset() const
|
||||||
|
{ return IsFragment() ?
|
||||||
|
(ntohs(GetFragHdr()->ip6f_offlg) & 0xfff8) : 0; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the header chain is a fragment, returns the identification field.
|
||||||
|
*/
|
||||||
|
uint32 ID() const
|
||||||
|
{ return IsFragment() ? ntohl(GetFragHdr()->ip6f_ident) : 0; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the header chain is a fragment, returns the M (more fragments) flag.
|
||||||
|
*/
|
||||||
|
int MF() const
|
||||||
|
{ return IsFragment() ?
|
||||||
|
(ntohs(GetFragHdr()->ip6f_offlg) & 0x0001) != 0 : 0; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
void Init(const struct ip6_hdr* ip6, bool set_next, uint16 next = 0);
|
||||||
|
|
||||||
vector<IPv6_Hdr*> chain;
|
vector<IPv6_Hdr*> chain;
|
||||||
uint16 length; // The summation of all header lengths in the chain in bytes.
|
uint16 length; // The summation of all header lengths in the chain in bytes.
|
||||||
};
|
};
|
||||||
|
|
||||||
class IP_Hdr {
|
class IP_Hdr {
|
||||||
public:
|
public:
|
||||||
|
IP_Hdr(const u_char* p, bool arg_del)
|
||||||
|
: ip4(0), ip6(0), del(arg_del), ip6_hdrs(0)
|
||||||
|
{
|
||||||
|
if ( ((const struct ip*)p)->ip_v == 4 )
|
||||||
|
ip4 = (const struct ip*)p;
|
||||||
|
else if ( ((const struct ip*)p)->ip_v == 6 )
|
||||||
|
{
|
||||||
|
ip6 = (const struct ip6_hdr*)p;
|
||||||
|
ip6_hdrs = new IPv6_Hdr_Chain(ip6);
|
||||||
|
}
|
||||||
|
else if ( arg_del )
|
||||||
|
delete [] p;
|
||||||
|
}
|
||||||
|
|
||||||
IP_Hdr(const struct ip* arg_ip4, bool arg_del)
|
IP_Hdr(const struct ip* arg_ip4, bool arg_del)
|
||||||
: ip4(arg_ip4), ip6(0), del(arg_del)
|
: ip4(arg_ip4), ip6(0), del(arg_del), ip6_hdrs(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
IP_Hdr(const struct ip6_hdr* arg_ip6, bool arg_del)
|
IP_Hdr(const struct ip6_hdr* arg_ip6, bool arg_del,
|
||||||
: ip4(0), ip6(arg_ip6), del(arg_del)
|
const IPv6_Hdr_Chain* c = 0)
|
||||||
|
: ip4(0), ip6(arg_ip6), del(arg_del),
|
||||||
|
ip6_hdrs(c ? c : new IPv6_Hdr_Chain(ip6))
|
||||||
{
|
{
|
||||||
ip6_hdrs = new IPv6_Hdr_Chain(ip6);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~IP_Hdr()
|
~IP_Hdr()
|
||||||
|
@ -190,7 +276,7 @@ public:
|
||||||
return ntohs(ip6->ip6_plen) - ip6_hdrs->TotalLength();
|
return ntohs(ip6->ip6_plen) - ip6_hdrs->TotalLength();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16 TotalLen() const
|
uint32 TotalLen() const
|
||||||
{ return ip4 ? ntohs(ip4->ip_len) : ntohs(ip6->ip6_plen) + 40; }
|
{ return ip4 ? ntohs(ip4->ip_len) : ntohs(ip6->ip6_plen) + 40; }
|
||||||
|
|
||||||
uint16 HdrLen() const
|
uint16 HdrLen() const
|
||||||
|
@ -207,25 +293,19 @@ public:
|
||||||
unsigned char TTL() const
|
unsigned char TTL() const
|
||||||
{ return ip4 ? ip4->ip_ttl : ip6->ip6_hlim; }
|
{ return ip4 ? ip4->ip_ttl : ip6->ip6_hlim; }
|
||||||
|
|
||||||
//TODO: check for IPv6 Fragment ext. header
|
|
||||||
bool IsFragment() const
|
bool IsFragment() const
|
||||||
{ return ip4 ? (ntohs(ip4->ip_off) & 0x3fff) != 0 : false; }
|
{ return ip4 ? (ntohs(ip4->ip_off) & 0x3fff) != 0 :
|
||||||
|
ip6_hdrs->IsFragment(); }
|
||||||
|
|
||||||
//TODO: check for IPv6 Fragment ext. header
|
|
||||||
uint16 FragOffset() const
|
uint16 FragOffset() const
|
||||||
{ return ip4 ? (ntohs(ip4->ip_off) & 0x1fff) * 8 : 0; }
|
{ return ip4 ? (ntohs(ip4->ip_off) & 0x1fff) * 8 :
|
||||||
|
ip6_hdrs->FragOffset(); }
|
||||||
|
|
||||||
//TODO: check for IPv6 Fragment ext. header
|
uint32 ID() const
|
||||||
uint16 FragField() const
|
{ return ip4 ? ntohs(ip4->ip_id) : ip6_hdrs->ID(); }
|
||||||
{ return ip4 ? ntohs(ip4->ip_off) : 0; }
|
|
||||||
|
|
||||||
//TODO: check for IPv6 Fragment ext. header
|
|
||||||
uint16 ID() const
|
|
||||||
{ return ip4 ? ntohs(ip4->ip_id) : 0; }
|
|
||||||
|
|
||||||
//TODO: check for IPv6 Fragment ext. header
|
|
||||||
int MF() const
|
int MF() const
|
||||||
{ return ip4 ? (ntohs(ip4->ip_off) & 0x2000) != 0 : 0; }
|
{ return ip4 ? (ntohs(ip4->ip_off) & 0x2000) != 0 : ip6_hdrs->MF(); }
|
||||||
|
|
||||||
// IPv6 has no "Don't Fragment" flag.
|
// IPv6 has no "Don't Fragment" flag.
|
||||||
int DF() const
|
int DF() const
|
||||||
|
@ -240,7 +320,7 @@ private:
|
||||||
const struct ip* ip4;
|
const struct ip* ip4;
|
||||||
const struct ip6_hdr* ip6;
|
const struct ip6_hdr* ip6;
|
||||||
bool del;
|
bool del;
|
||||||
IPv6_Hdr_Chain* ip6_hdrs;
|
const IPv6_Hdr_Chain* ip6_hdrs;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue