text: // SoftEther VPN Source Code - Developer Edition Master Branch
  // Cedar Communication Module
  
  
  // Proto_IKE.h
  // Header of Proto_IKE.c
  
  #ifndef	PROTO_IKE_H
  #define	PROTO_IKE_H
  
  //// Macro
  
  //// Constants
  
  // State
  #define	IKE_SA_MAIN_MODE					0	// Main mode
  #define	IKE_SA_AGGRESSIVE_MODE				1	// Aggressive mode
  
  #define	IKE_SA_MM_STATE_1_SA				0	// Main mode state 1 (SA exchange is complete. Wait for key exchange)
  #define	IKE_SA_MM_STATE_2_KEY				1	// Main mode state 2 (Key exchange is complete. Wait for exchange ID)
  #define	IKE_SA_MM_STATE_3_ESTABLISHED		2	// Main mode state 3 (ID exchange is complete. Established)
  
  #define	IKE_SA_AM_STATE_1_SA				0	// Aggressive mode state 1 (SA exchange is completed. Wait for hash)
  #define	IKE_SA_AM_STATE_2_ESTABLISHED		1	// Aggressive mode state 2 (Hash exchange is completed. Established)
  
  #define	IKE_SA_RESEND_INTERVAL				(2 * 1000)	// IKE SA packet retransmission interval
  #define	IKE_SA_RAND_SIZE					16	// Size of the random number
  
  // ESP
  #define	IKE_ESP_HASH_SIZE					12	// The hash size for the ESP packet
  
  // Type of UDP packet
  #define	IKE_UDP_TYPE_ISAKMP					0	// ISAKMP packet (destination 500)
  #define	IKE_UDP_TYPE_ESP					1	// ESP packet (destination 4500)
  #define	IKE_UDP_KEEPALIVE					2	// KeepAlive packet
  #define	IKE_UDP_SPECIAL						3	// Special packet
  
  // String for Vendor ID
  #define	IKE_VENDOR_ID_RFC3947_NAT_T			"0x4a131c81070358455c5728f20e95452f"
  #define	IKE_VENDOR_ID_IPSEC_NAT_T_IKE_03	"0x7d9419a65310ca6f2c179d9215529d56"
  #define	IKE_VENDOR_ID_IPSEC_NAT_T_IKE_02	"0x90cb80913ebb696e086381b5ec427b1f"
  #define	IKE_VENDOR_ID_IPSEC_NAT_T_IKE_02_2	"0xcd60464335df21f87cfdb2fc68b6a448"
  #define	IKE_VENDOR_ID_IPSEC_NAT_T_IKE_00	"0x4485152d18b6bbcd0be8a8469579ddcc"
  #define	IKE_VENDOR_ID_RFC3706_DPD			"0xafcad71368a1f1c96b8696fc77570100"
  #define	IKE_VENDOR_ID_MICROSOFT_L2TP		"0x4048b7d56ebce88525e7de7f00d6c2d3"
  #define	IKE_VENDOR_ID_MS_NT5_ISAKMPOAKLEY	"0x1e2b516905991c7d7c96fcbfb587e461"
  #define	IKE_VENDOR_ID_MS_VID_INITIALCONTACT	"0x26244d38eddb61b3172a36e3d0cfb819"
  
  // Quota
  #define	IKE_QUOTA_MAX_NUM_CLIENTS_PER_IP	1000			// The number of IKE_CLIENT per IP address
  #define	IKE_QUOTA_MAX_NUM_CLIENTS			30000			// Limit number of IKE_CLIENT
  #define	IKE_QUOTA_MAX_SA_PER_CLIENT			100				// The limit number of SA for each IKE_CLIENT
  
  // Time-out
  #define	IKE_TIMEOUT_FOR_IKE_CLIENT			150000			// IKE_CLIENT non-communication disconnect time
  #define	IKE_TIMEOUT_FOR_IKE_CLIENT_FOR_NOT_ESTABLISHED		10000 // IKE_CLIENT non-communication disconnect time (connection incomplete)
  #define	IKE_INTERVAL_UDP_KEEPALIVE			5000			// UDP KeepAlive transmission interval
  #define	IKE_QUICKMODE_START_INTERVAL		2000			// QuickMode start interval
  #define	IKE_QUICKMODE_FAILED_TIMEOUT		10000			// Maximum time to tolerant that to fail to establish a QuickMode
  #define	IKE_INTERVAL_DPD_KEEPALIVE			10000			// DPD KeepAlive transmission interval
  
  // Expiration margin
  #define	IKE_SOFT_EXPIRES_MARGIN				1000			// Expiration margin
  
  
  //// Type
  
  // IKE SA transform data
  struct IKE_SA_TRANSFORM_SETTING
  {
  	IKE_CRYPTO *Crypto;
  	UINT CryptoKeySize;
  	IKE_HASH *Hash;
  	IKE_DH *Dh;
  	UINT CryptoId;
  	UINT HashId;
  	UINT DhId;
  	UINT LifeKilobytes;
  	UINT LifeSeconds;
  };
  
  // IPsec SA transforms data
  struct IPSEC_SA_TRANSFORM_SETTING
  {
  	IKE_CRYPTO *Crypto;
  	UINT CryptoKeySize;
  	IKE_HASH *Hash;
  	IKE_DH *Dh;
  	UINT CryptoId;
  	UINT HashId;
  	UINT DhId;
  	UINT LifeKilobytes;
  	UINT LifeSeconds;
  	UINT SpiServerToClient;
  	UINT CapsuleMode;
  	bool OnlyCapsuleModeIsInvalid;
  };
  
  // Function support information
  struct IKE_CAPS
  {
  	// Support Information
  	bool NatTraversalRfc3947;		// RFC 3947 Negotiation of NAT-Traversal in the IKE
  	bool NatTraversalDraftIetf;		// draft-ietf-ipsec-nat-t-ike
  	bool DpdRfc3706;				// RFC 3706 A Traffic-Based Method of Detecting Dead Internet Key Exchange (IKE) Peers
  	bool MS_L2TPIPSecVPNClient;		// Vendor ID: Microsoft L2TP/IPSec VPN Client
  	bool MS_NT5_ISAKMP_OAKLEY;		// Vendor ID: MS NT5 ISAKMPOAKLEY
  	bool MS_Vid_InitialContact;		// Vendor ID: Microsoft Vid-Initial-Contact
  
  	// Use information
  	bool UsingNatTraversalRfc3947;
  	bool UsingNatTraversalDraftIetf;
  };
  
  // IKE / IPsec client
  struct IKE_CLIENT
  {
  	UINT Id;
  	IP ClientIP;
  	UINT ClientPort;
  	IP ServerIP;
  	UINT ServerPort;
  	IKE_SA *CurrentIkeSa;						// IKE SA to be used currently
  	IPSECSA *CurrentIpSecSaRecv;				// IPsec SA to be used currently (receive direction)
  	IPSECSA *CurrentIpSecSaSend;				// IPsec SA to be currently in use (transmit direction)
  	UINT64 FirstCommTick;						// Time the first data communication
  	UINT64 LastCommTick;						// Time that made the last communication (received data) time
  	bool Deleting;								// Deleting
  	UINT64 NextKeepAliveSendTick;				// Time to send the next KeepAlive
  	UINT64 NextDpdSendTick;						// Time to send the next DPD
  	UINT DpdSeqNo;								// DPD sequence number
  	char ClientId[128];							// ID presented by the client
  	char Secret[MAX_SIZE];						// Secret value of the authentication is successful
  
  	bool IsMicrosoft;							// Whether the client is Microsoft's
  
  	IPSEC_SA_TRANSFORM_SETTING CachedTransformSetting;	// Cached transform attribute value
  	UINT64 CurrentExpiresSoftTick_StoC;			// The maximum value of the flexible expiration date of the current (server -> client)
  	UINT64 CurrentExpiresSoftTick_CtoS;			// The maximum value of the flexible expiration date of the current (client -> server)
  	UINT CurrentNumEstablishedIPsecSA_StoC;		// The number of IPsec SA currently active (server -> client)
  	UINT CurrentNumEstablishedIPsecSA_CtoS;		// The number of IPsec SA currently active (client -> server)
  	UINT CurrentNumHealtyIPsecSA_CtoS;			// The number of currently available IPsec SA which expiration well within (client -> server)
  	UINT CurrentNumHealtyIPsecSA_StoC;			// The number of currently available IPsec SA which expiration well within (server -> client)
  	bool SendID1andID2;							// Whether to send the ID in QM
  	UCHAR SendID1_Type, SendID2_Type;
  	UCHAR SendID1_Protocol, SendID2_Protocol;
  	USHORT SendID1_Port, SendID2_Port;
  	BUF *SendID1_Buf, *SendID2_Buf;
  	bool SendNatOaDraft1, SendNatOaDraft2, SendNatOaRfc;	// Whether to send the NAT-OA in QM
  	bool StartQuickModeAsSoon;					// Flag to indicate to the start of the Quick Mode as soon as possible
  	UINT64 LastQuickModeStartTick;				// Time which the last QuickMode started
  	UINT64 NeedQmBeginTick;						// Time which a start-up of QuickMode is required
  
  	// L2TP related
  	L2TP_SERVER *L2TP;							// L2TP server
  	UINT L2TPClientPort;						// Client-side port number of L2TP
  	IP L2TPServerIP, L2TPClientIP;				// IP address used by the L2TP processing
  	bool IsL2TPOnIPsecTunnelMode;				// Whether the L2TP is working on IPsec tunnel mode
  
  	// EtherIP related
  	ETHERIP_SERVER *EtherIP;					// EtherIP server
  	bool IsEtherIPOnIPsecTunnelMode;			// Whether the EtherIP is working on IPsec tunnel mode
  
  	// Transport mode related
  	IP TransportModeServerIP;
  	IP TransportModeClientIP;
  	bool ShouldCalcChecksumForUDP;				// Flag to calculate the checksum for the UDP packet
  
  	// Tunnel mode related
  	IP TunnelModeServerIP;						// Server-side internal IP address
  	IP TunnelModeClientIP;						// Client-side internal IP address
  	USHORT TunnelSendIpId;						// ID of the transmission IP header
  };
  
  // IKE SA
  struct IKE_SA
  {
  	UINT Id;
  	IKE_CLIENT *IkeClient;						// Pointer to the IKE client
  	UINT64 InitiatorCookie, ResponderCookie;	// Cookie
  	UINT Mode;									// Mode
  	UINT State;									// State
  	BUF *SendBuffer;							// Buffer during transmission
  	UINT64 NextSendTick;						// Next transmission time
  	UINT64 FirstCommTick;						// Time that the first data communication
  	UINT64 EstablishedTick;						// Time that the SA has been established
  	UINT64 LastCommTick;						// Time that made the last communication (received data) time
  	IKE_SA_TRANSFORM_SETTING TransformSetting;	// Transform Configuration
  	IKE_CAPS Caps;								// IKE Caps
  	BUF *InitiatorRand, *ResponderRand;			// Random number
  	BUF *DhSharedKey;							// DH common key
  	BUF *GXi, *GXr;								// DH exchange data
  	BUF *SAi_b;									// Data needed for authentication
  	BUF *YourIDPayloadForAM;					// Copy the ID payload of the client-side
  	UCHAR SKEYID[IKE_MAX_HASH_SIZE];			// Key set
  	UCHAR SKEYID_d[IKE_MAX_HASH_SIZE];
  	UCHAR SKEYID_a[IKE_MAX_HASH_SIZE];
  	UCHAR SKEYID_e[IKE_MAX_HASH_SIZE];
  	UCHAR InitiatorHashForAM[IKE_MAX_HASH_SIZE];
  	IKE_CRYPTO_KEY *CryptoKey;					// Common encryption key
  	UINT HashSize;								// Hash size
  	UINT KeySize;								// Key size
  	UINT BlockSize;								// Block size
  	UCHAR Iv[IKE_MAX_BLOCK_SIZE];				// IV
  	bool IsIvExisting;							// Whether an IV exists
  	bool Established;							// Established flag
  	bool Deleting;								// Deleting
  	UINT NumResends;							// The number of retransmissions
  	char Secret[MAX_SIZE];						// Secret value of the authentication is successful
  };
  
  // IPsec SA
  struct IPSECSA
  {
  	UINT Id;
  	IKE_CLIENT *IkeClient;						// Pointer to the IKE client
  	IKE_SA *IkeSa;								// Pointer to IKE_SA to use for transmission
  	UCHAR Iv[IKE_MAX_BLOCK_SIZE];				// IV used in the Quick Mode exchange
  	bool IsIvExisting;							// Whether the IV exists
  	UINT MessageId;								// Message ID used in Quick Mode exchange
  	UINT Spi;									// SPI
  	UINT CurrentSeqNo;							// Send sequence number
  	BUF *SendBuffer;							// Buffer during transmission
  	UINT NumResends;							// The number of retransmissions
  	UINT64 NextSendTick;						// Next transmission date and time
  	UINT64 FirstCommTick;						// Time the last data sent
  	UINT64 EstablishedTick;						// Time that the SA has been established
  	UINT64 LastCommTick;						// Time that made the last communication (received data) time
  	UINT64 ExpiresHardTick;						// Exact expiration time
  	UINT64 ExpiresSoftTick;						// Flexible expiration time
  	UINT64 TotalSize;							// Size sent to and received
  	IPSEC_SA_TRANSFORM_SETTING TransformSetting;	// Transform Configuration
  	bool ServerToClient;						// Whether is upload direction
  	IPSECSA *PairIPsecSa;						// IPsec SA that are paired
  	bool Established;							// Established flag
  	BUF *InitiatorRand, *ResponderRand;			// Random number
  	BUF *SharedKey;								// PFS shared key
  	UCHAR Hash3[IKE_MAX_HASH_SIZE];				// Hash 3
  	UCHAR KeyMat[IKE_MAX_KEY_SIZE + IKE_MAX_HASH_SIZE];	// Encryption key
  	UCHAR HashKey[IKE_MAX_HASH_SIZE];			// Hash key
  	IKE_CRYPTO_KEY *CryptoKey;					// Key data
  	bool Deleting;								// Deleting
  	UCHAR EspIv[IKE_MAX_BLOCK_SIZE];			// IV for ESP communication
  	bool Initiated;								// The server-side is initiator
  	DH_CTX *Dh;									// DH (only if the server-side is initiator)
  	bool StartQM_FlagSet;						// Whether the flag to indicate to do the QM is set to the IKE_CLIENT
  	UCHAR SKEYID_d[IKE_MAX_HASH_SIZE];
  	UCHAR SKEYID_a[IKE_MAX_HASH_SIZE];
  	IKE_HASH *SKEYID_Hash;
  };
  
  // IKE server
  struct IKE_SERVER
  {
  	CEDAR *Cedar;
  	IPSEC_SERVER *IPsec;
  	UINT64 Now;									// Current time
  	LIST *SendPacketList;						// Transmission packet
  	INTERRUPT_MANAGER *Interrupts;				// Interrupt manager
  	SOCK_EVENT *SockEvent;						// SockEvent
  	IKE_ENGINE *Engine;							// Encryption engine
  	LIST *ClientList;							// Client list
  	LIST *IkeSaList;							// SA list
  	LIST *IPsecSaList;							// IPsec SA list
  	LIST *ThreadList;							// L2TP thread list
  	bool StateHasChanged;						// Flag whether the state has changed
  	UINT CurrentIkeSaId, CurrentIPsecSaId, CurrentIkeClientId, CurrentEtherId;	// Serial number ID
  
  	// Setting data
  	char Secret[MAX_SIZE];						// Pre-shared key
  };
  
  
  //// Function prototype
  IKE_SERVER *NewIKEServer(CEDAR *cedar, IPSEC_SERVER *ipsec);
  void FreeIKEServer(IKE_SERVER *ike);
  void SetIKEServerSockEvent(IKE_SERVER *ike, SOCK_EVENT *e);
  void ProcIKEPacketRecv(IKE_SERVER *ike, UDPPACKET *p);
  void StopIKEServer(IKE_SERVER *ike);
  void ProcessIKEInterrupts(IKE_SERVER *ike);
  IKE_PACKET *ParseIKEPacketHeader(UDPPACKET *p);
  void ProcIkeMainModePacketRecv(IKE_SERVER *ike, UDPPACKET *p, IKE_PACKET *header);
  void ProcIkeQuickModePacketRecv(IKE_SERVER *ike, UDPPACKET *p, IKE_PACKET *header);
  void ProcIkeAggressiveModePacketRecv(IKE_SERVER *ike, UDPPACKET *p, IKE_PACKET *header);
  void ProcIkeInformationalExchangePacketRecv(IKE_SERVER *ike, UDPPACKET *p, IKE_PACKET *header);
  void FreeIkeSa(IKE_SA *sa);
  void FreeIkeClient(IKE_SERVER *ike, IKE_CLIENT *c);
  UINT64 GenerateNewResponserCookie(IKE_SERVER *ike);
  bool GetBestTransformSettingForIkeSa(IKE_SERVER *ike, IKE_PACKET *pr, IKE_SA_TRANSFORM_SETTING *setting);
  bool TransformPayloadToTransformSettingForIkeSa(IKE_SERVER *ike, IKE_PACKET_TRANSFORM_PAYLOAD *transform, IKE_SA_TRANSFORM_SETTING *setting);
  IKE_CLIENT *SearchIkeClientForIkePacket(IKE_SERVER *ike, IP *client_ip, UINT client_port, IP *server_ip, UINT server_port, IKE_PACKET *pr);
  IKE_CLIENT *SearchOrCreateNewIkeClientForIkePacket(IKE_SERVER *ike, IP *client_ip, UINT client_port, IP *server_ip, UINT server_port, IKE_PACKET *pr);
  UINT GetNumberOfIkeClientsFromIP(IKE_SERVER *ike, IP *client_ip);
  UINT GetNumberOfIPsecSaOfIkeClient(IKE_SERVER *ike, IKE_CLIENT *c);
  UINT GetNumberOfIkeSaOfIkeClient(IKE_SERVER *ike, IKE_CLIENT *c);
  int CmpIkeClient(void *p1, void *p2);
  int CmpIkeSa(void *p1, void *p2);
  int CmpIPsecSa(void *p1, void *p2);
  IKE_SA *FindIkeSaByEndPointAndInitiatorCookie(IKE_SERVER *ike, IP *client_ip, UINT client_port, IP *server_ip, UINT server_port, UINT64 init_cookie, UINT mode);
  IKE_SA *FindIkeSaByResponderCookie(IKE_SERVER *ike, UINT64 responder_cookie);
  IKE_SA *FindIkeSaByResponderCookieAndClient(IKE_SERVER *ike, UINT64 responder_cookie, IKE_CLIENT *c);
  IKE_CLIENT *NewIkeClient(IKE_SERVER *ike, IP *client_ip, UINT client_port, IP *server_ip, UINT server_port);
  IKE_CLIENT *SetIkeClientEndpoint(IKE_SERVER *ike, IKE_CLIENT *c, IP *client_ip, UINT client_port, IP *server_ip, UINT server_port);
  IKE_SA *NewIkeSa(IKE_SERVER *ike, IKE_CLIENT *c, UINT64 init_cookie, UINT mode, IKE_SA_TRANSFORM_SETTING *setting);
  IKE_PACKET_PAYLOAD *TransformSettingToTransformPayloadForIke(IKE_SERVER *ike, IKE_SA_TRANSFORM_SETTING *setting);
  void IkeSaSendPacket(IKE_SERVER *ike, IKE_SA *sa, IKE_PACKET *p);
  IKE_PACKET *IkeSaRecvPacket(IKE_SERVER *ike, IKE_SA *sa, void *data, UINT size);
  void IkeSendUdpPacket(IKE_SERVER *ike, UINT type, IP *server_ip, UINT server_port, IP *client_ip, UINT client_port, void *data, UINT size);
  void IkeAddVendorIdPayloads(IKE_PACKET *p);
  BUF *IkeStrToVendorId(char *str);
  void IkeAddVendorId(IKE_PACKET *p, char *str);
  bool IkeIsVendorIdExists(IKE_PACKET *p, char *str);
  void IkeCheckCaps(IKE_CAPS *caps, IKE_PACKET *p);
  BUF *IkeCalcNatDetectHash(IKE_SERVER *ike, IKE_HASH *hash, UINT64 initiator_cookie, UINT64 responder_cookie, IP *ip, UINT port);
  void IkeCalcSaKeySet(IKE_SERVER *ike, IKE_SA *sa, char *secret);
  IKE_CRYPTO_KEY *IkeNewCryptoKeyFromK(IKE_SERVER *ike, void *k, UINT k_size, IKE_HASH *h, IKE_CRYPTO *c, UINT crypto_key_size);
  BUF *IkeExpandKeySize(IKE_HASH *h, void *k, UINT k_size, UINT target_size);
  void IkeSaUpdateIv(IKE_SA *sa, void *iv, UINT iv_size);
  IPSECSA *NewIPsecSa(IKE_SERVER *ike, IKE_CLIENT *c, IKE_SA *ike_sa, bool initiate, UINT message_id, bool server_to_client, void *iv, UINT spi, void *init_rand_data, UINT init_rand_size, void *res_rand_data, UINT res_rand_size, IPSEC_SA_TRANSFORM_SETTING *setting, void *shared_key_data, UINT shared_key_size);
  void IkeCalcPhase2InitialIv(void *iv, IKE_SA *sa, UINT message_id);
  bool GetBestTransformSettingForIPsecSa(IKE_SERVER *ike, IKE_PACKET *pr, IPSEC_SA_TRANSFORM_SETTING *setting, IP *server_ip);
  bool TransformPayloadToTransformSettingForIPsecSa(IKE_SERVER *ike, IKE_PACKET_TRANSFORM_PAYLOAD *transform, IPSEC_SA_TRANSFORM_SETTING *setting, IP *server_ip);
  IKE_PACKET_PAYLOAD *TransformSettingToTransformPayloadForIPsec(IKE_SERVER *ike, IPSEC_SA_TRANSFORM_SETTING *setting);
  UINT GenerateNewIPsecSaSpi(IKE_SERVER *ike, UINT counterpart_spi);
  IPSECSA *SearchClientToServerIPsecSaBySpi(IKE_SERVER *ike, UINT spi);
  IPSECSA *SearchIPsecSaBySpi(IKE_SERVER *ike, IKE_CLIENT *c, UINT spi);
  IPSECSA *SearchIPsecSaByMessageId(IKE_SERVER *ike, IKE_CLIENT *c, UINT message_id);
  void IPsecSaSendPacket(IKE_SERVER *ike, IPSECSA *sa, IKE_PACKET *p);
  IKE_PACKET *IPsecSaRecvPacket(IKE_SERVER *ike, IPSECSA *sa, void *data, UINT size);
  void IPsecSaUpdateIv(IPSECSA *sa, void *iv, UINT iv_size);
  void ProcDeletePayload(IKE_SERVER *ike, IKE_CLIENT *c, IKE_PACKET_DELETE_PAYLOAD *d);
  void MarkIPsecSaAsDeleted(IKE_SERVER *ike, IPSECSA *sa);
  void MarkIkeSaAsDeleted(IKE_SERVER *ike, IKE_SA *sa);
  void PurgeDeletingSAsAndClients(IKE_SERVER *ike);
  void PurgeIPsecSa(IKE_SERVER *ike, IPSECSA *sa);
  void PurgeIkeSa(IKE_SERVER *ike, IKE_SA *sa);
  void PurgeIkeClient(IKE_SERVER *ike, IKE_CLIENT *c);
  void FreeIPsecSa(IPSECSA *sa);
  void MarkIkeClientAsDeleted(IKE_SERVER *ike, IKE_CLIENT *c);
  IKE_SA *GetOtherLatestIkeSa(IKE_SERVER *ike, IKE_SA *sa);
  IPSECSA *GetOtherLatestIPsecSa(IKE_SERVER *ike, IPSECSA *sa);
  void SendInformationalExchangePacket(IKE_SERVER *ike, IKE_CLIENT *c, IKE_PACKET_PAYLOAD *payload);
  void SendInformationalExchangePacketEx(IKE_SERVER *ike, IKE_CLIENT *c, IKE_PACKET_PAYLOAD *payload, bool force_plain, UINT64 init_cookie, UINT64 resp_cookie);
  void SendDeleteIkeSaPacket(IKE_SERVER *ike, IKE_CLIENT *c, UINT64 init_cookie, UINT64 resp_cookie);
  void SendDeleteIPsecSaPacket(IKE_SERVER *ike, IKE_CLIENT *c, UINT spi);
  void IPsecCalcKeymat(IKE_SERVER *ike, IKE_HASH *h, void *dst, UINT dst_size, void *skeyid_d_data, UINT skeyid_d_size, UCHAR protocol, UINT spi, void *rand_init_data, UINT rand_init_size,
  					 void *rand_resp_data, UINT rand_resp_size, void *df_key_data, UINT df_key_size);
  
  void ProcIPsecEspPacketRecv(IKE_SERVER *ike, UDPPACKET *p);
  void ProcIPsecUdpPacketRecv(IKE_SERVER *ike, IKE_CLIENT *c, UCHAR *data, UINT data_size);
  void IPsecSendPacketByIPsecSa(IKE_SERVER *ike, IPSECSA *sa, UCHAR *data, UINT data_size, UCHAR protocol_id);
  void IPsecSendPacketByIPsecSaInner(IKE_SERVER *ike, IPSECSA *sa, UCHAR *data, UINT data_size, UCHAR protocol_id);
  void IPsecSendPacketByIkeClient(IKE_SERVER *ike, IKE_CLIENT *c, UCHAR *data, UINT data_size, UCHAR protocol_id);
  void IPsecSendUdpPacket(IKE_SERVER *ike, IKE_CLIENT *c, UINT src_port, UINT dst_port, UCHAR *data, UINT data_size);
  void IPsecIkeClientManageL2TPServer(IKE_SERVER *ike, IKE_CLIENT *c);
  void IPsecIkeClientSendL2TPPackets(IKE_SERVER *ike, IKE_CLIENT *c, L2TP_SERVER *l2tp);
  void IPsecIkeSendUdpForDebug(UINT dst_port, UINT dst_ip, void *data, UINT size);
  void StartQuickMode(IKE_SERVER *ike, IKE_CLIENT *c);
  UINT GenerateNewMessageId(IKE_SERVER *ike);
  
  void IPsecIkeClientManageEtherIPServer(IKE_SERVER *ike, IKE_CLIENT *c);
  void IPsecIkeClientSendEtherIPPackets(IKE_SERVER *ike, IKE_CLIENT *c, ETHERIP_SERVER *s);
  void ProcIPsecEtherIPPacketRecv(IKE_SERVER *ike, IKE_CLIENT *c, UCHAR *data, UINT data_size, bool is_tunnel_mode);
  bool IsIPsecSaTunnelMode(IPSECSA *sa);
  void ProcL2TPv3PacketRecv(IKE_SERVER *ike, IKE_CLIENT *c, UCHAR *data, UINT data_size, bool is_tunnel_mode);
  
  IKE_SA *SearchIkeSaByCookie(IKE_SERVER *ike, UINT64 init_cookie, UINT64 resp_cookie);
  
  #endif	// PROTO_IKE_H
  
  