/* 2103, Wed 16 May 01 (PST)

   LFAPMET.H:  GLobal declarations for LfapMet

   Copyright (C) 2001 by the Internet Next Generation project
                             http://ing.ctit.utwente.nl/WU5
   Author: Remco Poortinga, Telematics Institute

   NeTraMet Copyright (C) 1992-2002 by Nevil Brownlee,
   CAIDA | University of Auckland */


#ifndef LFAPMET_H_
#define LFAPMET_H_

/* some debug thingies */

#define LFAPMET_DEBUG_LEVEL 	6

#define LFAPMET_DBG_FUNC 		1	/* print function entries and exits */
#define LFAPMET_DBG_WARNINGS 	2	/* print warning messages			*/
#define LFAPMET_DBG_ERRORS 		4	/* print error messages				*/

#if (LFAPMET_DEBUG_LEVEL == 0)
# define debug(msg,lvl) { \
 }
#else
# define debug(msg,lvl) { \
 if ((LFAPMET_DEBUG_LEVEL & lvl)>0)	fprintf(stdout, msg); \
 }
#endif

 /* info level defines (set with -p option) */
#define LFAP_INFLVL_FLOW	 	1
#define LFAP_INFLVL_MSG		 	2
#define LFAP_INFLVL_LOGHEX	 	4
#define LFAP_INFLVL_FLOW_FILE	8
#define LFAP_INFLVL_MSG_FILE	16
#define LFAP_INFLVL_LOGHEX_FILE	32
 
 
/* All kinds of LFAP stuff */

typedef struct lfapheader
{
	Bit8		version;
    Bit8		opcode;
    Bit8		reserved;
    Bit8		status;
    Bit16		messageID;
    Bit16		messageLength;
} LFAPHeader;
#define LFAP_HEADER_SIZE ((int)8)

#define LFAP_VERSION	((Bit8)4)
/* LFAP Opcodes */

#define LFAP_OPCODE_NULL 	((Bit8) 0)
#define LFAP_OPCODE_VR	 	((Bit8) 1)
#define LFAP_OPCODE_VRA	 	((Bit8) 2)
#define LFAP_OPCODE_FAR	 	((Bit8) 3)
#define LFAP_OPCODE_FUN	 	((Bit8) 4)
#define LFAP_OPCODE_AR	 	((Bit8) 5)
#define LFAP_OPCODE_ARA		((Bit8) 6)

#define LFAP_OPCODE_MAX 	((Bit8) 6)


/* LFAP Status field */

#define LFAP_STATUS_SUCCESS ((Bit8) 1)
#define LFAP_STATUS_VERSION ((Bit8) 2)

#define LFAP_STATUS_MAX		((Bit8) 2)


/* Information Elements */
/* IEs are TLV (Type Length Value) */
typedef struct lfap_ie_header {
	Bit16	type;
	Bit16	length; /* excluding the 4 octet header */
} LFAP_IE_Header;
#define LFAP_IE_HEADER_SIZE ((int)4)

#define LFAP_IE_NULL				((Bit16) 0)
#define LFAP_IE_FLOW_ID				((Bit16) 1)
#define LFAP_IE_SOURCE_ADDRESS		((Bit16) 2)
#define LFAP_IE_DESTINATION_ADDRESS	((Bit16) 3)
#define LFAP_IE_FLOW_QUALIFIER		((Bit16) 4)
#define LFAP_IE_TIME				((Bit16) 5)
#define LFAP_IE_TYPE_OF_SERVICE		((Bit16) 6)
#define LFAP_IE_SOURCE_CCE_ADDRESS	((Bit16) 7)
#define LFAP_IE_CLIENT_DATA			((Bit16) 8)
#define LFAP_IE_COMMAND_CODE		((Bit16) 9)
#define LFAP_IE_FAS_IP_ADDRESS		((Bit16) 10)
#define LFAP_IE_FAILURE_CODE		((Bit16) 11)
#define LFAP_IE_FLOW_ID_PREFIX		((Bit16) 12)
#define LFAP_IE_FLOW_STATE			((Bit16) 13)
#define LFAP_IE_BYTE_COUNT_RUNNING	((Bit16) 14)
#define LFAP_IE_BYTE_COUNT_DELTA	((Bit16) 15)
#define LFAP_IE_PACKET_COUNT_RUNNING ((Bit16) 16)
#define LFAP_IE_PACKET_COUNT_DELTA	((Bit16) 17)
#define LFAP_IE_PROTOCOL_IDENTIFIER	((Bit16) 18)
#define LFAP_IE_SOURCE_PORT_UDP		((Bit16) 19)
#define LFAP_IE_SOURCE_PORT_TCP		((Bit16) 20)
#define LFAP_IE_SOURCE_PORT_IPX		((Bit16) 21)
#define LFAP_IE_MULTIPLE_RECORD		((Bit16) 22)
#define LFAP_IE_SRC_AND_DEST_AS		((Bit16) 23)
#define LFAP_IE_INGRESS_PORT		((Bit16) 24)
#define LFAP_IE_EGRESS_PORT			((Bit16) 25)

