//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//
//
//
//	See RFC2472 "IP Version 6 over PPP"
//


#ifndef IPV6CP_H
#define IPV6CP_H

#include "layerfsm.h"


// IPCP Option Values

#define IPV6CP_OPT_INTERFACE_IDENTIFIER    1
#define IPV6CP_OPT_COMPRESSION_PROTOCOL    2

//  IPV6 Interface Identifier Length is 8 octets,
//	the lower 8 bytes of the 16 byte IPV6 address

#define IPV6_IFID_LENGTH	8

//  Different methods for generating IFIDs
#define METHOD_IFID_REGISTRY          0
#define METHOD_IFID_PERSISTENT_RANDOM 1
#define METHOD_IFID_EUI               2
#define METHOD_IFID_DEVICE_ID         3
#define METHOD_IFID_RANDOM            4

//  IPV6CP Context

typedef struct  IPV6Context
{
    pppSession_t  	*pSession;                   // PPP session context

	PPppFsm			pFsm;

	//
	// Note: There may be a requirement imposed by tcpip6 that the
	// peer IFID immediately follow the Local IFID.
	//
	BYTE			LocalInterfaceIdentifier[IPV6_IFID_LENGTH];
	BYTE			PeerInterfaceIdentifier[IPV6_IFID_LENGTH];
	BYTE			IFIDSuggestedToPeer[IPV6_IFID_LENGTH];
	BYTE			LocalCompressionProtocol[2];
	BYTE			PeerCompressionProtocol[2];

	DWORD           dwOptionFlags;
#define OPTION_DISABLE_REGISTRY_IFID		(1<<METHOD_IFID_REGISTRY)
#define OPTION_DISABLE_PERSISTENT_RANDOM	(1<<METHOD_IFID_PERSISTENT_RANDOM)
#define OPTION_DISABLE_EUI_IFID	            (1<<METHOD_IFID_EUI)
#define OPTION_DISABLE_DEVICE_IFID	        (1<<METHOD_IFID_DEVICE_ID)

	//
	// Keeps track of the method that will be used to try to generate
	// a unique Interface Identifier.
	//
	DWORD           NextIFIDMethod;

	//
	// The IFID may be specified in the registry.
	//
	BYTE            RegistryIFID[IPV6_IFID_LENGTH];
	BOOL            bRegistryIFIDPresent;

	//
	// Random IFID generated in an earlier session and preserved in the registry
	//
	BYTE            RegistryRandomIFID[IPV6_IFID_LENGTH];
	BOOL            bRegistryRandomIFIDPresent;

	//
	// EUI of some adapter on the local machine, if available.
	// cbEUI set to 0 if no EUI available locally.
	//
	BYTE	        EUI[8];
	DWORD           cbEUI;

	//
	// Unique device ID for this computer, if available.
	//
	BYTE            DeviceID[IPV6_IFID_LENGTH];
	DWORD           cbDeviceID;

	//
	// Network prefix (to be sent by server in Routing Advertisements)
	//
	BYTE            NetPrefix[16];
	DWORD           NetPrefixBitLength;

} IPV6Context, *PIPV6Context;

DWORD	pppIpv6cp_InstanceCreate( void *SessionContext, void **ReturnContext );
void    pppIpv6cp_InstanceDelete( void  *context );
DWORD   Ipv6cpOpen( void  *context );
DWORD   Ipv6cpClose( void  *context );
DWORD   Ipv6cpRenegotiate( void  *context );
void	pppIpv6cp_LowerLayerUp(void *context);
void    pppIpv6cp_LowerLayerDown(IN	PVOID	context);
void    pppIpv6cp_Rejected( void  *context );

void    pppIpv6cpRcvData( void *context, pppMsg_t *msg_p );
void    pppIpv6cpSendData( void *context, PNDIS_PACKET Packet);

void
pppIpv6ReceiveIPV6(
	IN  PIPV6Context pContext,
	IN  pppMsg_t    *pMsg );

DWORD   ipv6cpOptionInit(PIPV6Context pContext);
void    ipv6cpOptionValueReset(PIPV6Context pContext);

#endif
