/*
** SellaNMS
** $Id: bgp.h,v 1.12 2005/05/15 05:21:17 sella Exp $
** Copyright (c) 2001-2005 Digital Genesis Software, LLC. All Rights Reserved.
** Released under the GPL Version 2 License.
** http://www.digitalgenesis.com
*/

#ifndef __DGS_MODULE_MONITOR_BGP_H
#define __DGS_MODULE_MONITOR_BGP_H

#ifdef HAVE_CONFIG_H
	#include "config.h"
#endif

#include "defaults.h"
#include "util.h"
#include "netblock.h"
#include "storagedata.h"
#include "policy_framework/policy_framework.h"
#include "../monitor.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stl/slist>
#include <stl/queue>

#define MODULE_MONITOR_BGP_ASN_DEFAULT			65535;
#define MODULE_MONITOR_BGP_PORT_DEFAULT		179
#define MODULE_MONITOR_BGP_VERSION_DEFAULT	4
#define MODULE_MONITOR_BGP_HOLDTIME_DEFAULT	90

#define BGP_MSG_MAX_SIZE							4096
#define BGP_TTL_MAX									255

#define BGP_HEADER_SIZE								19
#define BGP_OPEN_SIZE								10
#define BGP_NOTIFY_SIZE								2

/* BGP message types */
#define BGP_MSG_OPEN									1
#define BGP_MSG_UPDATE								2
#define BGP_MSG_NOTIFY								3
#define BGP_MSG_KEEPALIVE							4
#define BGP_MSG_ROUTE_REFRESH_01					5
#define BGP_MSG_ROUTE_REFRESH						128

/* BGP notify message codes.  */
#define BGP_NOTIFY_HEADER_ERR						1
#define BGP_NOTIFY_OPEN_ERR						2
#define BGP_NOTIFY_UPDATE_ERR						3
#define BGP_NOTIFY_HOLD_ERR						4
#define BGP_NOTIFY_FSM_ERR							5
#define BGP_NOTIFY_CEASE							6
#define BGP_NOTIFY_MAX								7

/* BGP_NOTIFY_HEADER_ERR sub codes.  */
#define BGP_NOTIFY_HEADER_NOT_SYNC				1
#define BGP_NOTIFY_HEADER_BAD_MESLEN			2
#define BGP_NOTIFY_HEADER_BAD_MESTYPE			3
#define BGP_NOTIFY_HEADER_MAX						4

/* BGP_NOTIFY_OPEN_ERR sub codes.  */
#define BGP_NOTIFY_OPEN_UNSUP_VERSION			1
#define BGP_NOTIFY_OPEN_BAD_PEER_AS				2
#define BGP_NOTIFY_OPEN_BAD_BGP_IDENT			3
#define BGP_NOTIFY_OPEN_UNSUP_PARAM				4
#define BGP_NOTIFY_OPEN_AUTH_FAILURE			5
#define BGP_NOTIFY_OPEN_UNACEP_HOLDTIME		6
#define BGP_NOTIFY_OPEN_UNSUP_CAPBL				7
#define BGP_NOTIFY_OPEN_MAX						8

/* BGP_NOTIFY_UPDATE_ERR sub codes.  */
#define BGP_NOTIFY_UPDATE_MAL_ATTR				1
#define BGP_NOTIFY_UPDATE_UNREC_ATTR			2
#define BGP_NOTIFY_UPDATE_MISS_ATTR				3
#define BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR		4
#define BGP_NOTIFY_UPDATE_ATTR_LENG_ERR		5
#define BGP_NOTIFY_UPDATE_INVAL_ORIGIN			6
#define BGP_NOTIFY_UPDATE_AS_ROUTE_LOOP		7
#define BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP		8
#define BGP_NOTIFY_UPDATE_OPT_ATTR_ERR			9
#define BGP_NOTIFY_UPDATE_INVAL_NETWORK		10
#define BGP_NOTIFY_UPDATE_MAL_AS_PATH			11
#define BGP_NOTIFY_UPDATE_MAX						12

/* BGP finite state machine status. */
#define BGP_STATE_IDLE								1
#define BGP_STATE_CONNECT							2
#define BGP_STATE_ACTIVE							3
#define BGP_STATE_OPENSENT							4
#define BGP_STATE_OPENCONFIRM						5
#define BGP_STATE_ESTABLISHED						6
#define BGP_STATE_BGP_STATUS_MAX					7

/* BGP finite state machine events. */
#define BGP_EVENT_START								1
#define BGP_EVENT_BGP_STOP							2
#define BGP_EVENT_TCP_CONNECTION_OPEN			3
#define BGP_EVENT_TCP_CONNECTION_CLOSED		4
#define BGP_EVENT_TCP_CONNECTION_OPEN_FAILED	5
#define BGP_EVENT_TCP_FATAL_ERROR				6
#define BGP_EVENT_CONNECTRETRY_TIMER_EXPIRED	7
#define BGP_EVENT_HOLD_TIMER_EXPIRED			8
#define BGP_EVENT_KEEPALIVE_TIMER_EXPIRED		9
#define BGP_EVENT_RECEIVE_OPEN_MSG				10
#define BGP_EVENT_RECEIVE_KEEPALIVE_MSG		11
#define BGP_EVENT_RECEIVE_UPDATE_MSG			12
#define BGP_EVENT_RECEIVE_NOTIFICATION_MSG	13
#define BGP_EVENT_BGP_EVENTS_MAX					14

typedef struct fsm_t {
	int state;					// Current State
	time_t connect_retry;	// ConnectRetry Timer
	time_t hold_time;			// Latest Keepalive
};

typedef struct bgp_t {
	int socket;
	unsigned long neighbor;
	unsigned long bgp_id;
	unsigned long port;
	unsigned long peer_as;
	unsigned long version;
	unsigned long hold_time;
	time_t last_keepalive;
	bool passive;	
};

typedef struct neighbor_t {
	fsm_t fsm;
	bgp_t bgp;
};

typedef struct update_t {
	in_addr neighbor;
	int network;
	int netmask;
	int next_hop;
	slist<int> aspath;
};

typedef slist<neighbor_t> neighbor_slist_t;
typedef queue<update_t> update_queue_t;

class BGP: public Monitor {
	public:
		BGP();
		~BGP();

	protected:

	private:
		virtual RESULT execute();
		virtual RESULT readConfig();

		RESULT readNeighborConfig(ConfigNode* node, bgp_t &neighbor, bgp_t &defaults);
		RESULT handle_packet(int s, u_int8_t *buf, int size);
		RESULT transmit_open(int s);
		RESULT transmit_update(int s);
		RESULT transmit_notify(int s);
		RESULT transmit_keepalive(int s);

		static RESULT fsm_thread(void *args);
		static RESULT storage_thread(void *args);

		slist<Netblock> allowed_neighbors;	/* Allowed BGP neighbors */
		neighbor_slist_t neighbors;			/* Established connections */

		pthread_mutex_t neighbor_mutex;
		pthread_mutex_t update_mutex;
};

#endif

/*
** Local Variables:
** c-basic-offset: 3
** tab-width: 3
** End:
** vim600: fdm=marker
** vim: noet ts=3 sw=3
*/
