mirror of
https://github.com/zeek/zeek.git
synced 2025-10-09 10: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
57
src/Frag.cc
57
src/Frag.cc
|
@ -33,13 +33,23 @@ FragReassembler::FragReassembler(NetSessions* arg_s,
|
|||
s = arg_s;
|
||||
key = k;
|
||||
const struct ip* ip4 = ip->IP4_Hdr();
|
||||
proto_hdr_len = ip4->ip_hl * 4;
|
||||
proto_hdr = (struct ip*) 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);
|
||||
if ( ip4 )
|
||||
{
|
||||
proto_hdr_len = ip4->ip_hl * 4;
|
||||
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;
|
||||
frag_size = 0; // flag meaning "not known"
|
||||
next_proto = ip->NextProto();
|
||||
|
||||
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();
|
||||
|
||||
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
|
||||
// don't check TOS, there's at least one stack that actually
|
||||
// uses different values, and it's hard to see an associated
|
||||
// attack.
|
||||
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() )
|
||||
// Linux MTU discovery for UDP can do this, for example.
|
||||
s->Weird("fragment_with_DF", ip);
|
||||
|
||||
int offset = ip->FragOffset();
|
||||
int len = ntohs(ip4->ip_len);
|
||||
int hdr_len = proto_hdr->ip_hl * 4;
|
||||
int len = ip->TotalLen();
|
||||
int hdr_len = ip->HdrLen();
|
||||
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() )
|
||||
{
|
||||
// Last fragment.
|
||||
|
@ -192,8 +217,7 @@ void FragReassembler::BlockInserted(DataBlock* /* start_block */)
|
|||
u_char* pkt = new u_char[n];
|
||||
memcpy((void*) pkt, (const void*) proto_hdr, proto_hdr_len);
|
||||
|
||||
struct ip* reassem4 = (struct ip*) pkt;
|
||||
reassem4->ip_len = htons(frag_size + proto_hdr_len);
|
||||
u_char* pkt_start = pkt;
|
||||
|
||||
pkt += proto_hdr_len;
|
||||
|
||||
|
@ -213,7 +237,20 @@ void FragReassembler::BlockInserted(DataBlock* /* start_block */)
|
|||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue