You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
881 lines
19 KiB
881 lines
19 KiB
/*++
|
|
|
|
Copyright (c) 2001-2002 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
teredo.h
|
|
|
|
Abstract:
|
|
|
|
This module contains the teredo client and server (cum relay) state.
|
|
|
|
Author:
|
|
|
|
Mohit Talwar (mohitt) Mon Oct 22 15:17:48 2001
|
|
|
|
Environment:
|
|
|
|
User mode only.
|
|
|
|
--*/
|
|
|
|
#ifndef _TEREDO_
|
|
#define _TEREDO_
|
|
|
|
#pragma once
|
|
|
|
|
|
#include <tunuser.h>
|
|
#define DEVICE_PREFIX L"\\Device\\"
|
|
|
|
|
|
//
|
|
// IP6_HDR
|
|
//
|
|
// Define the RFC 2292 structure for an IPv6 header.
|
|
//
|
|
|
|
typedef struct _IP6_HDR {
|
|
union {
|
|
struct ip6_hdrctl {
|
|
UINT32 ip6_un1_flow; // 20 bits of flow-ID
|
|
UINT16 ip6_un1_plen; // payload length
|
|
UINT8 ip6_un1_nxt; // next header
|
|
UINT8 ip6_un1_hlim; // hop limit
|
|
} ip6_un1;
|
|
UINT8 ip6_un2_vfc; // 4 bits version, 4 bits priority
|
|
} ip6_ctlun;
|
|
IN6_ADDR ip6_src; // source address
|
|
IN6_ADDR ip6_dest; // destination address
|
|
#define ip6_vfc ip6_ctlun.ip6_un2_vfc
|
|
#define ip6_flow ip6_ctlun.ip6_un1.ip6_un1_flow
|
|
#define ip6_plen ip6_ctlun.ip6_un1.ip6_un1_plen
|
|
#define ip6_nxt ip6_ctlun.ip6_un1.ip6_un1_nxt
|
|
#define ip6_hlim ip6_ctlun.ip6_un1.ip6_un1_hlim
|
|
#define ip6_hops ip6_ctlun.ip6_un1.ip6_un1_hlim
|
|
} IP6_HDR, *PIP6_HDR;
|
|
|
|
#define IPV6_VERSION 0x60 // This is 6 << 4
|
|
#define IPV6_TEREDOMTU 1280
|
|
#define IPV6_INFINITE_LIFETIME 0xffffffff
|
|
#define IPPROTO_NONE 59
|
|
|
|
|
|
//
|
|
// HASHTABLE
|
|
//
|
|
// Define a simple, statically sized, locked hash table.
|
|
// Each bucket is a doubly linked LRU list.
|
|
//
|
|
|
|
#define BUCKET_COUNT 29 // # buckets in the hash table
|
|
typedef struct _HASHTABLE {
|
|
CRITICAL_SECTION Lock; // Protects the table and entries.
|
|
ULONG Size; // # entries in the hash table
|
|
LIST_ENTRY Bucket[BUCKET_COUNT];
|
|
} HASHTABLE, *PHASHTABLE;
|
|
|
|
|
|
//
|
|
// TEREDO_TYPE
|
|
//
|
|
// Define the type of the teredo service.
|
|
//
|
|
|
|
typedef enum {
|
|
TEREDO_DEFAULT = 0,
|
|
TEREDO_CLIENT,
|
|
TEREDO_SERVER,
|
|
TEREDO_DISABLED,
|
|
TEREDO_AUTOMATIC,
|
|
TEREDO_MAXIMUM,
|
|
} TEREDO_TYPE, *PTEREDO_TYPE;
|
|
|
|
|
|
//
|
|
// TEREDO_PACKET_TYPE
|
|
//
|
|
// Define the type of a teredo packet.
|
|
//
|
|
|
|
typedef enum {
|
|
TEREDO_PACKET_READ, // Data read from TUN device.
|
|
TEREDO_PACKET_WRITE, // Data written to TUN device.
|
|
TEREDO_PACKET_BUBBLE, // Bubble transmitted on UDP socket.
|
|
TEREDO_PACKET_BOUNCE, // Packet bounced on UDP socket.
|
|
TEREDO_PACKET_RECEIVE, // Packet received on UDP socket.
|
|
TEREDO_PACKET_TRANSMIT, // Packet transmitted on UDP socket.
|
|
TEREDO_PACKET_MULTICAST, // Multicast bubble transmitted on UDP socket.
|
|
TEREDO_PACKET_MAX,
|
|
} TEREDO_PACKET_TYPE, *PTEREDO_PACKET_TYPE;
|
|
|
|
|
|
//
|
|
// TEREDO_PACKET
|
|
//
|
|
// Define a teredo packet.
|
|
// The packet structure is followed in memory by the packet's data buffer.
|
|
//
|
|
|
|
typedef struct _TEREDO_PACKET {
|
|
#if DBG
|
|
ULONG Signature; // TEREDO_PACKET_SIGNATURE
|
|
#endif // DBG
|
|
|
|
OVERLAPPED Overlapped; // For asynchronous completion.
|
|
TEREDO_PACKET_TYPE Type; // Packet type.
|
|
SOCKADDR_IN SocketAddress; // Peer we are in communication with.
|
|
UINT SocketAddressLength; // Length of the peer's socket address.
|
|
WSABUF Buffer; // Packet buffer and length.
|
|
DWORD Flags; // Flags required during sends and receives.
|
|
} TEREDO_PACKET, *PTEREDO_PACKET;
|
|
|
|
#define TEREDO_PACKET_BUFFER(Packet) \
|
|
((PUCHAR) (((PTEREDO_PACKET) (Packet)) + 1))
|
|
|
|
|
|
typedef
|
|
VOID
|
|
(TEREDO_REFERENCE)(
|
|
VOID
|
|
);
|
|
typedef TEREDO_REFERENCE *PTEREDO_REFERENCE;
|
|
|
|
typedef
|
|
VOID
|
|
(TEREDO_DEREFERENCE)(
|
|
VOID
|
|
);
|
|
typedef TEREDO_DEREFERENCE *PTEREDO_DEREFERENCE;
|
|
|
|
typedef
|
|
VOID
|
|
(TEREDO_PACKET_IO_COMPLETE)(
|
|
IN DWORD Error,
|
|
IN ULONG Bytes,
|
|
IN PTEREDO_PACKET Packet
|
|
);
|
|
typedef TEREDO_PACKET_IO_COMPLETE *PTEREDO_PACKET_IO_COMPLETE;
|
|
|
|
|
|
//
|
|
// TEREDO_STATE_TYPE
|
|
//
|
|
// Define the protocol state values of the teredo client service.
|
|
//
|
|
|
|
typedef enum {
|
|
TEREDO_STATE_OFFLINE,
|
|
TEREDO_STATE_PROBE,
|
|
TEREDO_STATE_QUALIFIED,
|
|
TEREDO_STATE_ONLINE,
|
|
} TEREDO_STATE_TYPE, *PTEREDO_STATE_TYPE;
|
|
|
|
|
|
//
|
|
// TEREDO_IO
|
|
//
|
|
// Define teredo I/O state.
|
|
// NOTE: All addresses and ports are stored in network byte order.
|
|
//
|
|
|
|
typedef struct _TEREDO_IO {
|
|
#if DBG
|
|
ULONG Signature; // TEREDO_PACKET_SIGNATURE
|
|
#endif // DBG
|
|
|
|
HANDLE PacketHeap; // Head for allocating teredo packets.
|
|
|
|
ULONG PostedReceives; // Count of posted receives.
|
|
HANDLE ReceiveEvent; // Event signalled upon a receive notification.
|
|
HANDLE ReceiveEventWait; // Wait registered for ReceiveEvent.
|
|
|
|
IN_ADDR Group; // Group joined on the native interface.
|
|
SOCKADDR_IN ServerAddress; // Teredo server IPv4 address and UDP port.
|
|
SOCKADDR_IN SourceAddress; // Preferred source address to teredo server.
|
|
SOCKET Socket; // Socket bound to SourceAddress on a UDP port.
|
|
HANDLE TunnelDevice; // Interface to the TUNNEL driver.
|
|
WCHAR TunnelInterface[MAX_ADAPTER_NAME_LENGTH];
|
|
|
|
//
|
|
// Function handlers.
|
|
//
|
|
PTEREDO_REFERENCE Reference;
|
|
PTEREDO_DEREFERENCE Dereference;
|
|
LPOVERLAPPED_COMPLETION_ROUTINE IoCompletionCallback;
|
|
} TEREDO_IO, *PTEREDO_IO;
|
|
|
|
|
|
//
|
|
// TEREDO_CLIENT_STATE
|
|
//
|
|
// Define the global state of the teredo client service.
|
|
//
|
|
// References:
|
|
// - One for initialization.
|
|
// - One for any running timer.
|
|
// - One for each teredo peer.
|
|
// - One for each teredo packet
|
|
// - One for "the" multicast bubble. At most one outstanding bubble allowed.
|
|
// (reads, writes posted on TunDevice & receives, transmits posted on Socket).
|
|
//
|
|
|
|
typedef struct _TEREDO_CLIENT_STATE {
|
|
ULONG ReferenceCount; // Number of outstanding references.
|
|
|
|
TEREDO_IO Io; // I/O state. TUN device and UDP socket.
|
|
|
|
HANDLE PeerHeap; // Heap for allocating teredo peers.
|
|
|
|
HANDLE Timer; // One shot timer active in Probe & Qualified.
|
|
HANDLE TimerEvent; // Event signalled upon timer deletion.
|
|
HANDLE TimerEventWait; // Wait registered for TimerEvent.
|
|
BOOL RestartQualifiedTimer; // When NAT mapping is created or refreshed.
|
|
|
|
LONG Time; // Current time (in seconds).
|
|
TEREDO_STATE_TYPE State; // Teredo client service protocol state.
|
|
IN6_ADDR Ipv6Prefix; // Teredo IPv6 prefix advertised by server.
|
|
ULONG RefreshInterval; // Expected lifetime of client's NAT mapping.
|
|
HASHTABLE PeerSet; // Locked set of recent teredo peers.
|
|
|
|
ULONG BubbleTicks; // "RefreshInterval" ticks until next bubble.
|
|
BOOL BubblePosted; // Whether there is any outstanding bubble.
|
|
TEREDO_PACKET Packet; // Teredo multicast bubble packet.
|
|
IP6_HDR Bubble; // Teredo multicast bubble packet buffer.
|
|
} TEREDO_CLIENT_STATE, *PTEREDO_CLIENT_STATE;
|
|
|
|
|
|
//
|
|
// TEREDO_SERVER_STATE
|
|
//
|
|
// Define the global state of the teredo server service.
|
|
//
|
|
// References:
|
|
// - One for initialization.
|
|
// - One for each teredo packet
|
|
// (reads, writes posted on TunDevice & receives, transmits posted on Socket).
|
|
//
|
|
|
|
typedef struct _TEREDO_SERVER_STATE {
|
|
ULONG ReferenceCount; // Number of outstanding references.
|
|
|
|
TEREDO_IO Io; // I/O state. TUN device and UDP socket.
|
|
|
|
TEREDO_STATE_TYPE State; // Teredo server service protocol state.
|
|
} TEREDO_SERVER_STATE, *PTEREDO_SERVER_STATE;
|
|
|
|
|
|
//
|
|
// TEREDO_PEER
|
|
//
|
|
// Define a teredo peer's state.
|
|
//
|
|
// References:
|
|
// - One for initialization.
|
|
// - One for "the" posted bubble. At most one outstanding bubble is allowed.
|
|
//
|
|
// Synchronization:
|
|
// - Link: Protected by PeerSet::Lock.
|
|
// - ReferenceCount: InterlockedIncrement, InterlockedDecrement.
|
|
// - LastReceive, LastTransmit: Atomic reads and writes.
|
|
// - BubbleCount: Single writer! Atomic reads.
|
|
// - BubblePosted: InterlockedExchange.
|
|
// - Remaining Fields: Read only.
|
|
//
|
|
|
|
typedef struct _TEREDO_PEER {
|
|
#if DBG
|
|
ULONG Signature; // TEREDO_PEER_SIGNATURE
|
|
#endif // DBG
|
|
|
|
LIST_ENTRY Link; // Linkage within the PeerSet.
|
|
|
|
ULONG ReferenceCount; // Number of outstanding references.
|
|
|
|
LONG LastReceive; // Time of last reception from the peer.
|
|
LONG LastTransmit; // Time of last transmission to the peer.
|
|
IN6_ADDR Address; // Teredo IPv6 address of the peer.
|
|
ULONG BubbleCount; // Number of bubbles transmitted to the peer.
|
|
|
|
BOOL BubblePosted; // Whether there is any outstanding bubble.
|
|
TEREDO_PACKET Packet; // Teredo bubble packet.
|
|
IP6_HDR Bubble; // Teredo bubble packet buffer.
|
|
} TEREDO_PEER, *PTEREDO_PEER;
|
|
|
|
|
|
//
|
|
// Cast and Signature Verification
|
|
//
|
|
|
|
#define TEREDO_IO_SIGNATURE 'oIhS' // 'ShIo'
|
|
#define TEREDO_PEER_SIGNATURE 'ePhS' // 'ShPe'
|
|
#define TEREDO_PACKET_SIGNATURE 'aPhS' // 'ShPa'
|
|
|
|
//
|
|
// A NULL handle is considered a valid structure.
|
|
//
|
|
|
|
#define Cast(Pointer, TYPE) \
|
|
((TYPE *) (Pointer)); \
|
|
ASSERT(!(Pointer) || \
|
|
(((TYPE *) (Pointer))->Signature == TYPE##_SIGNATURE))
|
|
|
|
|
|
//
|
|
// Lower and upper limits on number of posted reads or receives.
|
|
//
|
|
#define TEREDO_LOW_WATER_MARK 5 // Receives or Reads.
|
|
#define TEREDO_HIGH_WATER_MARK 256 // Receives. Reads are fixed.
|
|
|
|
//
|
|
// Intervals used by the protocol.
|
|
//
|
|
#define INFINITE_INTERVAL 0x7fffffff
|
|
#define TEREDO_RESOLVE_INTERVAL 15 * MINUTES
|
|
#define TEREDO_PROBE_INTERVAL 15 * SECONDS
|
|
#define TEREDO_REFRESH_INTERVAL 30 * SECONDS
|
|
#define TEREDO_MULTICAST_BUBBLE_TICKS 0 // In RefreshInterval units.
|
|
#define TEREDO_BUBBLE_INTERVAL 10 * SECONDS
|
|
#define TEREDO_SLOW_BUBBLE_INTERVAL 5 * MINUTES
|
|
#define TEREDO_BUBBLE_THRESHHOLD 2 * MINUTES
|
|
#define TEREDO_ROUTER_LIFETIME 5 * HOURS
|
|
|
|
|
|
//
|
|
// Teredo multicast bubbles are sent to group 224.0.0.252 on port 337.
|
|
//
|
|
#define TEREDO_MULTICAST_PREFIX \
|
|
{ 0x20, 0x03, 0xe0, 0x00, 0x00, 0xfc, 0x01, 0x51, }
|
|
|
|
#define TEREDO_DEFAULT_TYPE TEREDO_DISABLED
|
|
|
|
#define TEREDO_PORT htons(337)
|
|
#define TEREDO_SERVER_NAME L"teredo.ipv6.microsoft.com"
|
|
#define TEREDO_SERVICE_PREFIX { 0x20, 0x03, }
|
|
|
|
#define KEY_TEREDO_REFRESH_INTERVAL L"RefreshInterval"
|
|
#define KEY_TEREDO_TYPE L"Type"
|
|
#define KEY_TEREDO_SERVER_NAME L"ServerName"
|
|
#define KEY_TEREDO L"System\\CurrentControlSet\\Services\\Teredo"
|
|
|
|
|
|
//
|
|
// Configured parameters.
|
|
//
|
|
extern ULONG TeredoClientRefreshInterval;
|
|
extern TEREDO_TYPE TeredoType;
|
|
extern WCHAR TeredoServerName[NI_MAXHOST];
|
|
|
|
extern CONST IN6_ADDR TeredoIpv6ServicePrefix;
|
|
extern CONST IN6_ADDR TeredoIpv6MulticastPrefix;
|
|
extern TEREDO_CLIENT_STATE TeredoClient;
|
|
extern TEREDO_SERVER_STATE TeredoServer;
|
|
|
|
|
|
//
|
|
// Time.
|
|
//
|
|
|
|
__inline
|
|
LONG
|
|
TeredoGetTime(
|
|
VOID
|
|
)
|
|
{
|
|
//
|
|
// FILETIME is a 64 bit value representing the number of 100 nanoseconds.
|
|
//
|
|
C_ASSERT(sizeof(FILETIME) == sizeof(ULONGLONG));
|
|
ULONGLONG Time;
|
|
|
|
GetSystemTimeAsFileTime((PFILETIME) &Time);
|
|
return ((ULONG) (Time / (10 * 1000 * 1000)));
|
|
}
|
|
|
|
#define TIME_GREATER(a, b) (((a) - (b)) > 0)
|
|
|
|
|
|
//
|
|
// Address validation and parsing.
|
|
//
|
|
|
|
__inline
|
|
BOOL
|
|
IN4_MULTICAST(IN_ADDR a)
|
|
{
|
|
return ((a.s_addr & 0x0000000f) == 0x0000000e);
|
|
}
|
|
|
|
_inline
|
|
BOOL
|
|
IN4_ADDR_EQUAL(IN_ADDR a, IN_ADDR b)
|
|
{
|
|
return (a.s_addr == b.s_addr);
|
|
}
|
|
|
|
_inline
|
|
BOOL
|
|
IN4_SOCKADDR_EQUAL(CONST SOCKADDR_IN *a, CONST SOCKADDR_IN *b)
|
|
{
|
|
ASSERT((a->sin_family == AF_INET) && (b->sin_family == AF_INET));
|
|
return (IN4_ADDR_EQUAL(a->sin_addr, b->sin_addr) &&
|
|
(a->sin_port == b->sin_port));
|
|
}
|
|
|
|
__inline
|
|
BOOL
|
|
TeredoIpv6GlobalAddress(
|
|
IN CONST IN6_ADDR *Address
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Determine whether the supplied IPv6 address is of global unicast scope.
|
|
|
|
--*/
|
|
{
|
|
//
|
|
// This can be coded quite a bit more efficiently!
|
|
//
|
|
if (IN6_IS_ADDR_UNSPECIFIED(Address) ||
|
|
IN6_IS_ADDR_LOOPBACK(Address) ||
|
|
IN6_IS_ADDR_MULTICAST(Address) ||
|
|
IN6_IS_ADDR_LINKLOCAL(Address) ||
|
|
IN6_IS_ADDR_SITELOCAL(Address)) {
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
__inline
|
|
BOOL
|
|
TeredoIpv4GlobalAddress(
|
|
IN CONST UCHAR *Address
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Determine whether the supplied IPv4 address is of global unicast scope.
|
|
|
|
--*/
|
|
{
|
|
if ((Address[0] > 223) || // ~Unicast
|
|
(Address[0] == 0) || // 0/8
|
|
(Address[0] == 127) || // 127/8
|
|
(Address[0] == 10) || // 10/8
|
|
((Address[0] == 169) && (Address[1] == 254)) || // 169.254/16
|
|
((Address[0] == 172) && ((Address[1] & 0xf0) == 16)) || // 172.16/12
|
|
((Address[0] == 192) && (Address[1] == 168))) { // 192.168/16
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
__inline
|
|
BOOL
|
|
TeredoServicePrefix(
|
|
IN CONST IN6_ADDR *Address
|
|
)
|
|
{
|
|
return (Address->s6_words[0] == TeredoIpv6ServicePrefix.s6_words[0]);
|
|
}
|
|
|
|
__inline
|
|
BOOL
|
|
TeredoValidAdvertisedPrefix(
|
|
IN CONST IN6_ADDR *Address,
|
|
IN UCHAR Length
|
|
)
|
|
{
|
|
if (Length != 64) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (!TeredoServicePrefix(Address)) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (!TeredoIpv4GlobalAddress((PUCHAR) (Address->s6_words + 1))) {
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
__inline
|
|
VOID
|
|
TeredoParseAddress(
|
|
IN CONST IN6_ADDR *Address,
|
|
OUT PIN_ADDR Ipv4Address,
|
|
OUT PUSHORT Ipv4Port
|
|
)
|
|
{
|
|
ASSERT(TeredoServicePrefix(Address));
|
|
|
|
//
|
|
// These are returned in network byte order.
|
|
//
|
|
((PUSHORT) Ipv4Address)[0] = Address->s6_words[1];
|
|
((PUSHORT) Ipv4Address)[1] = Address->s6_words[2];
|
|
*Ipv4Port = Address->s6_words[3];
|
|
}
|
|
|
|
__inline
|
|
BOOL
|
|
TeredoEqualPrefix(
|
|
IN CONST IN6_ADDR *Address1,
|
|
IN CONST IN6_ADDR *Address2
|
|
)
|
|
{
|
|
//
|
|
// Compare Teredo IPv6 Service Prefix, Mapped IPv4 Address and Port.
|
|
//
|
|
return ((Address1->s6_words[0] == Address2->s6_words[0]) &&
|
|
(Address1->s6_words[1] == Address2->s6_words[1]) &&
|
|
(Address1->s6_words[2] == Address2->s6_words[2]) &&
|
|
(Address1->s6_words[3] == Address2->s6_words[3]));
|
|
}
|
|
|
|
|
|
//
|
|
// Client API
|
|
//
|
|
|
|
DWORD
|
|
TeredoInitializeClient(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
TeredoUninitializeClient(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
TeredoCleanupClient(
|
|
VOID
|
|
);
|
|
|
|
__inline
|
|
VOID
|
|
TeredoReferenceClient(
|
|
VOID
|
|
)
|
|
{
|
|
ASSERT(TeredoClient.ReferenceCount > 0);
|
|
InterlockedIncrement(&(TeredoClient.ReferenceCount));
|
|
}
|
|
|
|
__inline
|
|
VOID
|
|
TeredoDereferenceClient(
|
|
VOID
|
|
)
|
|
{
|
|
ASSERT(TeredoClient.ReferenceCount > 0);
|
|
if (InterlockedDecrement(&(TeredoClient.ReferenceCount)) == 0) {
|
|
TeredoCleanupClient();
|
|
}
|
|
}
|
|
|
|
VOID
|
|
TeredoStartClient(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
TeredoStopClient(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
TeredoProbeClient(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
TeredoQualifyClient(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
TeredoClientAddressDeletionNotification(
|
|
IN IN_ADDR Address
|
|
);
|
|
|
|
VOID
|
|
TeredoClientRefreshIntervalChangeNotification(
|
|
VOID
|
|
);
|
|
|
|
__inline
|
|
VOID
|
|
TeredoRefreshClient(
|
|
VOID
|
|
)
|
|
{
|
|
ASSERT(TeredoClient.State != TEREDO_STATE_OFFLINE);
|
|
TeredoClientAddressDeletionNotification(
|
|
TeredoClient.Io.SourceAddress.sin_addr);
|
|
}
|
|
|
|
|
|
//
|
|
// Server API
|
|
//
|
|
|
|
DWORD
|
|
TeredoInitializeServer(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
TeredoUninitializeServer(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
TeredoCleanupServer(
|
|
VOID
|
|
);
|
|
|
|
__inline
|
|
VOID
|
|
TeredoReferenceServer(
|
|
VOID
|
|
)
|
|
{
|
|
ASSERT(TeredoServer.ReferenceCount > 0);
|
|
InterlockedIncrement(&(TeredoServer.ReferenceCount));
|
|
}
|
|
|
|
__inline
|
|
VOID
|
|
TeredoDereferenceServer(
|
|
VOID
|
|
)
|
|
{
|
|
ASSERT(TeredoServer.ReferenceCount > 0);
|
|
if (InterlockedDecrement(&(TeredoServer.ReferenceCount)) == 0) {
|
|
TeredoCleanupServer();
|
|
}
|
|
}
|
|
|
|
VOID
|
|
TeredoStartServer(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
TeredoStopServer(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
TeredoServerAddressDeletionNotification(
|
|
IN IN_ADDR Address
|
|
);
|
|
|
|
__inline
|
|
VOID
|
|
TeredoRefreshServer(
|
|
VOID
|
|
)
|
|
{
|
|
ASSERT(TeredoServer.State != TEREDO_STATE_OFFLINE);
|
|
TeredoServerAddressDeletionNotification(
|
|
TeredoServer.Io.SourceAddress.sin_addr);
|
|
}
|
|
|
|
|
|
//
|
|
// Common API
|
|
//
|
|
|
|
BOOL
|
|
TeredoInterface(
|
|
IN PWCHAR Guid
|
|
);
|
|
|
|
DWORD
|
|
TeredoInitializeGlobals(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
TeredoUninitializeGlobals(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
TeredoAddressChangeNotification(
|
|
IN BOOL Delete,
|
|
IN IN_ADDR Address
|
|
);
|
|
|
|
VOID
|
|
TeredoRouteChangeNotification(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
TeredoConfigurationChangeNotification(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
WINAPI
|
|
TeredoWmiEventNotification(
|
|
IN PWNODE_HEADER Event,
|
|
IN UINT_PTR Context
|
|
);
|
|
|
|
VOID
|
|
TeredoRequirementChangeNotification(
|
|
IN BOOL Required
|
|
);
|
|
|
|
|
|
//
|
|
// Peer API.
|
|
//
|
|
|
|
DWORD
|
|
TeredoInitializePeerSet(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
TeredoUninitializePeerSet(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
TeredoCleanupPeerSet(
|
|
VOID
|
|
);
|
|
|
|
PTEREDO_PEER
|
|
TeredoFindOrCreatePeer(
|
|
IN CONST IN6_ADDR *Address
|
|
);
|
|
|
|
VOID
|
|
TeredoDestroyPeer(
|
|
IN PTEREDO_PEER Peer
|
|
);
|
|
|
|
__inline
|
|
VOID
|
|
TeredoReferencePeer(
|
|
IN PTEREDO_PEER Peer
|
|
)
|
|
{
|
|
|
|
ASSERT(Peer->ReferenceCount > 0);
|
|
InterlockedIncrement(&(Peer->ReferenceCount));
|
|
}
|
|
|
|
__inline
|
|
VOID
|
|
TeredoDereferencePeer(
|
|
IN PTEREDO_PEER Peer
|
|
)
|
|
{
|
|
ASSERT(Peer->ReferenceCount > 0);
|
|
if (InterlockedDecrement(&(Peer->ReferenceCount)) == 0) {
|
|
TeredoDestroyPeer(Peer);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// I/O API.
|
|
//
|
|
|
|
DWORD
|
|
TeredoInitializeIo(
|
|
IN PTEREDO_IO TeredoIo,
|
|
IN IN_ADDR Group,
|
|
IN PTEREDO_REFERENCE Reference,
|
|
IN PTEREDO_DEREFERENCE Dereference,
|
|
IN LPOVERLAPPED_COMPLETION_ROUTINE IoCompletionCallback
|
|
);
|
|
|
|
VOID
|
|
TeredoCleanupIo(
|
|
IN PTEREDO_IO TeredoIo
|
|
);
|
|
|
|
DWORD
|
|
TeredoStartIo(
|
|
IN PTEREDO_IO TeredoIo
|
|
);
|
|
|
|
DWORD
|
|
TeredoRefreshSocket(
|
|
IN PTEREDO_IO TeredoIo
|
|
);
|
|
|
|
VOID
|
|
TeredoStopIo(
|
|
IN PTEREDO_IO TeredoIo
|
|
);
|
|
|
|
__inline
|
|
VOID
|
|
TeredoInitializePacket(
|
|
IN PTEREDO_PACKET Packet
|
|
)
|
|
{
|
|
#if DBG
|
|
Packet->Signature = TEREDO_PACKET_SIGNATURE;
|
|
#endif // DBG
|
|
ZeroMemory(&(Packet->SocketAddress), sizeof(SOCKADDR_IN));
|
|
Packet->SocketAddress.sin_family = AF_INET;
|
|
Packet->SocketAddressLength = sizeof(SOCKADDR_IN);
|
|
Packet->Flags = 0;
|
|
Packet->Buffer.buf = TEREDO_PACKET_BUFFER(Packet);
|
|
}
|
|
|
|
ULONG
|
|
TeredoPostReceives(
|
|
IN PTEREDO_IO TeredoIo,
|
|
IN PTEREDO_PACKET Packet
|
|
);
|
|
|
|
PTEREDO_PACKET
|
|
TeredoTransmitPacket(
|
|
IN PTEREDO_IO TeredoIo,
|
|
IN PTEREDO_PACKET Packet
|
|
);
|
|
|
|
BOOL
|
|
TeredoPostRead(
|
|
IN PTEREDO_IO TeredoIo,
|
|
IN PTEREDO_PACKET Packet OPTIONAL
|
|
);
|
|
|
|
PTEREDO_PACKET
|
|
TeredoWritePacket(
|
|
IN PTEREDO_IO TeredoIo,
|
|
IN PTEREDO_PACKET Packet
|
|
);
|
|
|
|
|
|
//
|
|
// Utility Functions.
|
|
//
|
|
|
|
ICMPv6Header *
|
|
TeredoParseIpv6Headers(
|
|
IN PUCHAR Buffer,
|
|
IN ULONG Bytes
|
|
);
|
|
|
|
#endif // _TEREDO_
|