#define LFAP_IE_MAX					((Bit16) 25)

#define LFAP_FLOW_STATE_INACTIVE	((Bit32)1)
#define LFAP_FLOW_STATE_ACTIVE		((Bit32)2)


/* Command codes for the command code IE */

#define LFAP_CMD_RETURN_INDICATED_FLOWS	((Bit32) 1)
#define LFAP_CMD_RETURN_FLOW_PREFIX		((Bit32) 2)
#define LFAP_CMD_CONNECTION_ACCEPTED	((Bit32) 3)
#define LFAP_CMD_CONNECTION_REJECTED	((Bit32) 4)
#define LFAP_CMD_LIST_OF_FASS			((Bit32) 5)
#define LFAP_CMD_DISCONNECT				((Bit32) 6)
#define LFAP_CMD_KEEPALIVE				((Bit32) 7)

#define LFAP_CMD_MAX					((Bit32) 7)


#define LFAP_PORT	3145

/* for LfapMet */

#define LFAP_MAX_ADDR_LEN		20
#define LFAP_MAX_PROTOCOL_LEN	20

/*
for 64 bit values (Packets_recvd, etc.):
element [0] contains hi value
element [1] contains lo value
*/

typedef struct v64
{
	Bit32 hi;
	Bit32 lo;
} val64;

typedef struct flowstats_s
{
	val64	fasPrefix;			/* FAS prefix */
	Bit32	flowID;				/* flowID */
	Bit32	flowState;			/* LFAP_FLOW_STATE_(IN)ACTIVE */
	/* both times as SNMPv2 timestamp */
	Bit32	firstTime;			/* first timeIE received for this flow */
	Bit32	lastTime;			/* latest time IE received for this flow */
	Bit32	diffTime;			/* time difference between a CCE and LfapMet */
	val64	dPackets_sent;		/* delta Packets sent */
	val64	dPackets_recvd;		/* delta Packets received */
	val64	dOctets_sent;		/* delta octets sent */
	val64	dOctets_recvd;		/* delta octets received */
	val64	Packets_sent;		/* total Packets sent */
	val64	Packets_recvd;		/* total Packets received */
	val64	Octets_sent;		/* total octets sent */
	val64	Octets_recvd;		/* total octets received */

    unsigned char	src_addr[LFAP_MAX_ADDR_LEN];
    Bit16	src_fam;
    Bit16	src_len;
    unsigned char	dest_addr[LFAP_MAX_ADDR_LEN];
    Bit16	dest_fam;
    Bit16	dest_len;
    Bit16	src_port;
    Bit16	src_port_type;
    Bit16	dst_port;
    Bit16	dst_port_type;
    unsigned char	protDirId[LFAP_MAX_PROTOCOL_LEN];
	Bit8	protocol;
    Bit32	tos;
    unsigned char	src_cce_addr[LFAP_MAX_ADDR_LEN];
    Bit16	src_cce_fam;
    Bit16	src_cce_len;
    Bit16	src_as;
    Bit16	dest_as;
    Bit16	ingress_port;
    Bit16	egress_port;
    Bit16	cxn_priority;
int changed_b; /* set to 1 if changed, back to 0 after processing */
} LFAPFlowStats;


/* do some structs and defines for a complete LFAP message */

