mirror of
https://github.com/zeek/zeek.git
synced 2025-10-07 00:58:19 +00:00
Add handling for IPv6 extension header chains (addresses #531)
- The script-layer 'pkt_hdr' type is extended with a new 'ip6' field representing the full IPv6 header chain. - The 'new_packet' event is now raised for IPv6 packets (addresses #523) - A new event called 'ipv6_ext_header' is raised for any IPv6 packet containing extension headers. - A new event called 'esp_packet' is raised for any packets using ESP ('new_packet' and 'ipv6_ext_header' events provide connection info, but that info can't be provided here since the upper-layer payload is encrypted). - The 'unknown_protocol' weird is now raised more reliably when Bro sees a transport protocol or IPv6 extension header it can't handle. (addresses #522) Still need to do IPv6 fragment reassembly and needs more testing.
This commit is contained in:
parent
0639487aad
commit
eb9f686bb2
11 changed files with 724 additions and 110 deletions
196
src/IP.h
196
src/IP.h
|
@ -4,8 +4,139 @@
|
|||
#define ip_h
|
||||
|
||||
#include "config.h"
|
||||
#include "net_util.h"
|
||||
#include "IPAddr.h"
|
||||
#include <net_util.h>
|
||||
#include "Reporter.h"
|
||||
#include "Val.h"
|
||||
#include "Type.h"
|
||||
#include <vector>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip6.h>
|
||||
|
||||
/**
|
||||
* Base class for IPv6 header/extensions.
|
||||
*/
|
||||
class IPv6_Hdr {
|
||||
public:
|
||||
IPv6_Hdr() : type(0), data(0) {}
|
||||
|
||||
/**
|
||||
* Construct the main IPv6 header.
|
||||
*/
|
||||
IPv6_Hdr(const u_char* d) : type(IPPROTO_IPV6), data(d) {}
|
||||
|
||||
/**
|
||||
* Construct an IPv6 header or extension header from assigned type number.
|
||||
*/
|
||||
IPv6_Hdr(uint8 t, const u_char* d) : type(t), data(d) {}
|
||||
|
||||
virtual ~IPv6_Hdr() {}
|
||||
|
||||
/**
|
||||
* Returns the assigned IPv6 extension header type number of the header
|
||||
* that immediately follows this one.
|
||||
*/
|
||||
virtual uint8 NextHdr() const { return ((ip6_hdr*)data)->ip6_nxt; }
|
||||
|
||||
/**
|
||||
* Returns the length of the header in bytes.
|
||||
*/
|
||||
virtual uint16 Length() const { return 40; }
|
||||
|
||||
/**
|
||||
* Returns the RFC 1700 assigned number indicating the header type.
|
||||
*/
|
||||
uint8 Type() const { return type; }
|
||||
|
||||
/**
|
||||
* Returns the script-layer record representation of the header.
|
||||
*/
|
||||
virtual RecordVal* BuildRecordVal() const;
|
||||
|
||||
protected:
|
||||
uint8 type;
|
||||
const u_char* data;
|
||||
};
|
||||
|
||||
class IPv6_HopOpts : public IPv6_Hdr {
|
||||
public:
|
||||
IPv6_HopOpts(const u_char* d) : IPv6_Hdr(IPPROTO_HOPOPTS, d) {}
|
||||
uint8 NextHdr() const { return ((ip6_ext*)data)->ip6e_nxt; }
|
||||
uint16 Length() const { return 8 + 8 * ((ip6_ext*)data)->ip6e_len; }
|
||||
RecordVal* BuildRecordVal() const;
|
||||
};
|
||||
|
||||
class IPv6_DstOpts : public IPv6_Hdr {
|
||||
public:
|
||||
IPv6_DstOpts(const u_char* d) : IPv6_Hdr(IPPROTO_DSTOPTS, d) {}
|
||||
uint8 NextHdr() const { return ((ip6_ext*)data)->ip6e_nxt; }
|
||||
uint16 Length() const { return 8 + 8 * ((ip6_ext*)data)->ip6e_len; }
|
||||
RecordVal* BuildRecordVal() const;
|
||||
};
|
||||
|
||||
class IPv6_Routing : public IPv6_Hdr {
|
||||
public:
|
||||
IPv6_Routing(const u_char* d) : IPv6_Hdr(IPPROTO_ROUTING, d) {}
|
||||
uint8 NextHdr() const { return ((ip6_ext*)data)->ip6e_nxt; }
|
||||
uint16 Length() const { return 8 + 8 * ((ip6_ext*)data)->ip6e_len; }
|
||||
RecordVal* BuildRecordVal() const;
|
||||
};
|
||||
|
||||
class IPv6_Fragment : public IPv6_Hdr {
|
||||
public:
|
||||
IPv6_Fragment(const u_char* d) : IPv6_Hdr(IPPROTO_FRAGMENT, d) {}
|
||||
uint8 NextHdr() const { return ((ip6_ext*)data)->ip6e_nxt; }
|
||||
uint16 Length() const { return 8; }
|
||||
RecordVal* BuildRecordVal() const;
|
||||
};
|
||||
|
||||
class IPv6_AH : public IPv6_Hdr {
|
||||
public:
|
||||
IPv6_AH(const u_char* d) : IPv6_Hdr(IPPROTO_AH, d) {}
|
||||
uint8 NextHdr() const { return ((ip6_ext*)data)->ip6e_nxt; }
|
||||
uint16 Length() const { return 8 + 4 * ((ip6_ext*)data)->ip6e_len; }
|
||||
RecordVal* BuildRecordVal() const;
|
||||
};
|
||||
|
||||
class IPv6_ESP : public IPv6_Hdr {
|
||||
public:
|
||||
IPv6_ESP(const u_char* d) : IPv6_Hdr(IPPROTO_ESP, d) {}
|
||||
uint8 NextHdr() const { return ((ip6_ext*)data)->ip6e_nxt; }
|
||||
// encrypted payload begins after 8 bytes
|
||||
uint16 Length() const { return 8; }
|
||||
RecordVal* BuildRecordVal() const;
|
||||
};
|
||||
|
||||
class IPv6_Hdr_Chain {
|
||||
public:
|
||||
/**
|
||||
* Initializes the header chain from an IPv6 header structure.
|
||||
*/
|
||||
IPv6_Hdr_Chain(const struct ip6_hdr* ip6);
|
||||
|
||||
~IPv6_Hdr_Chain()
|
||||
{ for ( size_t i = 0; i < chain.size(); ++i ) delete chain[i]; }
|
||||
|
||||
/**
|
||||
* Returns the number of headers in the chain.
|
||||
*/
|
||||
size_t Size() const { return chain.size(); }
|
||||
|
||||
/**
|
||||
* Returns the sum of the length of all headers in the chain in bytes.
|
||||
*/
|
||||
uint16 TotalLength() const { return length; }
|
||||
|
||||
/**
|
||||
* Accesses the header at the given location in the chain.
|
||||
*/
|
||||
const IPv6_Hdr* operator[](const size_t i) const { return chain[i]; }
|
||||
|
||||
protected:
|
||||
vector<IPv6_Hdr*> chain;
|
||||
uint16 length; // The summation of all header lengths in the chain in bytes.
|
||||
};
|
||||
|
||||
class IP_Hdr {
|
||||
public:
|
||||
|
@ -17,10 +148,12 @@ public:
|
|||
IP_Hdr(const struct ip6_hdr* arg_ip6, bool arg_del)
|
||||
: ip4(0), ip6(arg_ip6), del(arg_del)
|
||||
{
|
||||
ip6_hdrs = new IPv6_Hdr_Chain(ip6);
|
||||
}
|
||||
|
||||
~IP_Hdr()
|
||||
{
|
||||
if ( ip6 ) delete ip6_hdrs;
|
||||
if ( del )
|
||||
{
|
||||
if ( ip4 )
|
||||
|
@ -30,23 +163,23 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
//TODO: audit usages of this for correct IPv6 support or IPv4 assumptions
|
||||
const struct ip* IP4_Hdr() const { return ip4; }
|
||||
|
||||
const struct ip6_hdr* IP6_Hdr() const { return ip6; }
|
||||
|
||||
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
|
||||
{
|
||||
if ( ip4 )
|
||||
return ((const u_char*) ip4) + ip4->ip_hl * 4;
|
||||
else
|
||||
return ((const u_char*) ip6) + 40;
|
||||
return ((const u_char*) ip6) + ip6_hdrs->TotalLength();
|
||||
}
|
||||
|
||||
uint16 PayloadLen() const
|
||||
|
@ -54,33 +187,60 @@ public:
|
|||
if ( ip4 )
|
||||
return ntohs(ip4->ip_len) - ip4->ip_hl * 4;
|
||||
else
|
||||
return ntohs(ip6->ip6_plen);
|
||||
return ntohs(ip6->ip6_plen) - ip6_hdrs->TotalLength();
|
||||
}
|
||||
|
||||
uint16 TotalLen() const
|
||||
{
|
||||
if ( ip4 )
|
||||
return ntohs(ip4->ip_len);
|
||||
else
|
||||
return ntohs(ip6->ip6_plen) + 40;
|
||||
}
|
||||
{ return ip4 ? ntohs(ip4->ip_len) : ntohs(ip6->ip6_plen) + 40; }
|
||||
|
||||
uint16 HdrLen() const
|
||||
{ return ip4 ? ip4->ip_hl * 4 : ip6_hdrs->TotalLength(); }
|
||||
|
||||
uint8 LastHeader() const
|
||||
{ return ip4 ? IPPROTO_RAW :
|
||||
((*ip6_hdrs)[ip6_hdrs->Size()-1])->Type(); }
|
||||
|
||||
uint16 HdrLen() const { return ip4 ? ip4->ip_hl * 4 : 40; }
|
||||
unsigned char NextProto() const
|
||||
{ return ip4 ? ip4->ip_p : ip6->ip6_nxt; }
|
||||
{ return ip4 ? ip4->ip_p :
|
||||
((*ip6_hdrs)[ip6_hdrs->Size()-1])->NextHdr(); }
|
||||
|
||||
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; }
|
||||
|
||||
//TODO: check for IPv6 Fragment ext. header
|
||||
uint16 FragOffset() const
|
||||
{ return ip4 ? (ntohs(ip4->ip_off) & 0x1fff) * 8 : 0; }
|
||||
|
||||
//TODO: check for IPv6 Fragment ext. header
|
||||
uint16 FragField() const
|
||||
{ return ntohs(ip4 ? ip4->ip_off : 0); }
|
||||
{ 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
|
||||
{ return ip4 ? (ntohs(ip4->ip_off) & 0x2000) != 0 : 0; }
|
||||
|
||||
// IPv6 has no "Don't Fragment" flag.
|
||||
int DF() const
|
||||
{ return ip4 ? ((ntohs(ip4->ip_off) & IP_DF) != 0) : 0; }
|
||||
uint16 IP_ID() const
|
||||
{ return ip4 ? (ntohs(ip4->ip_id)) : 0; }
|
||||
{ return ip4 ? ((ntohs(ip4->ip_off) & 0x4000) != 0) : 0; }
|
||||
|
||||
size_t NumHeaders() const
|
||||
{ return ip4 ? 1 : ip6_hdrs->Size(); }
|
||||
|
||||
RecordVal* BuildRecordVal() const;
|
||||
|
||||
private:
|
||||
const struct ip* ip4;
|
||||
const struct ip6_hdr* ip6;
|
||||
bool del;
|
||||
IPv6_Hdr_Chain* ip6_hdrs;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue