235 lines
11 KiB
C
235 lines
11 KiB
C
|
// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs)
|
||
|
//
|
||
|
// Copyright (c) 1985-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:
|
||
|
//
|
||
|
// This file contains the definitions of TDI address objects and related
|
||
|
// constants and structures.
|
||
|
//
|
||
|
|
||
|
|
||
|
#define ao_signature 0x20204F41 // 'AO '.
|
||
|
|
||
|
#define WILDCARD_PORT 0 // 0 means assign a port.
|
||
|
|
||
|
#define MIN_USER_PORT 1025 // Minimum value for a wildcard port.
|
||
|
#define MAX_USER_PORT 5000 // Maximim value for a user port.
|
||
|
#define NUM_USER_PORTS (uint)(MaxUserPort - MIN_USER_PORT + 1)
|
||
|
|
||
|
#define NETBT_SESSION_PORT 139
|
||
|
|
||
|
typedef struct AddrObj AddrObj;
|
||
|
|
||
|
// Datagram transport-specific send function.
|
||
|
typedef void (*DGSendProc)(AddrObj *SrcAO, void *SendReq);
|
||
|
|
||
|
//
|
||
|
// Definition of the structure of an address object. Each object represents
|
||
|
// a local address, and the IP portion may be a wildcard.
|
||
|
//
|
||
|
typedef struct AddrObj {
|
||
|
#if DBG
|
||
|
ulong ao_sig;
|
||
|
#endif
|
||
|
struct AddrObj *ao_next; // Next address object in chain.
|
||
|
KSPIN_LOCK ao_lock; // Lock for this object.
|
||
|
struct AORequest *ao_request; // Pointer to pending request.
|
||
|
Queue ao_sendq; // Queue of sends waiting for transmit.
|
||
|
Queue ao_pendq; // Linkage for pending queue.
|
||
|
Queue ao_rcvq; // Receive queue.
|
||
|
IPv6Addr ao_addr; // IP address for this address object.
|
||
|
ulong ao_scope_id; // Scope ID of IP address (0 if none).
|
||
|
ushort ao_port; // Local port for this address object.
|
||
|
uchar ao_prot; // Protocol for this AO.
|
||
|
uchar ao_index; // Index into table of this AO.
|
||
|
ulong ao_flags; // Flags for this object.
|
||
|
uint ao_listencnt; // Number of listening connections.
|
||
|
ushort ao_usecnt; // Count of 'uses' on AO.
|
||
|
ushort ao_inst; // 'Instance' number of this AO.
|
||
|
int ao_ucast_hops; // Hop count for unicast packets.
|
||
|
uint ao_mcast_if; // Our multicast source interface.
|
||
|
int ao_mcast_hops; // Hop count for multicast packets.
|
||
|
int ao_mcast_loop; // The multicast loopback state.
|
||
|
Queue ao_activeq; // Queue of active connections.
|
||
|
Queue ao_idleq; // Queue of inactive (no TCB) connctns.
|
||
|
Queue ao_listenq; // Queue of listening connections.
|
||
|
WORK_QUEUE_ITEM ao_workitem; // Work-queue item to use for this AO.
|
||
|
PConnectEvent ao_connect; // Connect event handle.
|
||
|
PVOID ao_conncontext; // Receive DG context.
|
||
|
PDisconnectEvent ao_disconnect; // Disconnect event routine.
|
||
|
PVOID ao_disconncontext; // Disconnect event context.
|
||
|
PErrorEvent ao_error; // Error event routine.
|
||
|
PVOID ao_errcontext; // Error event context.
|
||
|
PRcvEvent ao_rcv; // Receive event handler.
|
||
|
PVOID ao_rcvcontext; // Receive context.
|
||
|
PRcvDGEvent ao_rcvdg; // Receive DG event handler.
|
||
|
PVOID ao_rcvdgcontext; // Receive DG context.
|
||
|
PRcvEvent ao_exprcv; // Expedited receive event handler.
|
||
|
PVOID ao_exprcvcontext; // Expedited receive context.
|
||
|
struct AOMCastAddr *ao_mcastlist; // List of active multicast addresses.
|
||
|
DGSendProc ao_dgsend; // Datagram transport send function.
|
||
|
PTDI_IND_ERROR_EX ao_errorex; // Error event routine.
|
||
|
PVOID ao_errorexcontext; // Error event context.
|
||
|
ushort ao_maxdgsize; // maximum user datagram size.
|
||
|
ushort ao_udp_cksum_cover; // UDP-Lite checksum coverage.
|
||
|
ulong ao_owningpid; // Process ID of owner.
|
||
|
uint* ao_iflist; // List of enabled interfaces.
|
||
|
} AddrObj;
|
||
|
|
||
|
#define AO_RCV_HOPLIMIT_FLAG 0x00020000 // Receive HopLimit in aux data.
|
||
|
// 0x00010000 Reserved for AO_WINSET_FLAG.
|
||
|
// 0x00008000 Reserved for AO_SCALE_CWIN_FLAG.
|
||
|
// 0x00004000 Reserved for AO_DEFERRED_FLAG.
|
||
|
#define AO_PKTINFO_FLAG 0x00002000 // Packet info structure passed in
|
||
|
// control info (WSARecvMsg).
|
||
|
#define AO_SHARE_FLAG 0x00001000 // AddrObj can be shared.
|
||
|
// 0x00000800 Reserved for AO_CONNUDP_FLAG.
|
||
|
#define AO_HDRINCL_FLAG 0x00000400 // User provides IP header on raw send.
|
||
|
#define AO_RAW_FLAG 0x00000200 // AO is for a raw endpoint.
|
||
|
#define AO_DHCP_FLAG 0x00000100 // AO is bound to real 0 address.
|
||
|
|
||
|
#define AO_VALID_FLAG 0x00000080 // AddrObj is valid.
|
||
|
#define AO_BUSY_FLAG 0x00000040 // AddrObj is busy (i.e., has it
|
||
|
// exclusive).
|
||
|
#define AO_OOR_FLAG 0x00000020 // AddrObj is out of resources, and on
|
||
|
// either the pending or delayed queue.
|
||
|
#define AO_QUEUED_FLAG 0x00000010 // AddrObj is on the pending queue.
|
||
|
|
||
|
// 0x00000008 Reserved for AO_XSUM_FLAG.
|
||
|
#define AO_SEND_FLAG 0x00000004 // Send is pending.
|
||
|
#define AO_OPTIONS_FLAG 0x00000002 // Option set pending.
|
||
|
#define AO_DELETE_FLAG 0x00000001 // Delete pending.
|
||
|
|
||
|
|
||
|
#define AO_VALID(A) ((A)->ao_flags & AO_VALID_FLAG)
|
||
|
#define SET_AO_INVALID(A) (A)->ao_flags &= ~AO_VALID_FLAG
|
||
|
|
||
|
#define AO_BUSY(A) ((A)->ao_flags & AO_BUSY_FLAG)
|
||
|
#define SET_AO_BUSY(A) (A)->ao_flags |= AO_BUSY_FLAG
|
||
|
#define CLEAR_AO_BUSY(A) (A)->ao_flags &= ~AO_BUSY_FLAG
|
||
|
|
||
|
#define AO_OOR(A) ((A)->ao_flags & AO_OOR_FLAG)
|
||
|
#define SET_AO_OOR(A) (A)->ao_flags |= AO_OOR_FLAG
|
||
|
#define CLEAR_AO_OOR(A) (A)->ao_flags &= ~AO_OOR_FLAG
|
||
|
|
||
|
#define AO_QUEUED(A) ((A)->ao_flags & AO_QUEUED_FLAG)
|
||
|
#define SET_AO_QUEUED(A) (A)->ao_flags |= AO_QUEUED_FLAG
|
||
|
#define CLEAR_AO_QUEUED(A) (A)->ao_flags &= ~AO_QUEUED_FLAG
|
||
|
|
||
|
#define AO_REQUEST(A, f) ((A)->ao_flags & f##_FLAG)
|
||
|
#define SET_AO_REQUEST(A, f) (A)->ao_flags |= f##_FLAG
|
||
|
#define CLEAR_AO_REQUEST(A, f) (A)->ao_flags &= ~f##_FLAG
|
||
|
#define AO_PENDING(A) \
|
||
|
((A)->ao_flags & (AO_DELETE_FLAG | AO_OPTIONS_FLAG | AO_SEND_FLAG))
|
||
|
|
||
|
#define AO_SHARE(A) ((A)->ao_flags & AO_SHARE_FLAG)
|
||
|
#define SET_AO_SHARE(A) (A)->ao_flags |= AO_SHARE_FLAG
|
||
|
#define CLEAR_AO_SHARE(A) (A)->ao_flags &= ~AO_SHARE_FLAG
|
||
|
|
||
|
#define AO_HDRINCL(A) ((A)->ao_flags & AO_HDRINCL_FLAG)
|
||
|
#define SET_AO_HDRINCL(A) (A)->ao_flags |= AO_HDRINCL_FLAG
|
||
|
#define CLEAR_AO_HDRINCL(A) (A)->ao_flags &= ~AO_HDRINCL_FLAG
|
||
|
|
||
|
#define AO_PKTINFO(A) ((A)->ao_flags & AO_PKTINFO_FLAG)
|
||
|
#define SET_AO_PKTINFO(A) (A)->ao_flags |= AO_PKTINFO_FLAG
|
||
|
#define CLEAR_AO_PKTINFO(A) (A)->ao_flags &= ~AO_PKTINFO_FLAG
|
||
|
|
||
|
#define AO_RCV_HOPLIMIT(A) ((A)->ao_flags & AO_RCV_HOPLIMIT_FLAG)
|
||
|
#define SET_AO_RCV_HOPLIMIT(A) (A)->ao_flags |= AO_RCV_HOPLIMIT_FLAG
|
||
|
#define CLEAR_AO_RCV_HOPLIMIT(A) (A)->ao_flags &= ~AO_RCV_HOPLIMIT_FLAG
|
||
|
|
||
|
//
|
||
|
// Definition of an address object search context. This is a data structure
|
||
|
// used when the address object table is to be read sequentially.
|
||
|
//
|
||
|
typedef struct AOSearchContext {
|
||
|
AddrObj *asc_previous; // Previous AO found.
|
||
|
IPv6Addr asc_addr; // IP address to be found.
|
||
|
uint asc_scope_id; // Scope id for IP address.
|
||
|
ushort asc_port; // Port to be found.
|
||
|
uchar asc_prot; // Protocol.
|
||
|
uchar asc_pad; // Pad to dword boundary.
|
||
|
} AOSearchContext;
|
||
|
|
||
|
//
|
||
|
// Definition of an AO request structure. There structures are used only for
|
||
|
// queuing delete and option set requests.
|
||
|
//
|
||
|
#define aor_signature 0x20524F41
|
||
|
|
||
|
typedef struct AORequest {
|
||
|
#if DBG
|
||
|
ulong aor_sig;
|
||
|
#endif
|
||
|
struct AORequest *aor_next; // Next pointer in chain.
|
||
|
uint aor_id; // ID for the request.
|
||
|
uint aor_length; // Length of buffer.
|
||
|
void *aor_buffer; // Buffer for this request.
|
||
|
RequestCompleteRoutine aor_rtn; // Complete routine for this request.
|
||
|
PVOID aor_context; // Request context;
|
||
|
} AORequest;
|
||
|
|
||
|
typedef struct AOMCastAddr {
|
||
|
struct AOMCastAddr *ama_next; // Next in list.
|
||
|
IPv6Addr ama_addr; // The address.
|
||
|
uint ama_if; // The interface.
|
||
|
} AOMCastAddr;
|
||
|
|
||
|
|
||
|
//
|
||
|
// External declarations for exported functions.
|
||
|
//
|
||
|
extern uint AddrObjTableSize;
|
||
|
extern AddrObj **AddrObjTable;
|
||
|
extern AddrObj *GetAddrObj(IPv6Addr *LocalAddr, uint LocalScopeId,
|
||
|
ushort LocalPort, uchar Prot, AddrObj *PreviousAO,
|
||
|
Interface* IF);
|
||
|
extern AddrObj *GetNextAddrObj(AOSearchContext *SearchContext);
|
||
|
extern AddrObj *GetFirstAddrObj(IPv6Addr *LocalAddr, uint LocalScopeId,
|
||
|
ushort LocalPort, uchar Prot,
|
||
|
AOSearchContext *SearchContext);
|
||
|
extern TDI_STATUS TdiOpenAddress(PTDI_REQUEST Request,
|
||
|
TRANSPORT_ADDRESS UNALIGNED *AddrList,
|
||
|
uint Protocol, void *Reuse);
|
||
|
extern TDI_STATUS TdiCloseAddress(PTDI_REQUEST Request);
|
||
|
extern TDI_STATUS SetAddrOptions(PTDI_REQUEST Request, uint ID, uint OptLength,
|
||
|
void *Options);
|
||
|
extern TDI_STATUS TdiSetEvent(PVOID Handle, int Type, PVOID Handler,
|
||
|
PVOID Context);
|
||
|
extern uchar GetAddress(TRANSPORT_ADDRESS UNALIGNED *AddrList,
|
||
|
IPv6Addr *Addr, ulong *ScopeId, ushort *Port);
|
||
|
extern int InitAddr(void);
|
||
|
extern void AddrUnload(void);
|
||
|
extern void ProcessAORequests(AddrObj *RequestAO);
|
||
|
extern void DelayDerefAO(AddrObj *RequestAO);
|
||
|
extern void DerefAO(AddrObj *RequestAO);
|
||
|
extern void FreeAORequest(AORequest *FreedRequest);
|
||
|
extern uint ValidateAOContext(void *Context, uint *Valid);
|
||
|
extern uint ReadNextAO(void *Context, void *OutBuf);
|
||
|
extern void InvalidateAddrs(IPv6Addr *Addr, uint ScopeId);
|
||
|
|
||
|
extern uint MCastAddrOnAO(AddrObj *AO, IPv6Addr *Addr);
|
||
|
extern AOMCastAddr *FindAOMCastAddr(AddrObj *AO, IPv6Addr *Addr, uint IFNo, AOMCastAddr **PrevAMA, BOOLEAN Loose);
|
||
|
|
||
|
#define GetBestAddrObj(addr, scope, port, prot, if) \
|
||
|
GetAddrObj(addr, scope, port, prot, NULL, if)
|
||
|
|
||
|
#define REF_AO(a) (a)->ao_usecnt++
|
||
|
|
||
|
#define DELAY_DEREF_AO(a) DelayDerefAO((a))
|
||
|
#define DEREF_AO(a) DerefAO((a))
|
||
|
#define LOCKED_DELAY_DEREF_AO(a) (a)->ao_usecnt--; \
|
||
|
\
|
||
|
if (!(a)->ao_usecnt && !AO_BUSY((a)) && AO_PENDING((a))) { \
|
||
|
SET_AO_BUSY((a)); \
|
||
|
ExQueueWorkItem(&(a)->ao_workitem, CriticalWorkQueue); \
|
||
|
}
|
||
|
|