typedef struct fas_info_s
{
	int				conn;		/* connection (socket number) 				*/
	LFAPHeader*		lfap_msg;	/* pointer the current recvd LFAP message	*/
	LFAPFlowStats** fs_pp;		/* pointer to pointers to FlowStats structs	*/
	int				fs_len;		/* number of pointers to flowstats			*/
	Bit16			msgID;		/* message ID for sending messages			*/
	void*			buf;		/* buffer for receiving	messages			*/
	int				bufsize;	/* length of buffer 						*/
	void*			recvptr;	/* ptr in buf for receiving					*/
	unsigned long	npackets;	/* total packet count from last stats reset */
	int 			ticks;		/* number of ticks (for KEEPALIVES) 		*/
	int				guesstimate;/* is set to 1 (TRUE) if the time difference*/
								/* between the FAS (LfapMet) and the CCE	*/
								/* has to be 'guesstimated' using the 		*/
								/* local arrival time of FAR messages		*/
	Bit32			diffTime;	/* used if we KNOW the difference in uptime */
} FASInfo;

#define LFAP_RECEIVE_BUF_SIZE 1024

/* function prototypes */


void 			dumphex(void* buf, int len);
void 			dumpMessage1(FILE* out, LFAPHeader* lfap, char* header);
void 			dumpMessage(LFAPHeader* lfap, char* header);
void 			formatDuration(char* dst,Bit32 uptime);
void 			dumpFlowStats1(LFAPFlowStats* fs, FILE* out);
void 			dumpFlowStats(LFAPFlowStats* fs);
int 			isCompleteMessage(void* buf, int len);
LFAPHeader* 	copyRawLFAPMessage(LFAPHeader* lfapsrc_p);
Bit16 			getIEType(LFAP_IE_Header* ie);
Bit16 			getIELengthIncl(LFAP_IE_Header* ie);
Bit16 			getIELengthExcl(LFAP_IE_Header* ie);
Bit16 			getLFAPMessageLengthExcl(LFAPHeader* lfap);
Bit16 			getLFAPMessageLengthIncl(LFAPHeader* lfap);
LFAPHeader* 	copyLFAPMessage(LFAPHeader* lfapsrc_p);
LFAP_IE_Header* getFirstIE(LFAPHeader* lfap);
LFAP_IE_Header* getNextIE(void* start_ptr, LFAP_IE_Header* ie, int max_offset);
void 			getIEDoubleDword(LFAP_IE_Header* ie, int offset, val64* result);
Bit32 			getIEDword(LFAP_IE_Header* ie, int offset);
Bit16 			getIEWord(LFAP_IE_Header* ie, int offset);
Bit8 			getIEByte(LFAP_IE_Header* ie, int offset);
LFAP_IE_Header* expandMultipleRecordIE(LFAP_IE_Header* mrie, int* newlen);
Bit8 			getLFAPOpcode(LFAPHeader* lfap);
Bit8 			getLFAPVersion(LFAPHeader* lfap);
Bit8			getLFAPStatus(LFAPHeader* lfap);
Bit16			getLFAPMessageID(LFAPHeader* lfap);
void			addIE(LFAPHeader** lfap, void* ie);
void 			addIEBlock(LFAPHeader** lfap, void* ie, int size);
void 			normalizeHeaders(LFAPHeader** lfap);
void 			denormalizeHeaders(LFAPHeader* lfap);
int 			handleError();
void 			processGenericFlowIEs( LFAPFlowStats* fs,
							LFAP_IE_Header* ie,
							unsigned long *npkts);
void 			sub64(val64* res, val64 orig, val64 min);
void 			add64(val64* res, val64 orig, val64 pls);
void 			sendKeepAlive(FASInfo *fasinfo);
void 			handleCMD_RFP(FASInfo* fasinfo);
void 			handleCMD_LOF(FASInfo* fasinfo);
void 			sendLFAPMessage(LFAPHeader* lfap, int conn);
Bit16 			newMessageId(FASInfo* fasinfo);
LFAPHeader* 	newLFAPMessage(
							Bit8 opcode,
							Bit8 status,
							Bit16 messageID
						  );
LFAP_IE_Header* newIE(Bit16 type, Bit16 length);
void 			putIEDword(LFAP_IE_Header* ie, Bit32 value, int offset);
void 			putIEWord(LFAP_IE_Header* ie, Bit16 value, int offset);

#endif /* LFAPMET_H_ */
