windows-nt/Source/XPSP1/NT/net/sfm/atalk/sys/ports.h
2020-09-26 16:20:57 +08:00

529 lines
15 KiB
C

/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
ports.h
Abstract:
This module contains the structures for ports.
Author:
Jameel Hyder (jameelh@microsoft.com)
Nikhil Kamkolkar (nikhilk@microsoft.com)
Revision History:
19 Jun 1992 Initial Version
Notes: Tab stop: 4
--*/
#ifndef _PORTS_
#define _PORTS_
#define PORT_AMT_HASH_SIZE 64
#define PORT_BRC_HASH_SIZE 16
#define MAX_ENTITY_LENGTH 32
#define MAX_HW_ADDR_LEN 6
#define MAX_ROUTING_BYTES 18
#define MAX_ROUTING_SPACE 0x1F // This much space is allocated
// for routing info
typedef VOID (*REQ_COMPLETION)(
NDIS_STATUS Status,
PVOID Ctx
);
// Prototypes for handlers
typedef ATALK_ERROR (*ADDMULTICASTADDR)(
struct _PORT_DESCRIPTOR *pPortDesc,
PBYTE Addr,
BOOLEAN ExecuteSync,
REQ_COMPLETION AddCompletion,
PVOID AddContext);
typedef ATALK_ERROR (*REMOVEMULTICASTADDR)(
struct _PORT_DESCRIPTOR *pPortDesc,
PBYTE Addr,
BOOLEAN ExecuteSync,
REQ_COMPLETION RemoveCompletion,
PVOID RemoveContext);
// Address mapping table
// Each port that the stack or router is communicating on must have an
// address mapping table [except non-extended ports]. The mapping table
// holds the association between Appletalk node addresses (network/node),
// and the actual hardware (ethernet/tokenring) addresses. Hash on the
// network/node value.
#define AMT_SIGNATURE (*(ULONG *)"AMT ")
#if DBG
#define VALID_AMT(pAmt) (((pAmt) != NULL) && \
((pAmt)->amt_Signature == AMT_SIGNATURE))
#else
#define VALID_AMT(pAmt) ((pAmt) != NULL)
#endif
typedef struct _AMT_NODE
{
#if DBG
DWORD amt_Signature;
#endif
struct _AMT_NODE * amt_Next;
ATALK_NODEADDR amt_Target;
BYTE amt_HardwareAddr[MAX_HW_ADDR_LEN];
BYTE amt_Age;
BYTE amt_RouteInfoLen;
// BYTE amt_RouteInfo[MAX_ROUTING_SPACE];
} AMT, *PAMT;
#define AMT_AGE_TIME 600 // In 100ms units
#define AMT_MAX_AGE 3
// Best Router Entry Table
// Maintained only for extended networks. This must age more quickly than the
// "SeenARouter" timer (50 seconds). To avoid allocations/frees for this structure,
// we use statically allocated data in the port descriptor.
typedef struct _BRE
{
struct _BRE * bre_Next;
USHORT bre_Network;
BYTE bre_Age;
BYTE bre_RouterAddr[MAX_HW_ADDR_LEN];
BYTE bre_RouteInfoLen;
// BYTE bre_RouteInfo[MAX_ROUTING_SPACE];
} BRE, *PBRE;
#define BRC_AGE_TIME 40 // In 100ms units
#define BRC_MAX_AGE 3
//
// Types of ports currently supported by stack. This is kept different
// from the NDIS medium types for two reasons. One is we use these as
// an index into the port handler array, and the second is if we decide
// to implement half-ports etc., which ndis might not be able to deal with.
// WARNING: THIS IS INTEGRATED WITH THE PORT HANDLER ARRAY IN GLOBALS.
typedef enum
{
ELAP_PORT = 0,
FDDI_PORT,
TLAP_PORT,
ALAP_PORT,
ARAP_PORT,
LAST_PORT,
LAST_PORTTYPE = LAST_PORT
} ATALK_PORT_TYPE;
//
// PORT DESCRIPTORS
// Descriptor for each active port:
//
#define PD_ACTIVE 0x00000001 // State after packets recv enabled
#define PD_BOUND 0x00000002 // State it goes in before ACTIVE
#define PD_EXT_NET 0x00000004 // For now, non-localtalk
#define PD_DEF_PORT 0x00000008 // Is this the default port
#define PD_SEND_CHECKSUMS 0x00000010 // Send ddp checksums?
#define PD_SEED_ROUTER 0x00000020 // seeding on this port?
#define PD_ROUTER_STARTING 0x00000040 // Temporary state when router is starting
#define PD_ROUTER_RUNNING 0x00000080 // Is the router running?
#define PD_SEEN_ROUTER_RECENTLY 0x00000100 // Seen router recently?
#define PD_VALID_DESIRED_ZONE 0x00000200 // Desired Zone is valid
#define PD_VALID_DEFAULT_ZONE 0x00000400 // Default zone is valid
#define PD_FINDING_DEFAULT_ZONE 0x00000800 // searching for default zone?
#define PD_FINDING_DESIRED_ZONE 0x00001000 // searching for desired zone?
#define PD_FINDING_NODE 0x00002000 // In the process of acquiring a
// new node on this port
#define PD_NODE_IN_USE 0x00004000 // Tentative node is already in
// use.
#define PD_ROUTER_NODE 0x00008000 // Router node is allocated
#define PD_USER_NODE_1 0x00010000 // First user node is allocated
#define PD_USER_NODE_2 0x00020000 // Second user node is allocated
#define PD_RAS_PORT 0x00040000 // this port for RAS clients
#define PD_PNP_RECONFIGURE 0x00080000 // this port is currently being reconfigured
#define PD_CONFIGURED_ONCE 0x00100000 // this port has been configured once
#define PD_CLOSING 0x80000000 // State when unbinding/shutting down
#define PD_SIGNATURE (*(ULONG *)"PDES")
#if DBG
#define VALID_PORT(pPortDesc) (((pPortDesc) != NULL) && \
((pPortDesc)->pd_Signature == PD_SIGNATURE))
#else
#define VALID_PORT(pPortDesc) ((pPortDesc) != NULL)
#endif
typedef struct _PORT_DESCRIPTOR
{
#if DBG
ULONG pd_Signature;
#endif
// Link to next - for now to help debugging
struct _PORT_DESCRIPTOR *pd_Next;
// Number of references to this port
ULONG pd_RefCount;
// State of the port
ULONG pd_Flags;
// if this is a Ras port, all ARAP connetions hang on this list
LIST_ENTRY pd_ArapConnHead;
// if this is a Ras port, all PPP connetions hang on this list
LIST_ENTRY pd_PPPConnHead;
// if this is a Ras port, how many lines do we have on this port?
ULONG pd_RasLines;
// Overide the default number of aarp probes when looking for a
// node on this port
SHORT pd_AarpProbes;
// Node # of the localtalk node
USHORT pd_LtNetwork;
// Nodes that are being managed on this port. We have a maximum
// of 2 nodes (3 if the router is started).
struct _ATALK_NODE * pd_Nodes;
struct _ATALK_NODE * pd_RouterNode;
// Following are used only during node acquisition process.
// PD_FINDINGNODE is set. Keep this separate from the ndis
// request event. Both could happen at the same time.
ATALK_NODEADDR pd_TentativeNodeAddr;
KEVENT pd_NodeAcquireEvent;
// Port type as defined above
ATALK_PORT_TYPE pd_PortType;
// NdisMedium type for this port
NDIS_MEDIUM pd_NdisPortType;
// Used during OpenAdapter to block
KEVENT pd_RequestEvent;
NDIS_STATUS pd_RequestStatus;
// Binding handle to the mac associated with this port
// Options associated with the mac.
// MAC Options - these are things that we can and cannot do with
// specific macs. Is the value of OID_GEN_MAC_OPTIONS.
NDIS_HANDLE pd_NdisBindingHandle;
ULONG pd_MacOptions;
// This is the spin lock used to protect all requests that need exclusion
// over requests per port.
ATALK_SPIN_LOCK pd_Lock;
// All the packets received on this port are linked in here. When the
// receive complete indication is called, all of them are passed to DDP.
LIST_ENTRY pd_ReceiveQueue;
// ASCII port name to be registered on the router node for this port
// This will be an NBP object name and hence is limited to 32 characters.
CHAR pd_PortName[MAX_ENTITY_LENGTH + 1];
// AdapterName is of the form \Device\<adaptername>. It is used
// to bind to the NDIS macs, and then during ZIP requests by setup
// to get the zonelist for a particular adapter. AdapterKey
// contains the adapterName only- this is useful both for getting
// per-port parameters and during errorlogging to specify the adapter
// name without the '\Device\' prefix.
UNICODE_STRING pd_AdapterKey;
UNICODE_STRING pd_AdapterName;
UNICODE_STRING pd_FriendlyAdapterName;
ATALK_NODEADDR pd_RoutersPramNode;
ATALK_NODEADDR pd_UsersPramNode1;
ATALK_NODEADDR pd_UsersPramNode2;
HANDLE pd_AdapterInfoHandle; // Valid during initialization only
// Initial values from the registry
ATALK_NETWORKRANGE pd_InitialNetworkRange;
struct _ZONE_LIST * pd_InitialZoneList;
struct _ZONE * pd_InitialDefaultZone;
struct _ZONE * pd_InitialDesiredZone;
// True cable range of connected network. Initial/aged values for
// extended ports: 1:FFFE; Initial value for non-extended ports:
// 0:0 (does not age).
ATALK_NETWORKRANGE pd_NetworkRange;
// If we are routing, this is the default zone for the network
// on this port, and the zone list for the same.
struct _ZONE_LIST * pd_ZoneList;
struct _ZONE * pd_DefaultZone;
struct _ZONE * pd_DesiredZone;
// When did we hear from a router?
LONG pd_LastRouterTime;
// Address of last router seen. If we are a routing port, this will
// always be the node that "our" router is operating on!
ATALK_NODEADDR pd_ARouter;
KEVENT pd_SeenRouterEvent;
// Zone in which all nodes on this port reside and the multicast
// address for it.
CHAR pd_ZoneMulticastAddr[MAX_HW_ADDR_LEN];
union
{
struct
{
//
// FOR ETHERNET PORTS:
//
// We add multicast addresses during ZIP packet reception at non-init
// time. We need to do a GET followed by a SET with the new address
// list. But there could be two zip packets coming in and doing the
// same thing effectively overwriting the effects of the first one to
// set the multicast list. So we need to maintain our own copy of the
// multicast list.
//
// Size of the list
ULONG pd_MulticastListSize;
PCHAR pd_MulticastList;
};
struct
{
//
// FOR TOKENRING PORTS:
//
// Just like for ethernet, we need to store the value for
// the current functional address. We only modify the last
// four bytes of this address, as the first two always remain
// constant. So we use a ULONG for it.
//
UCHAR pd_FunctionalAddr[4]; // TLAP_ADDR_LEN - TLAP_MCAST_HDR_LEN
};
};
// Hardware address for the port
union
{
UCHAR pd_PortAddr[MAX_HW_ADDR_LEN];
USHORT pd_AlapNode;
};
// Mapping table for best route to "off cable" addresses.
TIMERLIST pd_BrcTimer;
PBRE pd_Brc[PORT_BRC_HASH_SIZE];
// Logical/physical address mappings for the nodes on the network that
// this port is connected to.
ULONG pd_AmtCount; // # of entries in the Amt
TIMERLIST pd_AmtTimer;
PAMT pd_Amt[PORT_AMT_HASH_SIZE];
union
{
TIMERLIST pd_RtmpSendTimer; // If router is configured
TIMERLIST pd_RtmpAgingTimer; // else
};
// Per port statistics
ATALK_PORT_STATS pd_PortStats;
// Port handler stuff
ADDMULTICASTADDR pd_AddMulticastAddr;
REMOVEMULTICASTADDR pd_RemoveMulticastAddr;
BYTE pd_BroadcastAddr[MAX_HW_ADDR_LEN];
USHORT pd_BroadcastAddrLen;
USHORT pd_AarpHardwareType;
USHORT pd_AarpProtocolType;
PKEVENT pd_ShutDownEvent;
} PORT_DESCRIPTOR, *PPORT_DESCRIPTOR;
#define INDICATE_ATP 0x01
#define INDICATE_ADSP 0x02
#define ATALK_CACHE_SKTMAX 8
#define ATALK_CACHE_ADSPSKT ((BYTE)0x01)
#define ATALK_CACHE_ATPSKT ((BYTE)0x02)
#define ATALK_CACHE_INUSE ((BYTE)0x10)
#define ATALK_CACHE_NOTINUSE ((BYTE)0)
typedef struct _ATALK_SKT_CACHE
{
USHORT ac_Network;
BYTE ac_Node;
struct ATALK_CACHED_SKT
{
BYTE Type;
BYTE Socket;
union
{
// For ATP
struct _ATP_ADDROBJ * pAtpAddr;
} u;
} ac_Cache[ATALK_CACHE_SKTMAX];
} ATALK_SKT_CACHE, *PATALK_SKT_CACHE;
extern ATALK_SKT_CACHE AtalkSktCache;
extern ATALK_SPIN_LOCK AtalkSktCacheLock;
// externS
extern PPORT_DESCRIPTOR AtalkPortList; // Head of the port list
extern PPORT_DESCRIPTOR AtalkDefaultPort; // Ptr to the def port
extern KEVENT AtalkDefaultPortEvent; // Signalled when default port is available
extern UNICODE_STRING AtalkDefaultPortName; // Name of the default port
extern ATALK_SPIN_LOCK AtalkPortLock; // Lock for AtalkPortList
extern ATALK_NODEADDR AtalkUserNode1; // Node address of user node
extern ATALK_NODEADDR AtalkUserNode2; // Node address of user node
extern SHORT AtalkNumberOfPorts; // Determine dynamically
extern SHORT AtalkNumberOfActivePorts;// Number of ports active
extern BOOLEAN AtalkRouter; // Are we a router?
extern BOOLEAN AtalkFilterOurNames; // If TRUE, Nbplookup fails on names on this machine
extern KEVENT AtalkUnloadEvent; // Event for unloading
extern NDIS_HANDLE AtalkNdisPacketPoolHandle;
extern NDIS_HANDLE AtalkNdisBufferPoolHandle;
extern LONG AtalkHandleCount;
extern UNICODE_STRING AtalkRegPath;
extern HANDLE TdiRegistrationHandle;
extern BOOLEAN AtalkNoDefPortPrinted;
// Exported prototypes
extern
VOID FASTCALL
AtalkPortDeref(
IN OUT PPORT_DESCRIPTOR pPortDesc,
IN BOOLEAN AtDpc);
extern
BOOLEAN
AtalkReferenceDefaultPort(
IN VOID
);
extern
ATALK_ERROR
AtalkPortShutdown(
IN OUT PPORT_DESCRIPTOR pPortDesc);
VOID FASTCALL
AtalkPortSetResetFlag(
IN PPORT_DESCRIPTOR pPortDesc,
IN BOOLEAN fRemoveBit,
IN DWORD dwBit);
// Macros
#define AtalkPortReferenceByPtr(Port, pErr) \
{ \
DBGPRINT(DBG_COMP_REFCOUNTS, DBG_LEVEL_INFO, \
("Ref at %s %d\n", __FILE__, __LINE__)); \
AtalkPortRefByPtr((Port), (pErr)); \
}
#define AtalkPortReferenceByPtrDpc(Port, pErr) \
{ \
DBGPRINT(DBG_COMP_REFCOUNTS, DBG_LEVEL_INFO, \
("Ref (Dpc) at %s %d\n", \
__FILE__, __LINE__)); \
AtalkPortRefByPtrDpc((Port), (pErr)); \
}
#define AtalkPortReferenceByPtrNonInterlock(Port, pErr) \
{ \
DBGPRINT(DBG_COMP_REFCOUNTS, DBG_LEVEL_INFO, \
("Ref at %s %d\n", __FILE__, __LINE__)); \
AtalkPortRefByPtrNonInterlock((Port), (pErr)); \
}
#define AtalkPortReferenceByDdpAddr(DdpAddr, Port, pErr) \
{ \
DBGPRINT(DBG_COMP_REFCOUNTS, DBG_LEVEL_INFO, \
("Ref at %s %d\n", __FILE__, __LINE__)); \
AtalkPortRefByDdpAddr((DdpAddr), (Port), (pErr)); \
}
#define AtalkPortDereference(Port) \
{ \
DBGPRINT(DBG_COMP_REFCOUNTS, DBG_LEVEL_INFO, \
("Deref at %s %d\n", __FILE__, __LINE__)); \
AtalkPortDeref(Port, FALSE); \
}
#define AtalkPortDereferenceDpc(Port) \
{ \
DBGPRINT(DBG_COMP_REFCOUNTS, DBG_LEVEL_INFO, \
("Deref at %s %d\n", __FILE__, __LINE__)); \
AtalkPortDeref(Port, TRUE); \
}
#define EXT_NET(_pPortDesc) ((_pPortDesc)->pd_Flags & PD_EXT_NET)
#define DEF_PORT(_pPortDesc) ((_pPortDesc)->pd_Flags & PD_DEF_PORT)
#define PORT_BOUND(_pPortDesc) ((_pPortDesc)->pd_Flags & PD_BOUND)
#define PORT_CLOSING(_pPortDesc) ((_pPortDesc)->pd_Flags & PD_CLOSING)
#define AtalkPortRefByPtr(pPortDesc, pErr) \
{ \
KIRQL OldIrql; \
\
ACQUIRE_SPIN_LOCK(&((pPortDesc)->pd_Lock),&OldIrql);\
AtalkPortRefByPtrNonInterlock((pPortDesc), (pErr)); \
RELEASE_SPIN_LOCK(&((pPortDesc)->pd_Lock),OldIrql); \
}
#define AtalkPortRefByPtrDpc(pPortDesc, pErr) \
{ \
ACQUIRE_SPIN_LOCK_DPC(&((pPortDesc)->pd_Lock)); \
AtalkPortRefByPtrNonInterlock((pPortDesc), (pErr)); \
RELEASE_SPIN_LOCK_DPC(&((pPortDesc)->pd_Lock)); \
}
#define AtalkPortRefByPtrNonInterlock(pPortDesc, pErr) \
{ \
if (((pPortDesc)->pd_Flags & PD_CLOSING) == 0) \
{ \
ASSERT((pPortDesc)->pd_RefCount > 0); \
(pPortDesc)->pd_RefCount++; \
*(pErr) = ATALK_NO_ERROR; \
} \
else \
{ \
*(pErr) = ATALK_PORT_CLOSING; \
} \
}
#define AtalkPortRefByDdpAddr(pDdpAddr, ppPortDesc, pErr) \
{ \
ASSERT(VALID_ATALK_NODE((pDdpAddr)->ddpao_Node)); \
\
*(ppPortDesc) = (pDdpAddr)->ddpao_Node->an_Port; \
AtalkPortRefByPtr(*(ppPortDesc), (pErr)); \
}
VOID
atalkPortFreeZones(
IN PPORT_DESCRIPTOR pPortDesc
);
#endif // _PORTS_