148 lines
4.8 KiB
C
148 lines
4.8 KiB
C
|
// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs)
|
||
|
//
|
||
|
// Copyright (c) 1998-2000 Microsoft Corporation
|
||
|
//
|
||
|
// This file is part of the Microsoft Research IPv6 Network Protocol Stack.
|
||
|
// You should have received a copy of the Microsoft End-User License Agreement
|
||
|
// for this software along with this release; see the file "license.txt".
|
||
|
// If not, please see http://www.research.microsoft.com/msripv6/license.htm,
|
||
|
// or write to Microsoft Research, One Microsoft Way, Redmond, WA 98052-6399.
|
||
|
//
|
||
|
// Abstract:
|
||
|
//
|
||
|
// IPv6 fragmentation/reassembly definitions.
|
||
|
//
|
||
|
|
||
|
|
||
|
#ifndef FRAGMENT_H_INCLUDED
|
||
|
#define FRAGMENT_H_INCLUDED 1
|
||
|
|
||
|
//
|
||
|
// Structure used to link fragments together.
|
||
|
//
|
||
|
// The fragment data follows the shim structure in memory.
|
||
|
//
|
||
|
typedef struct PacketShim {
|
||
|
struct PacketShim *Next; // Next packet on list.
|
||
|
ushort Len;
|
||
|
ushort Offset;
|
||
|
} PacketShim;
|
||
|
|
||
|
__inline uchar *
|
||
|
PacketShimData(PacketShim *shim)
|
||
|
{
|
||
|
return (uchar *)(shim + 1);
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Structure used to keep track of the fragments
|
||
|
// being reassembled into a single IPv6 datagram.
|
||
|
//
|
||
|
// REVIEW: Some of these fields are bigger than they need to be.
|
||
|
//
|
||
|
struct Reassembly {
|
||
|
struct Reassembly *Next, *Prev; // Protected by global reassembly lock.
|
||
|
KSPIN_LOCK Lock; // Protects reassembly fields below.
|
||
|
uint State; // See values below.
|
||
|
IPv6Header IPHdr; // Copy of original IP header.
|
||
|
Interface *IF; // Does not hold a reference.
|
||
|
ulong Id; // Unique (along w/ addrs) datagram identifier.
|
||
|
uchar *UnfragData; // Pointer to unfragmentable data.
|
||
|
ushort UnfragmentLength; // Length of the unfragmentable part.
|
||
|
ushort Timer; // Time to expiration in ticks (see IPv6Timeout).
|
||
|
uint DataLength; // Length of the fragmentable part.
|
||
|
PacketShim *ContigList; // Sorted, contiguous frags (from offset zero).
|
||
|
PacketShim *ContigEnd; // Last shim on ContigList (for quick access).
|
||
|
PacketShim *GapList; // Other fragments (sorted but non-contiguous).
|
||
|
uint Flags; // Packet flags.
|
||
|
uint Size; // Amount of memory consumed in this reassembly.
|
||
|
ushort Marker; // The current marker for contiguous data.
|
||
|
ushort MaxGap; // Largest data offset in the gap list.
|
||
|
ushort NextHeaderOffset; // Offset from IPHdr to pre-FH NextHeader field.
|
||
|
uchar NextHeader; // Header type following the fragment header.
|
||
|
};
|
||
|
|
||
|
//
|
||
|
// A reassembly starts in REASSEMBLY_STATE_NORMAL.
|
||
|
// If you want to remove it, then change the state
|
||
|
// to REASSEMBLY_STATE_DELETING. This prevents someone else
|
||
|
// from freeing it while you unlock the reassembly,
|
||
|
// get the global reassembly list lock, and relock the assembly.
|
||
|
// Someone else can remove the deleting reassembly
|
||
|
// from the global list, in which case the state becomes
|
||
|
// REASSEMBLY_STATE_REMOVED.
|
||
|
//
|
||
|
#define REASSEMBLY_STATE_NORMAL 0
|
||
|
#define REASSEMBLY_STATE_DELETING 1
|
||
|
#define REASSEMBLY_STATE_REMOVED 2
|
||
|
|
||
|
//
|
||
|
// There are denial-of-service issues with reassembly.
|
||
|
// We limit the total amount of memory in the reassembly list.
|
||
|
// If we get fragments that cause us to exceed the limit,
|
||
|
// we remove old reassemblies.
|
||
|
//
|
||
|
// The locking order is
|
||
|
// 1. Global reassembly list lock.
|
||
|
// 2. Individual reassembly record locks.
|
||
|
// 3. Reassembly list size lock.
|
||
|
//
|
||
|
|
||
|
extern struct ReassemblyList {
|
||
|
KSPIN_LOCK Lock; // Protects Reassembly List.
|
||
|
Reassembly *First; // List of packets being reassembled.
|
||
|
Reassembly *Last;
|
||
|
|
||
|
KSPIN_LOCK LockSize; // Protects the Size field.
|
||
|
uint Size; // Total size of the waiting fragments.
|
||
|
uint Limit; // Upper bound for Size.
|
||
|
} ReassemblyList;
|
||
|
|
||
|
#define SentinelReassembly ((Reassembly *)&ReassemblyList.First)
|
||
|
|
||
|
//
|
||
|
// Per-packet and per-fragment overhead sizes.
|
||
|
// These are in addition to the actual size of the buffered data.
|
||
|
// They should be at least as large as the Reassembly
|
||
|
// and PacketShim struct sizes.
|
||
|
//
|
||
|
#define REASSEMBLY_SIZE_PACKET 1024
|
||
|
#define REASSEMBLY_SIZE_FRAG 256
|
||
|
|
||
|
#define DEFAULT_REASSEMBLY_TIMEOUT IPv6TimerTicks(60) // 60 seconds.
|
||
|
|
||
|
|
||
|
extern Reassembly *
|
||
|
FragmentLookup(Interface *IF, ulong Id,
|
||
|
const IPv6Addr *Source, const IPv6Addr *Dest);
|
||
|
|
||
|
extern void
|
||
|
RemoveReassembly(Reassembly *Reass);
|
||
|
|
||
|
extern void
|
||
|
DeleteReassembly(Reassembly *Reass);
|
||
|
|
||
|
extern void
|
||
|
AddToReassemblyList(Reassembly *Reass);
|
||
|
|
||
|
extern void
|
||
|
DeleteFromReassemblyList(Reassembly *Reass);
|
||
|
|
||
|
extern void
|
||
|
IncreaseReassemblySize(Reassembly *Reass, uint Size);
|
||
|
|
||
|
extern void
|
||
|
CheckReassemblyQuota(Reassembly *Reass);
|
||
|
|
||
|
extern void
|
||
|
ReassemblyTimeout(void);
|
||
|
|
||
|
extern void
|
||
|
ReassembleDatagram(IPv6Packet *Packet, Reassembly *Reass);
|
||
|
|
||
|
extern IPv6Packet *
|
||
|
CreateFragmentPacket(Reassembly *Reass);
|
||
|
|
||
|
#endif // FRAGMENT_H_INCLUDED
|