windows-nt/Source/XPSP1/NT/net/rras/ndis/raspppoe/packet.h
2020-09-26 16:20:57 +08:00

559 lines
17 KiB
C

#ifndef _PACKET_H_
#define _PACKET_H_
#ifndef _PPPOE_VERSION
#define _PPPOE_VERSION 1
#endif
typedef struct _ADAPTER* PADAPTER;
typedef struct _BINDING* PBINDING;
//
// Network-to-Host and vice versa conversion macros
//
#if (defined(_M_IX86) && (_MSC_FULL_VER > 13009037)) || ((defined(_M_AMD64) || defined(_M_IA64)) && (_MSC_FULL_VER > 13009175))
#define htons(x) _byteswap_ushort((USHORT)(x))
#define htonl(x) _byteswap_ulong((ULONG)(x))
#else
#define htons( a ) ((((a) & 0xFF00) >> 8) |\
(((a) & 0x00FF) << 8))
#define htonl( a ) ((((a) & 0xFF000000) >> 24) | \
(((a) & 0x00FF0000) >> 8) | \
(((a) & 0x0000FF00) << 8) | \
(((a) & 0x000000FF) << 24))
#endif
#define ntohs( a ) htons(a)
#define ntohl( a ) htonl(a)
//
// Constants related to packet lengths
//
#define PPPOE_PACKET_BUFFER_SIZE 1514
#define ETHERNET_HEADER_LENGTH 14
#define PPPOE_PACKET_HEADER_LENGTH 20 // Per RFC2156
#define PPPOE_TAG_HEADER_LENGTH 4 // Per RFC2156
#define PPP_MAX_HEADER_LENGTH 14 // maximum possible header length for ppp
#define PPPOE_AC_COOKIE_TAG_LENGTH 6
//
// Offsets for the header members
//
#define PPPOE_PACKET_DEST_ADDR_OFFSET 0 // Per RFC2156
#define PPPOE_PACKET_SRC_ADDR_OFFSET 6 // Per RFC2156
#define PPPOE_PACKET_ETHER_TYPE_OFFSET 12 // Per RFC2156
#define PPPOE_PACKET_VERSION_OFFSET 14 // Per RFC2156
#define PPPOE_PACKET_TYPE_OFFSET 14 // Per RFC2156
#define PPPOE_PACKET_CODE_OFFSET 15 // Per RFC2156
#define PPPOE_PACKET_SESSION_ID_OFFSET 16 // Per RFC2156
#define PPPOE_PACKET_LENGTH_OFFSET 18 // Per RFC2156
//
// Macros to set information in the header of the packet
//
#define PacketSetDestAddr( pP, addr ) \
NdisMoveMemory( ( pP->pHeader + PPPOE_PACKET_DEST_ADDR_OFFSET ), addr, 6 )
#define PacketSetSrcAddr( pP, addr ) \
NdisMoveMemory( ( pP->pHeader + PPPOE_PACKET_SRC_ADDR_OFFSET ), addr, 6 )
#define PacketSetEtherType( pP, type ) \
* ( USHORT UNALIGNED * ) ( pP->pHeader + PPPOE_PACKET_ETHER_TYPE_OFFSET ) = htons( (USHORT) type )
#define PacketSetVersion( pP, ver ) \
* ( UCHAR UNALIGNED * ) ( pP->pHeader + PPPOE_PACKET_VERSION_OFFSET ) |= ( ( ( (UCHAR) ver ) << 4 ) & PACKET_VERSION_MASK )
#define PacketSetType( pP, type ) \
* ( UCHAR UNALIGNED * ) ( pP->pHeader + PPPOE_PACKET_TYPE_OFFSET ) |= ( ( (UCHAR) type ) & PACKET_TYPE_MASK )
#define PacketSetCode( pP, code ) \
* ( UCHAR UNALIGNED * ) ( pP->pHeader + PPPOE_PACKET_CODE_OFFSET ) = ( (UCHAR) code )
#define PacketSetSessionId( pP, ses_id ) \
* ( USHORT UNALIGNED * ) ( pP->pHeader + PPPOE_PACKET_SESSION_ID_OFFSET ) = htons( (USHORT) ses_id )
#define PacketSetLength( pP, len) \
* ( USHORT UNALIGNED * ) ( pP->pHeader + PPPOE_PACKET_LENGTH_OFFSET ) = htons( (USHORT) len )
#define PacketSetSendCompletionStatus( pP, s ) \
( pP->SendCompletionStatus = s )
//
// Macros to get information from the header of the packet
//
#define PacketGetDestAddr( pP ) \
( pP->pHeader + PPPOE_PACKET_DEST_ADDR_OFFSET )
#define PacketGetSrcAddr( pP ) \
( pP->pHeader + PPPOE_PACKET_SRC_ADDR_OFFSET )
#define PacketGetEtherType( pP ) \
ntohs( * ( USHORT UNALIGNED * ) ( pP->pHeader + PPPOE_PACKET_ETHER_TYPE_OFFSET ) )
#define PacketGetVersion( pP ) \
( ( ( * ( UCHAR UNALIGNED * ) ( pP->pHeader + PPPOE_PACKET_VERSION_OFFSET ) ) & PACKET_VERSION_MASK ) >> 4 )
#define PacketGetType( pP ) \
( ( * ( UCHAR UNALIGNED * ) ( pP->pHeader + PPPOE_PACKET_TYPE_OFFSET ) ) & PACKET_TYPE_MASK )
#define PacketGetCode( pP ) \
( * ( UCHAR UNALIGNED * ) ( pP->pHeader + PPPOE_PACKET_CODE_OFFSET ) )
#define PacketGetSessionId( pP ) \
ntohs( * ( USHORT UNALIGNED * ) ( pP->pHeader + PPPOE_PACKET_SESSION_ID_OFFSET ) )
#define PacketGetLength( pP ) \
ntohs( * ( USHORT UNALIGNED * ) ( pP->pHeader + PPPOE_PACKET_LENGTH_OFFSET ) )
#define PacketGetSendCompletionStatus( pP ) \
( pP->SendCompletionStatus )
//
// Macro that returns the Ndis Packet for a PPPoE packet
//
#define PacketGetNdisPacket( pP ) \
( pP->pNdisPacket )
//
// This structure is just a map, and it is not actually used in the code
//
typedef struct
_PPPOE_HEADER
{
CHAR DestAddr[6];
CHAR SrcAddr[6];
#define PACKET_BROADCAST_ADDRESS EthernetBroadcastAddress
USHORT usEtherType;
#define PACKET_ETHERTYPE_DISCOVERY 0x8863
#define PACKET_ETHERTYPE_PAYLOAD 0x8864
union
{
//
// Version field is 4 bits and MUST be set to 0x1 for this version
//
CHAR usVersion;
#define PACKET_VERSION_MASK 0xf0
#define PACKET_VERSION (USHORT)0x1
//
// Type field is 4 bits and MUST be set to 0x1 for this version
//
CHAR usType;
#define PACKET_TYPE_MASK 0x0f
#define PACKET_TYPE (USHORT)0x1
} uVerType;
//
// Code field is 8 bits and is defined as follows for Version 1
// Values selected from enumerated type PACKET_CODES (see below)
//
CHAR usCode;
//
// Session Id field is 16 bits and define a unique session combined with
// the source and destination addresses
//
USHORT usSessionId;
#define PACKET_NULL_SESSION 0x0000
//
// Length field is 16 bits and indicates the length of the payload field only.
// The length field excludes the PPPoE header block.
//
USHORT usLength;
//
// Subtract Header size from Max PADI and MAX payload lengths per RFC2156
//
#define PACKET_PADI_MAX_LENGTH 1478 // (1514 - 20 - 16)
#define PACKET_GEN_MAX_LENGTH 1494 // (1514 - 20)
#define PACKET_PPP_PAYLOAD_MAX_LENGTH 1480 // (1514 - 20)
}
PPPOE_HEADER;
//
// PACKET CODES defined by RFC2156
//
typedef enum
_PACKET_CODES
{
PACKET_CODE_PADI = 0x09,
PACKET_CODE_PADO = 0x07,
PACKET_CODE_PADR = 0x19,
PACKET_CODE_PADS = 0x65,
PACKET_CODE_PADT = 0xa7,
PACKET_CODE_PAYLOAD = 0x00
}
PACKET_CODES;
//
// TAGS defined by RFC2156
//
typedef enum
_PACKET_TAGS
{
tagEndOfList = 0x0000,
tagServiceName = 0x0101,
tagACName = 0x0102,
tagHostUnique = 0x0103,
tagACCookie = 0x0104,
tagVendorSpecific = 0x0105,
tagRelaySessionId = 0x0110,
tagServiceNameError = 0x0201,
tagACSystemError = 0x0202,
tagGenericError = 0x0204
}
PACKET_TAGS;
//
// This is the packet context.
//
// CAUTION: Packets are not protected by their own locks, however they must be accessed carefully
// by using their owner's locks.
//
typedef struct
_PPPOE_PACKET
{
//
// Points to the previous and next packet contexts when in a doubly linked list
//
LIST_ENTRY linkPackets;
//
// Keeps references on the packet
// References added and removed for the following operations:
//
// (a) A reference is added when a packet is created and removed when it is freed.
//
// (b) A reference must be added before sending the packet and must be removed when
// send operation is completed.
//
LONG lRef;
//
// Quick look-up for tags.
//
// The value pointers mark the beginning of the tag value in the pPacket->pPayload section.
// The length values show the lengths of the values (not including the tag header)
//
USHORT tagServiceNameLength;
CHAR* tagServiceNameValue;
USHORT tagACNameLength;
CHAR* tagACNameValue;
USHORT tagHostUniqueLength;
CHAR* tagHostUniqueValue;
USHORT tagACCookieLength;
CHAR* tagACCookieValue;
USHORT tagRelaySessionIdLength;
CHAR* tagRelaySessionIdValue;
PACKET_TAGS tagErrorType;
USHORT tagErrorTagLength;
CHAR* tagErrorTagValue;
//
// Points to the buffer that holds the header portion of a PPPoE packet in wire format.
// This points to the buffer portion of pNdisBuffer (see below)
//
CHAR* pHeader;
//
// Points to the payload portion of a PPPoE packet in wire format.
// This is calculated and is set as : pPacket->pHeader + PPPOE_PACKET_HEADER_LENGTH
//
CHAR* pPayload;
//
// Bit flags that identifies the nature of the buffer and packet
//
// (a) PCBF_BufferAllocatedFromNdisBufferPool: Indicates that pNdisBuffer points to a buffer allocated
// from gl_hNdisBufferpool, and it must be freed to that pool.
//
// (b) PCBF_BufferAllocatedFromOurBufferPool: Indicates that pNdisBuffer points to a buffer allocated
// from gl_poolBuffers, and it must be freed to that pool.
//
// (c) PCBF_PacketAllocatedFromOurPacketPool: Indicates that pNdisPacket points to a packet allocated
// from gl_poolPackets, and it must be freed to that pool.
//
// (d) PCBF_BufferChainedToPacket: Indicates that the buffer pointed to by pNdisBuffer is chained to
// the packet pointed to by pNdisPacket, and must be unchained before
// returning them back to their pools.
//
// (e) PCBF_CallNdisReturnPackets: Indicates that the packet was created using PacketCreateFromReceived()
// and we should call NdisReturnPackets() when we are done with it to
// return it back to NDIS.
//
//
// (f) PCBF_ErrorTagReceived: This flag is valid only for received packets.
// It indicates that when the packet was processed and a PPPoE packet was created
// some error tags were noticed in the packet.
//
ULONG ulFlags;
#define PCBF_BufferAllocatedFromNdisBufferPool 0x00000001
#define PCBF_BufferAllocatedFromOurBufferPool 0x00000002
#define PCBF_PacketAllocatedFromOurPacketPool 0x00000004
#define PCBF_BufferChainedToPacket 0x00000008
#define PCBF_CallNdisReturnPackets 0x00000010
#define PCBF_CallNdisMWanSendComplete 0x00000020
#define PCBF_ErrorTagReceived 0x00000040
#define PCBF_PacketIndicatedIncomplete 0x00000080
//
// Pointer to the NdisBuffer
//
NDIS_BUFFER* pNdisBuffer;
//
// Points directly to the NDIS_PACKET
//
NDIS_PACKET* pNdisPacket;
//
// pPacket->pNdisPacket->ProtocolReserved[0 * sizeof(PVOID)] = (PVOID) pPPPoEPacket;
// pPacket->pNdisPacket->ProtocolReserved[1 * sizeof(PVOID)] = (PVOID) pNdiswanPacket;
// pPacket->pNdisPacket->ProtocolReserved[2 * sizeof(PVOID)] = (PVOID) miniportAdapter;
//
//
// Points to the PACKETHEAD struct in ppool.h. It contains the pointer to NDIS_PACKET
//
PACKETHEAD* pPacketHead;
//
// This is needed to dereference the binding when PCBF_CallNdisReturnPackets flag is set.
//
PBINDING pBinding;
//
// Send completion status for the packet
//
NDIS_STATUS SendCompletionStatus;
}
PPPOE_PACKET;
VOID PacketPoolInit();
VOID PacketPoolUninit();
VOID PacketPoolAlloc();
VOID PacketPoolFree();
PPPOE_PACKET* PacketAlloc();
VOID PacketFree(
IN PPPOE_PACKET* pPacket
);
VOID ReferencePacket(
IN PPPOE_PACKET* pPacket
);
VOID DereferencePacket(
IN PPPOE_PACKET* pPacket
);
PPPOE_PACKET*
PacketCreateSimple();
PPPOE_PACKET*
PacketCreateForReceived(
PBINDING pBinding,
PNDIS_PACKET pNdisPacket,
PNDIS_BUFFER pNdisBuffer,
PUCHAR pContents
);
PPPOE_PACKET*
PacketNdis2Pppoe(
IN PBINDING pBinding,
IN PNDIS_PACKET pNdisPacket,
OUT PINT pRefCount
);
BOOLEAN
PacketFastIsPPPoE(
IN CHAR* HeaderBuffer,
IN UINT HeaderBufferSize
);
VOID
RetrieveTag(
IN OUT PPPOE_PACKET* pPacket,
IN PACKET_TAGS tagType,
OUT USHORT* pTagLength,
OUT CHAR** pTagValue,
IN USHORT prevTagLength,
IN CHAR* prevTagValue,
IN BOOLEAN fSetTagInPacket
);
NDIS_STATUS PacketInsertTag(
IN PPPOE_PACKET* pPacket,
IN PACKET_TAGS tagType,
IN USHORT tagLength,
IN CHAR* tagValue,
OUT CHAR** pNewTagValue
);
NDIS_STATUS PacketInitializePADIToSend(
OUT PPPOE_PACKET** ppPacket,
IN USHORT tagServiceNameLength,
IN CHAR* tagServiceNameValue,
IN USHORT tagHostUniqueLength,
IN CHAR* tagHostUniqueValue
);
NDIS_STATUS
PacketInitializePADOToSend(
IN PPPOE_PACKET* pPADI,
OUT PPPOE_PACKET** ppPacket,
IN CHAR* pSrcAddr,
IN USHORT tagServiceNameLength,
IN CHAR* tagServiceNameValue,
IN USHORT tagACNameLength,
IN CHAR* tagACNameValue,
IN BOOLEAN fInsertACCookieTag
);
NDIS_STATUS PacketInitializePADRToSend(
IN PPPOE_PACKET* pPADO,
OUT PPPOE_PACKET** ppPacket,
IN USHORT tagServiceNameLength,
IN CHAR* tagServiceNameValue,
IN USHORT tagHostUniqueLength,
IN CHAR* tagHostUniqueValue
);
NDIS_STATUS PacketInitializePADSToSend(
IN PPPOE_PACKET* pPADR,
OUT PPPOE_PACKET** ppPacket,
IN USHORT usSessionId
);
NDIS_STATUS PacketInitializePADTToSend(
OUT PPPOE_PACKET** ppPacket,
IN CHAR* pSrcAddr,
IN CHAR* pDestAddr,
IN USHORT usSessionId
);
NDIS_STATUS PacketInitializePAYLOADToSend(
OUT PPPOE_PACKET** ppPacket,
IN CHAR* pSrcAddr,
IN CHAR* pDestAddr,
IN USHORT usSessionId,
IN NDIS_WAN_PACKET* pWanPacket,
IN PADAPTER MiniportAdapter
);
NDIS_STATUS PacketInitializeFromReceived(
IN PPPOE_PACKET* pPacket
);
BOOLEAN PacketAnyErrorTagsReceived(
IN PPPOE_PACKET* pPacket
);
VOID PacketRetrievePayload(
IN PPPOE_PACKET* pPacket,
OUT CHAR** ppPayload,
OUT USHORT* pusLength
);
VOID PacketRetrieveServiceNameTag(
IN PPPOE_PACKET* pPacket,
OUT USHORT* pTagLength,
OUT CHAR** pTagValue,
IN USHORT prevTagLength,
IN CHAR* prevTagValue
);
VOID PacketRetrieveHostUniqueTag(
IN PPPOE_PACKET* pPacket,
OUT USHORT* pTagLength,
OUT CHAR** pTagValue
);
VOID PacketRetrieveACNameTag(
IN PPPOE_PACKET* pPacket,
OUT USHORT* pTagLength,
OUT CHAR** pTagValue
);
VOID PacketRetrieveACCookieTag(
IN PPPOE_PACKET* pPacket,
OUT USHORT* pTagLength,
OUT CHAR** pTagValue
);
VOID PacketRetrieveErrorTag(
IN PPPOE_PACKET* pPacket,
OUT PACKET_TAGS* pTagType,
OUT USHORT* pTagLength,
OUT CHAR** pTagValue
);
PPPOE_PACKET* PacketGetRelatedPppoePacket(
IN NDIS_PACKET* pNdisPacket
);
NDIS_WAN_PACKET* PacketGetRelatedNdiswanPacket(
IN PPPOE_PACKET* pPacket
);
PADAPTER PacketGetMiniportAdapter(
IN PPPOE_PACKET* pPacket
);
PPPOE_PACKET* PacketMakeClone(
IN PPPOE_PACKET* pPacket
);
VOID
PacketGenerateACCookieTag(
IN PPPOE_PACKET* pPacket,
IN CHAR tagACCookieValue[ PPPOE_AC_COOKIE_TAG_LENGTH ]
);
BOOLEAN
PacketValidateACCookieTagInPADR(
IN PPPOE_PACKET* pPacket
);
//////////////////////////////////////////////////////////
//
// Error codes and messages
//
//////////////////////////////////////////////////////////
#define PPPOE_ERROR_BASE 0
#define PPPOE_NO_ERROR PPPOE_ERROR_BASE
#define PPPOE_ERROR_SERVICE_NOT_SUPPORTED PPPOE_ERROR_BASE + 1
#define PPPOE_ERROR_SERVICE_NOT_SUPPORTED_MSG "Service not supported"
#define PPPOE_ERROR_SERVICE_NOT_SUPPORTED_MSG_SIZE ( sizeof( PPPOE_ERROR_SERVICE_NOT_SUPPORTED_MSG ) / sizeof( CHAR ) )
#define PPPOE_ERROR_INVALID_AC_COOKIE_TAG PPPOE_ERROR_BASE + 2
#define PPPOE_ERROR_INVALID_AC_COOKIE_TAG_MSG "AC-Cookie tag is invalid"
#define PPPOE_ERROR_INVALID_AC_COOKIE_TAG_MSG_SIZE ( sizeof( PPPOE_ERROR_INVALID_AC_COOKIE_TAG_MSG ) / sizeof( CHAR ) )
#define PPPOE_ERROR_CLIENT_QUOTA_EXCEEDED PPPOE_ERROR_BASE + 3
#define PPPOE_ERROR_CLIENT_QUOTA_EXCEEDED_MSG "Can not accept any more connections from this machine"
#define PPPOE_ERROR_CLIENT_QUOTA_EXCEEDED_MSG_SIZE ( sizeof( PPPOE_ERROR_CLIENT_QUOTA_EXCEEDED_MSG ) / sizeof( CHAR ) )
#endif