|
|
/*+++
Copyright (c) 1992 Microsoft Corporation
Module Name:
ddp.h
Abstract:
This module contains the DDP address object and ddp related definitions
Author:
Jameel Hyder (jameelh@microsoft.com) Nikhil Kamkolkar (nikhilk@microsoft.com)
Revision History: 19 Jun 1992 Initial Version
Notes: Tab stop: 4 --*/
#ifndef _DDP_
#define _DDP_
// Network number information.
#define FIRST_VALID_NETWORK 0x0001
#define LAST_VALID_NETWORK 0xFFFE
#define FIRST_STARTUP_NETWORK 0xFF00
#define LAST_STARTUP_NETWORK 0xFFFE
#define NULL_NETWORK 0x0000
#define UNKNOWN_NETWORK NULL_NETWORK
#define CABLEWIDE_BROADCAST_NETWORK NULL_NETWORK
// Appletalk Sockets Definitions
#define UNKNOWN_SOCKET 0
#define DYNAMIC_SOCKET UNKNOWN_SOCKET
#define LAST_VALID_SOCKET 254
#define FIRST_DYNAMIC_SOCKET 128
#define LAST_DYNAMIC_SOCKET LAST_VALID_SOCKET
#define FIRST_STATIC_SOCKET 1
#define FIRST_VALID_SOCKET FIRST_STATIC_SOCKET
#define LAST_STATIC_SOCKET 127
// "Well known" sockets:
#define RTMP_SOCKET 1 // RTMP
#define NAMESINFORMATION_SOCKET 2 // NBP
#define ECHOER_SOCKET 4 // EP
#define ZONESINFORMATION_SOCKET 6 // ZIP
#define LAST_APPLE_RESD_SOCKET 0x3F // Apple reserves 1 thru 0x3F
// DDP Datagram Definitions
#define MAX_DGRAM_SIZE 586
#define MAX_LDDP_PKT_SIZE 600 // Really 599, but even is nicer
#define MAX_SDDP_PKT_SIZE 592 // Again, really 591
// Define temporary buffer sizes, these must be big enough to hold both all
// of the packet data plus any link/hardware headers...
#define MAX_PKT_SIZE (MAX_HDR_LEN + MAX_LDDP_PKT_SIZE)
#define DDP_LEN_MASK1 0x03 // High order 3 bits of length
#define DDP_LEN_MASK2 0xFF // Next byte of length
// DDP packet offsets (skipping Link/Hardware headers):
#define SDDP_HDR_LEN 5
#define SDDP_LEN_OFFSET 0
#define SDDP_DEST_SOCKET_OFFSET 2
#define SDDP_SRC_SOCKET_OFFSET 3
#define SDDP_PROTO_TYPE_OFFSET 4
#define SDDP_DGRAM_OFFSET 5
#define LDDP_HDR_LEN 13
#define LDDP_LEN_OFFSET 0
#define LDDP_CHECKSUM_OFFSET 2
#define LDDP_DEST_NETWORK_OFFSET 4
#define LDDP_SRC_NETWORK_OFFSET 6
#define LDDP_DEST_NODE_OFFSET 8
#define LDDP_SRC_NODE_OFFSET 9
#define LDDP_DEST_SOCKET_OFFSET 10
#define LDDP_SRC_SOCKET_OFFSET 11
#define LDDP_PROTO_TYPE_OFFSET 12
#define LDDP_DGRAM_OFFSET 13
#define LEADING_UNCHECKSUMED_BYTES 4
#define LDDP_HOPCOUNT_MASK 0x3C
#define DECIMAL_BASE 10
// DDP protocol types:
#define DDPPROTO_ANY 0 // Used to allow any protocol packet
#define DDPPROTO_DDP 0
#define DDPPROTO_RTMPRESPONSEORDATA 1
#define DDPPROTO_NBP 2
#define DDPPROTO_ATP 3
#define DDPPROTO_EP 4
#define DDPPROTO_RTMPREQUEST 5
#define DDPPROTO_ZIP 6
#define DDPPROTO_ADSP 7
#define DDPPROTO_MAX 255
typedef struct _DDPEVENT_INFO { // Event handler routines: DDP Only has RecvDatagram/Error handlers
// The following function pointer always points to a TDI_IND_RECEIVE_DATAGRAM
// event handler for the address.
PTDI_IND_RECEIVE_DATAGRAM ev_RcvDgramHandler; PVOID ev_RcvDgramCtx;
// The following function pointer always points to a TDI_IND_ERROR
// handler for the address.
PTDI_IND_ERROR ev_ErrHandler; PVOID ev_ErrCtx; PVOID ev_ErrOwner;
// Winsock assumes a buffering transport. So we buffer the last datagram
// indicated that was not accepted.
BYTE ev_IndDgram[MAX_DGRAM_SIZE]; int ev_IndDgramLen; int ev_IndProto;
// Source address of buffered datagram
ATALK_ADDR ev_IndSrc;
} DDPEVENT_INFO, *PDDPEVENT_INFO;
// Handler type for the DDP address object
typedef VOID (*DDPAO_HANDLER)( IN PPORT_DESCRIPTOR pPortDesc, IN struct _DDP_ADDROBJ *pAddr, IN PBYTE pPkt, IN USHORT pPktLen, IN PATALK_ADDR pSrcAddr, IN PATALK_ADDR pActDest, IN ATALK_ERROR ErrorCode, IN BYTE pDdpType, IN PVOID pHandlerCtx, IN BOOLEAN OptimizedPath, IN PVOID OptimizeCtx);
// DDP Address Object
// This is the basic address object in the stack. All other address objects
// eventually resolve to this one. It also holds the AppletalkSocket opened
// as its actual address. One address object corresponds to one address.
// DDP ADDRESS OBJECT STATES
#define DDPAO_DGRAM_EVENT 0x00000001
#define DDPAO_DGRAM_ACTIVE 0x00000002
#define DDPAO_DGRAM_PENDING 0x00000004
#define DDPAO_SOCK_INTERNAL 0x00000008
#define DDPAO_SOCK_PNPZOMBIE 0x00000010
#define DDPAO_CLOSING 0x80000000
#define DDPAO_SIGNATURE (*(PULONG)"DDPA")
#define VALID_DDP_ADDROBJ(pDdpAddr) (((pDdpAddr) != NULL) && \
(((struct _DDP_ADDROBJ *)(pDdpAddr))->ddpao_Signature == DDPAO_SIGNATURE)) typedef struct _DDP_ADDROBJ { ULONG ddpao_Signature;
// This will be a hash overflow list. Hash on the internet address.
// List of address objects on the node linkage
struct _DDP_ADDROBJ * ddpao_Next;
ULONG ddpao_RefCount;
// State of the address object
ULONG ddpao_Flags;
// Backpointer to the node on which this socket exists
struct _ATALK_NODE * ddpao_Node;
// The Appletalk address number for this object
ATALK_ADDR ddpao_Addr;
// List of NBP names registered on this socket
struct _REGD_NAME * ddpao_RegNames;
// List of NBP names being looked up, registered or confirmed on
// this socket.
struct _PEND_NAME * ddpao_PendNames;
// Linked list of pending ddp reads
LIST_ENTRY ddpao_ReadLinkage;
// The protocol type to use for datagrams sent on this socket and
// which can be received on this socket. 0 => no restrictions.
BYTE ddpao_Protocol;
ATALK_SPIN_LOCK ddpao_Lock; PATALK_DEV_CTX ddpao_DevCtx;
// The handler below is an listener for the upper layers. Note that
// this will take precedence over a incoming datagram event handler
// which would be set in ddpao_EventInfo.
DDPAO_HANDLER ddpao_Handler; PVOID ddpao_HandlerCtx;
// This structure is allocated when setting an event handler
// on this socket. All the event handler addresses are part of this
// structure.
PDDPEVENT_INFO ddpao_EventInfo;
// Completion routine to be called when socket is closed
GENERIC_COMPLETION ddpao_CloseComp; PVOID ddpao_CloseCtx; } DDP_ADDROBJ, *PDDP_ADDROBJ;
// Receive datagram completion: This will return the mdl we pass in along
// with the received length written into the mdl. Also, the protocol type
// and the RemoteAddress are passed back. The receive context will be the
// irp for the request. As will be the send context.
typedef VOID (*RECEIVE_COMPLETION)( IN ATALK_ERROR ErrorCode, IN PAMDL OpaqueBuffer, IN USHORT LengthReceived, IN PATALK_ADDR RemoteAddress, IN PVOID ReceiveContext);
typedef VOID (FASTCALL *WRITE_COMPLETION)( IN NDIS_STATUS Status, IN PVOID Ctx);
typedef VOID (FASTCALL *TRANSMIT_COMPLETION)( IN NDIS_STATUS Status, IN struct _SEND_COMPL_INFO * pInfo);
// If the above routine was set in the AtalkDdpSend(), then
// then context values would be:
// Ctx1 = pddp address object
// Ctx2 = pbuffer descriptor
// Ctx3 = Only for DdpWrite calls, this will be a pointer to the
// write structure enqueued in the ddp address object.
//
// If the above routine was set in the AtalkDdpTransmit(), then
// the context values would be (as specified by the client of
// course):
// Ctx1 = pport descriptor
// Ctx2 = pbuffer descriptor
// Ctx3 = not used.
//
// These are only suggested ideas, but probably is what the internal
// stack routines will use.
// This is used to store a pending read on a particular socket.
typedef struct _DDP_READ { // Linkage chain for reads on a socket.
LIST_ENTRY dr_Linkage;
PAMDL dr_OpBuf; USHORT dr_OpBufLen;
RECEIVE_COMPLETION dr_RcvCmp; PVOID dr_RcvCtx;
} DDP_READ, *PDDP_READ;
// This is used to store a pending write on a particular socket
// DDP will create a buffer descriptor for the header
// and will chain it in front of the buffer descriptor passed in.
// A pointer to this structure will then be passed as a completion
// context to DdpSend.
typedef struct _DDP_WRITE { // Linkage chain for writes on a socket.
LIST_ENTRY dw_Linkage;
// The buffer descriptor chain, including the ddp buffer
// descriptor containing the ddp/optional/link headers.
PBUFFER_DESC dw_BufferDesc;
// Write completion
// This will be called with the context (which will be a pointer
// to the write irp) after the write completes.
WRITE_COMPLETION dw_WriteRoutine; PVOID dw_WriteCtx;
} DDP_WRITE, *PDDP_WRITE;
//
// CANCEL IRP Functionality for NT:
//
// We have decided that if we receive a cancel irp for a particular request,
// we will shutdown the file object associated with that request, whether it
// be a connection object or an address object. This implies that the socket/
// connection/listener will be closed, thus cancelling *all* pending requests.
//
ATALK_ERROR AtalkDdpOpenAddress( IN PPORT_DESCRIPTOR pPortDesc, IN BYTE Socket, IN OUT PATALK_NODEADDR pDesiredNode OPTIONAL, IN DDPAO_HANDLER pSktHandler OPTIONAL, IN PVOID pSktCtx OPTIONAL, IN BYTE ProtoType OPTIONAL, IN PATALK_DEV_CTX pDevCtx, OUT PDDP_ADDROBJ * pAddr);
ATALK_ERROR AtalkDdpCloseAddress( IN PDDP_ADDROBJ pAddr, IN GENERIC_COMPLETION pCloseCmp OPTIONAL, IN PVOID pCloseCtx OPTIONAL);
ATALK_ERROR AtalkDdpPnPSuspendAddress( IN PDDP_ADDROBJ pDdpAddr);
ATALK_ERROR AtalkDdpCleanupAddress( IN PDDP_ADDROBJ pAddr);
ATALK_ERROR AtalkDdpInitCloseAddress( IN PPORT_DESCRIPTOR pPortDesc, IN PATALK_ADDR pAtalkAddr);
ATALK_ERROR AtalkInitDdpOpenStaticSockets( IN PPORT_DESCRIPTOR pPortDesc, IN OUT PATALK_NODE pNode);
ATALK_ERROR AtalkDdpReceive( IN PDDP_ADDROBJ pAddr, IN PAMDL pAmdl, IN USHORT AmdlLen, IN ULONG RecvFlags, IN RECEIVE_COMPLETION pRcvCmp, IN PVOID pRcvCtx);
ATALK_ERROR AtalkDdpSend( IN PDDP_ADDROBJ pDdpAddr, IN PATALK_ADDR DestAddr, IN BYTE ProtoType, IN BOOLEAN DefinitelyRemoteAddr, IN PBUFFER_DESC pBufDesc, IN PBYTE pOptHdr OPTIONAL, IN USHORT OptHdrLen OPTIONAL, IN PBYTE pZoneMcastAddr OPTIONAL, IN struct _SEND_COMPL_INFO * pInfo OPTIONAL);
ATALK_ERROR AtalkDdpTransmit( IN PPORT_DESCRIPTOR pPortDesc, IN PATALK_ADDR SrcAddr, IN PATALK_ADDR DestAddr, IN BYTE ProtoType, IN PBUFFER_DESC pBufDesc, IN PBYTE pOptHdr OPTIONAL, IN USHORT OptHdrLen OPTIONAL, IN USHORT HopCnt, IN PBYTE pMcastAddr OPTIONAL, IN PATALK_NODEADDR pXmitDestNode OPTIONAL, IN struct _SEND_COMPL_INFO * pInfo OPTIONAL);
VOID AtalkDdpSendComplete( IN NDIS_STATUS Status, IN PBUFFER_DESC pBufDesc, IN struct _SEND_COMPL_INFO * pInfo OPTIONAL);
VOID AtalkDdpPacketIn( IN PPORT_DESCRIPTOR pPortDesc, IN PBYTE pLinkHdr, IN PBYTE pPkt, IN USHORT PktLen, IN BOOLEAN fWanPkt);
VOID AtalkDdpQuery( IN PDDP_ADDROBJ pDdpAddr, IN PAMDL pAmdl, OUT PULONG BytesWritten);
VOID AtalkDdpRefByAddr( IN PPORT_DESCRIPTOR pPortDesc, IN PATALK_ADDR pAtalkAddr, OUT PDDP_ADDROBJ * ppDdpAddr, OUT PATALK_ERROR pErr);
VOID AtalkDdpRefByAddrNode( IN PPORT_DESCRIPTOR pPortDesc, IN PATALK_ADDR pAtalkAddr, IN PATALK_NODE pAtalkNode, OUT PDDP_ADDROBJ * ppDdpAddr, OUT PATALK_ERROR pErr);
VOID AtalkDdpRefNextNc( IN PDDP_ADDROBJ pDdpAddr, IN PDDP_ADDROBJ * ppDdpAddr, OUT PATALK_ERROR pErr);
VOID FASTCALL AtalkDdpDeref( IN OUT PDDP_ADDROBJ pDdpAddr, IN BOOLEAN AtDpc);
VOID AtalkDdpOutBufToNodesOnPort( IN PPORT_DESCRIPTOR pPortDesc, IN PATALK_ADDR pSrc, IN PATALK_ADDR pDest, IN BYTE ProtoType, IN PBUFFER_DESC pBufDesc, IN PBYTE pOptHdr, IN USHORT OptHdrLen, OUT PBOOLEAN Delivered);
VOID AtalkDdpInPktToNodesOnPort( IN PPORT_DESCRIPTOR pPortDesc, IN PATALK_ADDR pDest, IN PATALK_ADDR pSrc, IN BYTE ProtoType, IN PBYTE pPkt, IN USHORT PktLen, OUT PBOOLEAN Routed);
VOID AtalkDdpInvokeHandlerBufDesc( IN PPORT_DESCRIPTOR pPortDesc, IN PDDP_ADDROBJ pDdpAddr, IN PATALK_ADDR pSrcAddr, IN PATALK_ADDR pActDest, IN BYTE ProtoType, IN PBUFFER_DESC pBufDesc, IN PBYTE pOptHdr, IN USHORT OptHdrLen);
VOID AtalkDdpInvokeHandler( IN PPORT_DESCRIPTOR pPortDesc, IN PDDP_ADDROBJ pDdpAddr, IN PATALK_ADDR pSrcAddr, IN PATALK_ADDR pActDest, IN BYTE ProtoType, IN PBYTE pPkt, IN USHORT PktLen);
USHORT AtalkDdpCheckSumBuffer( IN PBYTE Buffer, IN USHORT BufLen, IN USHORT CurrentCheckSum);
USHORT AtalkDdpCheckSumBufferDesc( IN PBUFFER_DESC pBuffDesc, IN USHORT Offset);
USHORT AtalkDdpCheckSumPacket( IN PBYTE pHdr, IN USHORT HdrLen, IN PBYTE pPkt, IN USHORT PktLen);
VOID AtalkDdpNewHandlerForSocket( IN PDDP_ADDROBJ pDdpAddr, IN DDPAO_HANDLER pSktHandler, IN PVOID pSktHandlerCtx);
// MACROS
#define DDP_MSB_LEN(L) (((L) >> 8) & 0x03)
#define DDP_GET_LEN(P) ((((*P) & 0x03) << 8) + *(P+1))
#define DDP_GET_HOP_COUNT(P) (((*P) >> 2) & 0x0F)
#define DDP_HOP_COUNT(H) (((H) & 0x0F) << 2)
#if DBG
#define AtalkDdpReferenceByPtr(pDdpAddr, pErr) \
{ \ KIRQL OldIrql; \ \ ACQUIRE_SPIN_LOCK(&(pDdpAddr)->ddpao_Lock, &OldIrql); \ AtalkDdpRefByPtrNonInterlock(pDdpAddr, pErr); \ RELEASE_SPIN_LOCK(&(pDdpAddr)->ddpao_Lock, OldIrql); \ DBGPRINT(DBG_COMP_DDP, DBG_LEVEL_REFDDP, \ ("AtalkDdpReferenceByPtr: %s %d PostCount %d\n",\ __FILE__, __LINE__,pDdpAddr->ddpao_RefCount)); \ }
#define AtalkDdpReferenceByPtrDpc(pDdpAddr, pErr) \
{ \ ACQUIRE_SPIN_LOCK_DPC(&(pDdpAddr)->ddpao_Lock); \ AtalkDdpRefByPtrNonInterlock(pDdpAddr, pErr); \ RELEASE_SPIN_LOCK_DPC(&(pDdpAddr)->ddpao_Lock); \ DBGPRINT(DBG_COMP_DDP, DBG_LEVEL_REFDDP, \ ("AtalkDdpReferenceByPtr: %s %d PostCount %d\n",\ __FILE__, __LINE__,pDdpAddr->ddpao_RefCount)); \ }
#define AtalkDdpRefByPtrNonInterlock(pDdpAddr, pErr) \
{ \ ASSERT (VALID_DDP_ADDROBJ(pDdpAddr)); \ \ *pErr = ATALK_DDP_CLOSING; \ \ if ((pDdpAddr->ddpao_Flags & DDPAO_CLOSING) == 0) \ { \ pDdpAddr->ddpao_RefCount++; \ *pErr = ATALK_NO_ERROR; \ } \ DBGPRINT(DBG_COMP_DDP, DBG_LEVEL_REFDDP, \ ("AtalkDdpReferenceByPtrNonInterlock: %s %d PostCount %d\n",\ __FILE__, __LINE__, \ pDdpAddr->ddpao_RefCount)); \ }
#define AtalkDdpReferenceNextNc(pDdpAddr, ppDdpAddr, pErr) \
{ \ AtalkDdpRefNextNc(pDdpAddr, ppDdpAddr, pErr); \ if (ATALK_SUCCESS(*pErr)) \ { \ DBGPRINT(DBG_COMP_DDP, DBG_LEVEL_REFDDP, \ ("DdpRefNextNc : %s %d PostCount %d\n", \ __FILE__, __LINE__, \ (*ppDdpAddr)->ddpao_RefCount)); \ } \ }
#define AtalkDdpReferenceByAddr(pPortDesc, pAddr, ppDdpAddr, pErr) \
{ \ AtalkDdpRefByAddr(pPortDesc, pAddr, ppDdpAddr, pErr); \ if (ATALK_SUCCESS(*pErr)) \ { \ DBGPRINT(DBG_COMP_DDP, DBG_LEVEL_REFDDP, \ ("AtalkDdpReferenceByAddr: %s %d PostCount %d\n",\ __FILE__, __LINE__, \ (*ppDdpAddr)->ddpao_RefCount)); \ } \ }
#define AtalkDdpDereference(pDdpAddr) \
{ \ DBGPRINT(DBG_COMP_DDP, DBG_LEVEL_REFDDP, \ ("AtalkDdpDereference: %s %d PreCount %d\n", \ __FILE__, __LINE__,pDdpAddr->ddpao_RefCount)); \ AtalkDdpDeref(pDdpAddr, FALSE); \ }
#define AtalkDdpDereferenceDpc(pDdpAddr) \
{ \ DBGPRINT(DBG_COMP_DDP, DBG_LEVEL_REFDDP, \ ("AtalkDdpDereferenceDpc: %s %d PreCount %d\n", \ __FILE__, __LINE__,pDdpAddr->ddpao_RefCount)); \ AtalkDdpDeref(pDdpAddr, TRUE); \ }
#else
#define AtalkDdpReferenceByPtr(pDdpAddr, pErr) \
{ \ KIRQL OldIrql; \ \ ACQUIRE_SPIN_LOCK(&(pDdpAddr)->ddpao_Lock, &OldIrql); \ AtalkDdpRefByPtrNonInterlock(pDdpAddr, pErr); \ RELEASE_SPIN_LOCK(&(pDdpAddr)->ddpao_Lock, OldIrql); \ }
#define AtalkDdpReferenceByPtrDpc(pDdpAddr, pErr) \
{ \ ACQUIRE_SPIN_LOCK_DPC(&(pDdpAddr)->ddpao_Lock); \ AtalkDdpRefByPtrNonInterlock(pDdpAddr, pErr); \ RELEASE_SPIN_LOCK_DPC(&(pDdpAddr)->ddpao_Lock); \ }
#define AtalkDdpRefByPtrNonInterlock(pDdpAddr, pErr) \
{ \ *pErr = ATALK_DDP_CLOSING; \ \ if ((pDdpAddr->ddpao_Flags & DDPAO_CLOSING) == 0) \ { \ pDdpAddr->ddpao_RefCount++; \ *pErr = ATALK_NO_ERROR; \ } \ }
#define AtalkDdpReferenceByAddr(pPortDesc, pAddr, ppDdpAddr, pErr) \
AtalkDdpRefByAddr(pPortDesc, pAddr, ppDdpAddr, pErr)
#define AtalkDdpReferenceNextNc(pDdpAddr, ppDdpAddr, pErr) \
AtalkDdpRefNextNc(pDdpAddr, ppDdpAddr, pErr)
#define AtalkDdpDereference(pDdpAddr) \
AtalkDdpDeref(pDdpAddr, FALSE)
#define AtalkDdpDereferenceDpc(pDdpAddr) \
AtalkDdpDeref(pDdpAddr, TRUE) #endif
#define NET_ON_NONEXTPORT(pPort) \
(pPort->pd_LtNetwork)
#define NODE_ON_NONEXTPORT(pPort) \
(((pPort)->pd_Nodes != NULL) ? \ (pPort)->pd_Nodes->an_NodeAddr.atn_Node : 0)
ATALK_ERROR atalkDdpAllocSocketOnNode( IN PPORT_DESCRIPTOR pPortDesc, IN BYTE Socket, IN PATALK_NODE pAtalkNode, IN DDPAO_HANDLER pSktHandler OPTIONAL, IN PVOID pSktCtx OPTIONAL, IN BYTE ProtoType OPTIONAL, IN PATALK_DEV_CTX pDevCtx, OUT PDDP_ADDROBJ pDdpAddr);
VOID atalkDdpInitCloseComplete( IN ATALK_ERROR Error, IN PVOID Ctx);
/*
PBRE atalkDdpFindInBrc( IN PPORT_DESCRIPTOR pPortDesc, IN PATALK_NODEADDR pDestNodeAddr); */ #define atalkDdpFindInBrc(_pPortDesc, _Network, _ppBre) \
{ \ USHORT index; \ KIRQL OldIrql; \ PBRE pBre; \ \ index = (_Network) & (PORT_BRC_HASH_SIZE - 1); \ \ ACQUIRE_SPIN_LOCK(&(_pPortDesc)->pd_Lock, &OldIrql); \ \ for (pBre = (_pPortDesc)->pd_Brc[index]; \ pBre != NULL; \ pBre = pBre->bre_Next) \ { \ if ((_Network) == pBre->bre_Network) \ { \ break; \ } \ } \ \ RELEASE_SPIN_LOCK(&(_pPortDesc)->pd_Lock, OldIrql); \ \ *(_ppBre) = pBre; \ }
BOOLEAN atalkDdpFindAddrOnList( IN PATALK_NODE pAtalkNode, IN ULONG Index, IN BYTE Socket, OUT PDDP_ADDROBJ * ppDdpAddr);
#define IS_VALID_SOCKET(Socket) \
((Socket == DYNAMIC_SOCKET) || \ (Socket == LAST_DYNAMIC_SOCKET) || \ ((Socket >= FIRST_STATIC_SOCKET) && \ (Socket <= LAST_STATIC_SOCKET)))
#endif // _DDP_
|