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.
294 lines
18 KiB
294 lines
18 KiB
/*++
|
|
|
|
Copyright (c) 2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
ntddnlb.h
|
|
|
|
Abstract:
|
|
|
|
This header describes the structures and interfaces required to interact
|
|
with the NLB intermediate device driver.
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#ifndef __NTDDNLB_H__
|
|
#define __NTDDNLB_H__
|
|
|
|
#include <ndis.h>
|
|
#include <ntddndis.h>
|
|
#include <devioctl.h>
|
|
|
|
/* This is the public callback object on which NLB will listen for connection
|
|
callbacks. Currently, only TCP (protocol=6) notifications are accepted by
|
|
NLB. To notify NLB when connections change state, open the callback object,
|
|
and call ExNotifyCallback with the following parameters:
|
|
|
|
CallbackObject - The handle to the NLB public callback object.
|
|
Argument1 - A pointer to an NLBConnectionInfo block, defined below.
|
|
Argument2 - NULL (This parameter is currently unused).
|
|
|
|
For TCP connections, NLB needs to be notified of the following state changes:
|
|
|
|
CLOSED -> SYN_RCVD: A new incoming connection is being established. This
|
|
notification requires the IP interface index on which the SYN was received.
|
|
NLB will create state on the appropriate interface to track this TCP connection.
|
|
|
|
CLOSED -> SYN_SENT: A new outgoing connection is being established. At this
|
|
time, it is unknown on which interface the connection will ultimately be
|
|
established, so the IP interface index is NOT required for this notification.
|
|
NLB will create temporary state to track this connection should it return
|
|
on an NLB interface.
|
|
|
|
SYN_SENT -> ESTAB: An outgoing connection has been established. This nofication
|
|
requires the IP interface index on which the connection was ultimately established.
|
|
If the interface was NLB, state will be created to track the new connection; if
|
|
the interface was not NLB, the temporary state created by the SYN_SENT notification
|
|
is cleaned up.
|
|
|
|
SYN_RCVD -> ESTAB: An incoming connection has been established. This notification
|
|
is not currently required by NLB.
|
|
|
|
SYN_SENT -> CLOSED: An outgoing connection has been prematurely terminated (the
|
|
connection never reached the ESTABlished state). This notification does not require
|
|
the IP interface index. NLB will destroy any state created to track this connection.
|
|
|
|
SYN_RCVD -> CLOSED: An outgoing connection has been prematurely terminated (the
|
|
connection never reached the ESTABlished state). This notification does not require
|
|
the IP interface index. NLB will destroy any state created to track this connection.
|
|
|
|
ESTAB -> CLOSED: A connection has been *completely* terminated (i.e., the connection
|
|
has gone through TIME_WAIT, if necessary, already). This notification does not
|
|
require the IP interface index. NLB will destroy any state created to track this
|
|
connection.
|
|
*/
|
|
#define NLB_CONNECTION_CALLBACK_NAME L"\\Callback\\NLBConnectionCallback"
|
|
|
|
/*
|
|
This registry key instructs NLB which notification mechanism to use.
|
|
When deciding what notification(s) to use for connection management,
|
|
NLB checks the following, in this order:
|
|
|
|
(i) NLB first looks for the EnableTCPNotification registry key under
|
|
|
|
HKLM\System\CurrentControlSet\Services\WLBS\Parameters\Global\
|
|
|
|
This key has three possible values that instruct NLB on which
|
|
notifications to listen for. They are:
|
|
|
|
0 = Do not use any connection notifications.
|
|
1 = Use the TCP connection notifications.
|
|
2 = Use the NLB public connection notifications.
|
|
|
|
(ii) If the EnableTCPNotification registry is not present, NLB defaults
|
|
to using TCP notifications.
|
|
|
|
Note: The name of the key is EnableTCPNotifications for legacy reasons
|
|
although it controls multiple notifications covering multiple protocols.
|
|
*/
|
|
#define NLB_CONNECTION_CALLBACK_KEY L"EnableTCPNotification"
|
|
|
|
#define NLB_CONNECTION_CALLBACK_NONE 0
|
|
#define NLB_CONNECTION_CALLBACK_TCP 1
|
|
#define NLB_CONNECTION_CALLBACK_ALTERNATE 2
|
|
|
|
#define NLB_TCPIP_PROTOCOL_TCP 6 /* IP protocol ID for TCP. */
|
|
|
|
#define NLB_TCP_CLOSED 1 /* The TCP connection is/was CLOSED. */
|
|
#define NLB_TCP_SYN_SENT 3 /* The TCP connection is/was in SYN_SENT. */
|
|
#define NLB_TCP_SYN_RCVD 4 /* The TCP connection is/was in SYN_RCVD. */
|
|
#define NLB_TCP_ESTAB 5 /* The TCP connection is/was ESTABlished. */
|
|
|
|
/* Force default alignment on the callback buffers. */
|
|
#pragma pack(push)
|
|
#pragma pack()
|
|
typedef struct NLBTCPAddressInfo {
|
|
ULONG RemoteIPAddress; /* The remote (client) IP address, in network byte order. */
|
|
ULONG LocalIPAddress; /* The local (server) IP address, in network byte order. */
|
|
USHORT RemotePort; /* The remote (client) TCP port, in network byte order. */
|
|
USHORT LocalPort; /* The local (server) TCP port, in network byte order. */
|
|
} NLBTCPAddressInfo;
|
|
|
|
typedef struct NLBTCPConnectionInfo {
|
|
ULONG PreviousState; /* The previous state for the connection, as defined above. */
|
|
ULONG CurrentState; /* The new state for the connection, as defined above. */
|
|
ULONG IPInterface; /* The IP interface index on which the connection was, or is being, established. */
|
|
NLBTCPAddressInfo Address; /* A pointer to a block containing the IP tuple for the connection. */
|
|
} NLBTCPConnectionInfo;
|
|
|
|
typedef struct NLBConnectionInfo {
|
|
UCHAR Protocol; /* The protocol of the connection (currently, only TCP is supported). */
|
|
union {
|
|
NLBTCPConnectionInfo * pTCPInfo; /* A pointer to the TCP connection information block. */
|
|
};
|
|
} NLBConnectionInfo;
|
|
#pragma pack(pop)
|
|
|
|
#define NLB_DEVICE_NAME L"\\Device\\WLBS" /* The NLB device name for use in ZwCreateFile, for instance. */
|
|
|
|
/*
|
|
This IOCTL registers or de-registers a kernel-mode hook with NLB.
|
|
|
|
Returns:
|
|
o STATUS_SUCCESS - if the (de)registration succeeds.
|
|
o STATUS_INVALID_PARAMETER - if a parameter is invalid. E.g.,
|
|
- The I/O buffers are missing or the incorrect size.
|
|
- The HookIdentifier does not match a known NLB hook GUID.
|
|
- The HookTable entry is non-NULL, but the DeregisterCallback is NULL.
|
|
- The HookTable entry is non-NULL, but all hook function pointers are NULL.
|
|
- The HookTable entry is NULL, but no function is registered for this hook.
|
|
o STATUS_ACCESS_DENIED - if the operation will NOT be permitted by NLB. E.g.,
|
|
- The request to (de)register a hook does not come from kernel-mode.
|
|
- The de-register information provided is for a hook that was registered
|
|
by a different component, as identified by the RegisteringEntity.
|
|
- The specified hook has already been registered by somebody (anybody).
|
|
Components wishing to change their hook must first de-register it.
|
|
*/
|
|
#define NLB_IOCTL_REGISTER_HOOK CTL_CODE(0xc0c0, 18, METHOD_BUFFERED, FILE_WRITE_ACCESS)
|
|
|
|
#define NLB_HOOK_IDENTIFIER_LENGTH 39 /* 39 is sufficient for {GUID}. */
|
|
|
|
#define NLB_FILTER_HOOK_INTERFACE L"{069267c4-7eee-4aff-832c-02e22e00f96f}" /* The filter interface includes hooks for influencing the NLB
|
|
load-balancing decision on either the send path, receive path,
|
|
or both. This hook will be called for any packet for which
|
|
NLB would normally apply load-balancing policy. Components
|
|
registering this interface should use an NLB_FILTER_HOOK_TABLE
|
|
as the hook table in the NLB_IOCTL_REGISTER_HOOK_REQUEST. */
|
|
|
|
/* The de-register callback must be specifed for all register
|
|
operations. This function is called by NLB whenever a
|
|
registered hook is de-registered, either gracefully by the
|
|
registrar, or forcefully by NLB itself (as a result of the
|
|
NLB device driver getting unloaded). */
|
|
typedef VOID (* NLBHookDeregister) (PWCHAR pHookIdentifier, HANDLE RegisteringEntity, ULONG Flags);
|
|
|
|
/* Bit settings for the Flags field of the de-register callback. */
|
|
#define NLB_HOOK_DEREGISTER_FLAGS_FORCED 0x00000001
|
|
|
|
/* This enumerated type is the feedback for all filter hooks. */
|
|
typedef enum {
|
|
NLB_FILTER_HOOK_PROCEED_WITH_HASH, /* Continue to load-balance normally; i.e., the hook has no specific feedback. */
|
|
NLB_FILTER_HOOK_REVERSE_HASH, /* Use reverse hashing (use destination parameters, rather than source). */
|
|
NLB_FILTER_HOOK_FORWARD_HASH, /* Use conventional forward hashing (use source parameters). */
|
|
NLB_FILTER_HOOK_ACCEPT_UNCONDITIONALLY, /* By-pass load-balancing and accept the packet unconditionally. */
|
|
NLB_FILTER_HOOK_REJECT_UNCONDITIONALLY /* By-pass load-balancing and reject the packet unconditionally. */
|
|
} NLB_FILTER_HOOK_DIRECTIVE;
|
|
|
|
/*
|
|
Filter hooks:
|
|
|
|
The adapter GUID (1st parameter) will allow the hook consumer to
|
|
determine the adapter on which the packet is being sent or received.
|
|
Note that the length parameters are not necesarily indicative of the
|
|
actual length of the media header or payload themselves, but rather
|
|
indicate how much of the buffers pointed to are contiguously
|
|
accessible from the provided pointer. For instance, the payload
|
|
length may just be the length of an IP header, meaning that only
|
|
the IP header can be found at that pointer. However, it might
|
|
be equal to the total size of the packet payload, in which case,
|
|
that pointer can be used to access subsequent pieces of the
|
|
packet, such as the TCP header. If the payload length provided
|
|
is not sufficient to find all necessary packet information, the
|
|
packet pointer can be used to traverse the packet buffers manually
|
|
to try and find the information needed. However, note that the
|
|
packet may not always be available (it may be NULL).
|
|
*/
|
|
|
|
/* The send filter hook is invoked for every packet sent on any
|
|
adapter to which NLB is bound for which NLB would normally
|
|
apply load-balancing policy. ARPs, for instance, are not
|
|
filtered by NLB, so such packets would not be indicated to
|
|
this hook. */
|
|
typedef NLB_FILTER_HOOK_DIRECTIVE (* NLBSendFilterHook) (
|
|
const WCHAR * pAdapter, /* The GUID of the adapter on which the packet is being sent. */
|
|
const NDIS_PACKET * pPacket, /* A pointer to the NDIS packet, which CAN be NULL if not available. */
|
|
const UCHAR * pMediaHeader, /* A pointer to the media header (ethernet, since NLB supports only ethernet). */
|
|
ULONG cMediaHeaderLength, /* The length of contiguous memory accessible from the media header pointer. */
|
|
const UCHAR * pPayload, /* A pointer to the payload of the packet. */
|
|
ULONG cPayloadLength, /* The length of contiguous memory accesible from the payload pointer. */
|
|
ULONG Flags); /* Hook-related flags including whether or not the cluster is stopped. */
|
|
|
|
/* The receive filter hook is invoked for every packet received
|
|
on any adapter to which NLB is bound for which NLB would
|
|
normally apply load-balancing policy. Some protocols, such
|
|
as ARP, or NLB-specific packets not normally seen by the
|
|
protocol(s) bound to NLB (heartbeats, remote control requests)
|
|
are not filtered by NLB and will not be indicated to the hook. */
|
|
typedef NLB_FILTER_HOOK_DIRECTIVE (* NLBReceiveFilterHook) (
|
|
const WCHAR * pAdapter, /* The GUID of the adapter on which the packet was received. */
|
|
const NDIS_PACKET * pPacket, /* A pointer to the NDIS packet, which CAN be NULL if not available. */
|
|
const UCHAR * pMediaHeader, /* A pointer to the media header (ethernet, since NLB supports only ethernet). */
|
|
ULONG cMediaHeaderLength, /* The length of contiguous memory accessible from the media header pointer. */
|
|
const UCHAR * pPayload, /* A pointer to the payload of the packet. */
|
|
ULONG cPayloadLength, /* The length of contiguous memory accesible from the payload pointer. */
|
|
ULONG Flags); /* Hook-related flags including whether or not the cluster is stopped. */
|
|
|
|
/* The query filter hook is invoked in cases where the NLB driver
|
|
needs to invoke its hashing algorithm and therefore needs to
|
|
know whether or not the hook will influence the way in which
|
|
manner NLB performs the hash, if at all. */
|
|
typedef NLB_FILTER_HOOK_DIRECTIVE (* NLBQueryFilterHook) (
|
|
const WCHAR * pAdapter, /* The GUID of the adapter on which the packet was received. */
|
|
ULONG ServerIPAddress, /* The server IP address of the "packet" in NETWORK byte order. */
|
|
USHORT ServerPort, /* The server port of the "packet" (if applicable to the Protocol) in HOST byte order. */
|
|
ULONG ClientIPAddress, /* The client IP address of the "packet" in NETWORK byte order. */
|
|
USHORT ClientPort, /* The client port of the "packet" (if applicable to the Protocol) in HOST byte order. */
|
|
UCHAR Protocol, /* The IP protocol of the "packet"; TCP, UDP, ICMP, GRE, etc. */
|
|
BOOLEAN bReceiveContext, /* A boolean to indicate whether the packet is being processed in send or receive context. */
|
|
ULONG Flags); /* Hook-related flags including whether or not the cluster is stopped. */
|
|
|
|
/* Bit settings for the Flags field of the filter hooks. */
|
|
#define NLB_FILTER_HOOK_FLAGS_STOPPED 0x00000001
|
|
#define NLB_FILTER_HOOK_FLAGS_DRAINING 0x00000002
|
|
|
|
/* Force default alignment on the IOCTL buffers. */
|
|
#pragma pack(push)
|
|
#pragma pack()
|
|
/* This table contains function pointers to register or de-register
|
|
a packet filter hook. To register a hook, set the appropriate
|
|
function pointer. Those not being specified (for instance if
|
|
you want to register a receive hook, but not a send hook) should
|
|
be set to NULL. The QueryHook should ONLY be specified if in
|
|
conjunction with setting either the send or receive hook; i.e.
|
|
a user may not ONLY register the QueryHook. Further, if regis-
|
|
tering a send or receive hook (or both), the QueryHook MUST be
|
|
provided in order for NLB to query the hook response for cases
|
|
where a hashing decision is needed, but we are not in the context
|
|
of sending or receiving a packet; most notably, in a connection
|
|
up or down notification from IPSec or TCP. */
|
|
typedef struct {
|
|
NLBSendFilterHook SendHook;
|
|
NLBQueryFilterHook QueryHook;
|
|
NLBReceiveFilterHook ReceiveHook;
|
|
} NLB_FILTER_HOOK_TABLE, * PNLB_FILTER_HOOK_TABLE;
|
|
|
|
/* This is the input buffer for the hook (de)register IOCTL. There is
|
|
no corresponding output buffer. This structure identifies the hook
|
|
interface being (de)registered, the entity registering the hook and
|
|
all appropriate function pointers (callbacks). Note that hooks are
|
|
registered in groups, called interfaces, which prevents different
|
|
related hooks from being owned by different entities (for example,
|
|
it prevents one entity owned the send hook, but another owned the
|
|
receive hook). Interfaces are identified by a GUID, and to set any
|
|
hook in the interface requires ownership of the entire interface -
|
|
even if not all hooks in the interface are being specified. The hook
|
|
table should be a pointer to a hook table of the type required by the
|
|
specified hook identifier. To de-register a hook, set the hook table
|
|
pointer to NULL.
|
|
|
|
Note: The HookTable pointer does NOT need to be valid following the
|
|
completion of the IOCTL. That is, this pointer is only referenced
|
|
within the context of the IOCTL.
|
|
*/
|
|
typedef struct {
|
|
WCHAR HookIdentifier[NLB_HOOK_IDENTIFIER_LENGTH]; /* The GUID identifying the hook interface being registered. */
|
|
HANDLE RegisteringEntity; /* The open file handle on the NLB driver, which uniquely identifies the registrar. */
|
|
PVOID HookTable; /* A pointer to the appropriate hook table containing the hook function pointers. */
|
|
NLBHookDeregister DeregisterCallback; /* The de-register callback function, which MUST be non-NULL if the operation is a registration. */
|
|
} NLB_IOCTL_REGISTER_HOOK_REQUEST, * PNLB_IOCTL_REGISTER_HOOK_REQUEST;
|
|
#pragma pack(pop)
|
|
|
|
#endif
|