mirror of
https://github.com/zeek/zeek.git
synced 2025-10-07 09:08:20 +00:00
Add IPv6 fragment reassembly.
This commit is contained in:
parent
a0e07018f4
commit
9d590456b0
4 changed files with 180 additions and 61 deletions
154
src/IP.h
154
src/IP.h
|
@ -26,6 +26,16 @@ public:
|
|||
*/
|
||||
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.
|
||||
*/
|
||||
|
@ -49,6 +59,11 @@ public:
|
|||
*/
|
||||
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.
|
||||
*/
|
||||
|
@ -59,50 +74,63 @@ protected:
|
|||
const u_char* data;
|
||||
};
|
||||
|
||||
class IPv6_HopOpts : public IPv6_Hdr {
|
||||
class IPv6_Ext : public IPv6_Hdr {
|
||||
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; }
|
||||
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; }
|
||||
RecordVal* BuildRecordVal() const;
|
||||
};
|
||||
|
||||
class IPv6_DstOpts : public IPv6_Hdr {
|
||||
class IPv6_DstOpts : public IPv6_Ext {
|
||||
public:
|
||||
IPv6_DstOpts(const u_char* d) : IPv6_Hdr(IPPROTO_DSTOPTS, d) {}
|
||||
uint8 NextHdr() const { return ((ip6_ext*)data)->ip6e_nxt; }
|
||||
IPv6_DstOpts(const u_char* d) : IPv6_Ext(IPPROTO_DSTOPTS, d) {}
|
||||
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; }
|
||||
RecordVal* BuildRecordVal() const;
|
||||
};
|
||||
|
||||
class IPv6_Routing : public IPv6_Hdr {
|
||||
class IPv6_Routing : public IPv6_Ext {
|
||||
public:
|
||||
IPv6_Routing(const u_char* d) : IPv6_Hdr(IPPROTO_ROUTING, d) {}
|
||||
uint8 NextHdr() const { return ((ip6_ext*)data)->ip6e_nxt; }
|
||||
IPv6_Routing(const u_char* d) : IPv6_Ext(IPPROTO_ROUTING, d) {}
|
||||
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; }
|
||||
RecordVal* BuildRecordVal() const;
|
||||
};
|
||||
|
||||
class IPv6_Fragment : public IPv6_Hdr {
|
||||
class IPv6_Fragment : public IPv6_Ext {
|
||||
public:
|
||||
IPv6_Fragment(const u_char* d) : IPv6_Hdr(IPPROTO_FRAGMENT, d) {}
|
||||
uint8 NextHdr() const { return ((ip6_ext*)data)->ip6e_nxt; }
|
||||
IPv6_Fragment(const u_char* d) : IPv6_Ext(IPPROTO_FRAGMENT, d) {}
|
||||
IPv6_Fragment(const u_char* d, uint16 n) : IPv6_Ext(IPPROTO_FRAGMENT, d, n)
|
||||
{}
|
||||
uint16 Length() const { return 8; }
|
||||
RecordVal* BuildRecordVal() const;
|
||||
};
|
||||
|
||||
class IPv6_AH : public IPv6_Hdr {
|
||||
class IPv6_AH : public IPv6_Ext {
|
||||
public:
|
||||
IPv6_AH(const u_char* d) : IPv6_Hdr(IPPROTO_AH, d) {}
|
||||
uint8 NextHdr() const { return ((ip6_ext*)data)->ip6e_nxt; }
|
||||
IPv6_AH(const u_char* d) : IPv6_Ext(IPPROTO_AH, d) {}
|
||||
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; }
|
||||
RecordVal* BuildRecordVal() const;
|
||||
};
|
||||
|
||||
class IPv6_ESP : public IPv6_Hdr {
|
||||
class IPv6_ESP : public IPv6_Ext {
|
||||
public:
|
||||
IPv6_ESP(const u_char* d) : IPv6_Hdr(IPPROTO_ESP, d) {}
|
||||
uint8 NextHdr() const { return ((ip6_ext*)data)->ip6e_nxt; }
|
||||
IPv6_ESP(const u_char* d) : IPv6_Ext(IPPROTO_ESP, d) {}
|
||||
// encrypted payload begins after 8 bytes
|
||||
uint16 Length() const { return 8; }
|
||||
RecordVal* BuildRecordVal() const;
|
||||
|
@ -113,7 +141,14 @@ public:
|
|||
/**
|
||||
* 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()
|
||||
{ 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]; }
|
||||
|
||||
/**
|
||||
* 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:
|
||||
void Init(const struct ip6_hdr* ip6, bool set_next, uint16 next = 0);
|
||||
|
||||
vector<IPv6_Hdr*> chain;
|
||||
uint16 length; // The summation of all header lengths in the chain in bytes.
|
||||
};
|
||||
|
||||
class IP_Hdr {
|
||||
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)
|
||||
: 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)
|
||||
: ip4(0), ip6(arg_ip6), del(arg_del)
|
||||
IP_Hdr(const struct ip6_hdr* arg_ip6, bool 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()
|
||||
|
@ -190,7 +276,7 @@ public:
|
|||
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; }
|
||||
|
||||
uint16 HdrLen() const
|
||||
|
@ -207,25 +293,19 @@ public:
|
|||
unsigned char TTL() const
|
||||
{ return ip4 ? ip4->ip_ttl : ip6->ip6_hlim; }
|
||||
|
||||
//TODO: check for IPv6 Fragment ext. header
|
||||
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
|
||||
{ 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
|
||||
uint16 FragField() const
|
||||
{ return ip4 ? ntohs(ip4->ip_off) : 0; }
|
||||
uint32 ID() const
|
||||
{ return ip4 ? ntohs(ip4->ip_id) : ip6_hdrs->ID(); }
|
||||
|
||||
//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
|
||||
{ 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.
|
||||
int DF() const
|
||||
|
@ -240,7 +320,7 @@ private:
|
|||
const struct ip* ip4;
|
||||
const struct ip6_hdr* ip6;
|
||||
bool del;
|
||||
IPv6_Hdr_Chain* ip6_hdrs;
|
||||
const IPv6_Hdr_Chain* ip6_hdrs;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue