/************************************************************************/
/*	Routing Protocol Simulator	Relese 1.0	1994/3/17	*/
/*									*/
/*		module 	: protocol procedure				*/
/*		file	: bgp_proc.c			       		*/
/*									*/
/*   Copyright (c) 1994 by Systems Development Laboratory Hitachi,Ltd.	*/
/*   All rights reserved.						*/
/*----------------------------------------------------------------------*/
/*	UPDATE HISTORY							*/
/*									*/
/************************************************************************/
static char copyright[]=
  "@(#)Copyright (c) 1994 by Systems Development Laboratory Hitachi,Ltd.\n All rights researved.\n";

#include "rps.h"
#include "rps_bgp.h"
#include "router.h"

void bgp_message_send();
void ospf_message_send();
void ospf_message_recv();
void ospf_nbr_state_adjok();
void ospf_if_state_nbrchange();
void ospf_nbr_state_loading();

extern struct RT_CONF *router_search();
extern FILE *get_trace_fp();
extern char *get_rt_table();

int state_idle[]=
{BGP_EVENT_NOTHING,BGP_EVENT_NOTHING,BGP_EVENT_START,BGP_EVENT_NOTHING,
   BGP_EVENT_NOTHING,BGP_EVENT_NOTHING,BGP_EVENT_NOTHING};

int state_conncect[]=
{BGP_EVENT_NOTHING,BGP_EVENT_NOTHING,BGP_EVENT_START,BGP_EVENT_OPENFAIL,
   BGP_EVENT_OPEN,BGP_EVENT_NOTHING,BGP_EVENT_NOTHING};

int state_active[]=
{BGP_EVENT_NOTHING,BGP_EVENT_NOTHING,BGP_EVENT_CONNECTRETRY,BGP_EVENT_OPENFAIL,
   BGP_EVENT_OPEN,BGP_EVENT_NOTHING,BGP_EVENT_NOTHING};

int state_opensent[]=
{BGP_EVENT_NOTHING,BGP_EVENT_NOTHING,BGP_EVENT_NOTHING,BGP_EVENT_CLOSE,
   BGP_EVENT_NOTHING,BGP_EVENT_RECVOPEN,BGP_EVENT_NOTHING};

int state_openconfirm[]=
{BGP_EVENT_NOTHING,BGP_EVENT_NOTHING,BGP_EVENT_NOTHING,BGP_EVENT_NOTHING,
   BGP_EVENT_KEEPALIVE,BGP_EVENT_NOTHING,BGP_EVENT_RECVKEEPALIVE};

int state_establisth[]=
{BGP_EVENT_NOTHING,BGP_EVENT_NOTHING,BGP_EVENT_NOTHING,BGP_EVENT_NOTHING,
   BGP_EVENT_NOTHING,BGP_EVENT_NOTHING,BGP_EVENT_RECVUPDATE};
    
/*

  bgp_meesage_send

*/
void bgp_message_send(bgp,type)
struct proto_bgp *bgp;
int type;
{
    char *msg;
	     
    switch(type) {
    case BGP_MSG_OPEN : /*get_open_message(bgp,msg); */
      bgp_send_open(bgp);
	break;
    case BGP_MSG_KEEPALIVE :
      bgp_send_keepalive(bgp);
      break;
    case BGP_MSG_UPDATE : /*get_update_message(bgp,msg);*/
      bgp_send_update(bgp);
	break;
    case BGP_MSG_NOTIFY :
      bgp_send_notify(bgp);
      break;
	default : break;
    }
}


/*

  bgp_state_change

*/
void bgp_change_state(bgp,state)
struct proto_bgp *bgp;
int state;
{
    bgp->state = state;
}

/*

  get_message_type

*/
int get_message_type(bgp,event,flag)
struct proto_bgp *bgp;
int event;
int flag;
{
    int type;
    
    switch(bgp->state) {
    case BGP_STATE_IDLE : type = bgp_state_idle(bgp,event);
	break;
    case BGP_STATE_CONNECT : type = bgp_state_connect(bgp,event);
	break;
    case BGP_STATE_ACTIVE : type = bgp_state_active(bgp,event);
	break;
    case BGP_STATE_OPENSENT :type = bgp_state_opensent(bgp,event,flag);
	break;
    case BGP_STATE_OPENCONFIRM : type = bgp_state_openconfirm(bgp,event);
	break;
    case BGP_STATE_ESTABLISHED : type = bgp_state_established(bgp,event,flag);
	break;
	default : type = BGP_MSG_NONE;
    }

    return type;
}

/*

  bgp_state_idle

*/
int bgp_state_idle(bgp,event)
struct proto_bgp *bgp;
int event;
{
    switch(event) {
    case BGP_STATE_IDLE:bgp_change_state(bgp,BGP_STATE_ACTIVE);
	break;
	default :
	  break;
    }

    return BGP_MSG_NONE;
}
  
/*

  bgp_state_connect

*/
int bgp_state_connect(bgp,event)
struct proto_bgp *bgp;
int event;
{
    int type;
    
    switch(event) {
    case BGP_EVENT_START :
    case BGP_EVENT_CONNECTRETRY :
	 type = BGP_MSG_NONE;
	 break;
    case BGP_EVENT_OPEN : bgp_change_state(bgp,BGP_STATE_OPENSENT);
	 type = BGP_MSG_OPEN;
	 break;
    case BGP_EVENT_OPENFAIL : bgp_change_state(bgp,BGP_STATE_CONNECT);
	 type = BGP_MSG_NONE;
	 break;
    default : bgp_change_state(bgp,BGP_STATE_IDLE);
	 type = BGP_MSG_NONE;
	 break;
  }

    return type;
}

/*

  bgp_state_active

*/
int bgp_state_active(bgp,event)
struct proto_bgp *bgp;
int event;
{
    int type;
    
    switch(event) {
    case BGP_EVENT_START :
    case BGP_EVENT_OPENFAIL :
	 type = BGP_MSG_NONE;
	 break;
    case BGP_EVENT_OPEN : bgp_change_state(bgp,BGP_STATE_OPENSENT);
	 type = BGP_MSG_OPEN;
	 break;
    case BGP_EVENT_CONNECTRETRY : bgp_change_state(bgp,BGP_STATE_CONNECT);
	 type = BGP_MSG_NONE;
	 break;
    default : bgp_change_state(bgp,BGP_STATE_IDLE);
	 type = BGP_MSG_NONE;
	 break;
    }

    return type;
}

/*

  bgp_state_opensent

*/
int bgp_state_opensent(bgp,event,flag)
struct proto_bgp *bgp;
int event;
int flag;
{
    int type;
    
    switch(event) {
    case BGP_EVENT_START :type = BGP_MSG_NONE;
	break;
    case BGP_EVENT_CLOSE :bgp_change_state(bgp,BGP_STATE_CONNECT);
	break;
    case BGP_EVENT_RECVOPEN : if(flag == OKOK) {
				bgp_change_state(bgp,BGP_STATE_OPENCONFIRM);
				type = BGP_MSG_KEEPALIVE;
				break;
    			      }
			      else {
	    			bgp_change_state(bgp,BGP_STATE_IDLE);
	    			type = BGP_MSG_NOTIFY;
	    			break;
			      }
    default : bgp_change_state(bgp,BGP_STATE_IDLE);
	type = BGP_MSG_NONE;
	break;
    }

    return type;
}

/*

  bgp_state_openconfirm

*/
int bgp_state_openconfirm(bgp,event)
struct proto_bgp *bgp;
int event;
{
    int type;
    
    switch(event) {
    case BGP_EVENT_START :type = BGP_MSG_NONE;
	break;
    case BGP_EVENT_KEEPALIVE :type = BGP_MSG_KEEPALIVE;
	break;
    case BGP_EVENT_RECVKEEPALIVE :bgp_change_state(bgp,BGP_STATE_ESTABLISHED);
	type = BGP_MSG_UPDATE;
	break;
    case BGP_EVENT_STOP :
    case BGP_EVENT_OPEN:
    case BGP_EVENT_ERROR :
    case BGP_EVENT_RECVNOTIFY : bgp_change_state(bgp,BGP_STATE_IDLE);
	type = BGP_MSG_NONE;
	break;
	
    default : bgp_change_state(bgp,BGP_STATE_IDLE);
	type = BGP_MSG_NOTIFY;
	break;
    }

    return type;
}
    

/*

  int bgp_state_established

*/
int bgp_state_established(bgp,event,flag)
struct proto_bgp *bgp;
int event;
int flag;
{
    int type;
    
    switch(event) {
    case BGP_EVENT_START :type = BGP_MSG_NONE;
	break;
    case BGP_EVENT_KEEPALIVE :type = BGP_MSG_KEEPALIVE;
	break;
    case BGP_EVENT_RECVKEEPALIVE :type = BGP_MSG_KEEPALIVE;
	break;
    case BGP_EVENT_RECVUPDATE : if(flag == OKOK) {
      type = BGP_MSG_UPDATE;
      break;
  }
	else {
	    bgp_change_state(bgp,BGP_STATE_IDLE);
	    type = BGP_MSG_NOTIFY;
	    break;
	}
    case BGP_EVENT_RECVNOTIFY : bgp_change_state(bgp,BGP_STATE_IDLE);
	type = BGP_MSG_NOTIFY;
	break;
	
    default : bgp_change_state(bgp,BGP_STATE_IDLE);
	type = BGP_MSG_NOTIFY;
	break;
    }

    return type;
}
    
/*

  get_event

*/
int get_event(last_state,new_state)
int last_state;
int new_state;
{
    int event;

    if(new_state < BGP_STATE_IDLE || new_state > BGP_STATE_ESTABLISHED)
        return BGP_EVENT_NOTHING;
    
    switch(last_state) {
    case BGP_STATE_IDLE : event = state_idle[new_state];
	break;
    case BGP_STATE_CONNECT: event = state_conncect[new_state];
	break;
    case BGP_STATE_ACTIVE: event = state_active[new_state];
	break;
    case BGP_STATE_OPENSENT: event = state_opensent[new_state];
	break;
    case BGP_STATE_OPENCONFIRM: event = state_openconfirm[new_state];
	break;
    case BGP_STATE_ESTABLISHED: event = state_establisth[new_state];
	break;
    default: event = BGP_EVENT_NOTHING;
	break;
    }

    return event;
}


/*

  bgp_start

*/
void bgp_start(intf)
struct RT_IFCONF *intf;
{
    struct in_addr *addr;
    struct proto_bgp *bgp;
    int event;
    int state,last_state;
    int recv_msg_flag;
    int type;
    
    bgp = (struct proto_bgp *)intf->proto_info;

    bgp_send_open(bgp);
    bgp_change_state(bgp,BGP_STATE_OPENSENT);

    last_state = BGP_STATE_OPENSENT;
    state = BGP_STATE_OPENCONFIRM;

    while(last_state <= BGP_STATE_ESTABLISHED) {
	event = get_event(last_state,state);

	switch(event) {
	case BGP_EVENT_RECVOPEN : recv_msg_flag = bgp_recv_open();
	    break;
	case BGP_EVENT_RECVKEEPALIVE : recv_msg_flag = bgp_recv_keepalive();
	    break;
	case BGP_EVENT_RECVUPDATE : recv_msg_flag = bgp_recv_update();
	    last_state++;
	    continue;
	    break;
	case BGP_EVENT_RECVNOTIFY : recv_msg_flag = bgp_recv_notify();
	    break;
	default : break;
	}
    
	type = get_message_type(bgp,event,recv_msg_flag);
	bgp_message_send(bgp,type);
	
	last_state = state;
	if(BGP_STATE_ESTABLISHED > state) state++;
	
    }

}
    

/*

  bgp_send_open

*/
int bgp_send_open(bgp)
struct proto_bgp *bgp;
{

    printf("bgp_send_open\n");

    return OKOK;
    
}

/*

  bgp_send_keepalive

*/
int bgp_send_keepalive(bgp)
struct proto_bgp *bgp;
{

    printf("bgp_send_keepalive\n");

    return OKOK;
}

/*

  bgp_send_update

*/
int bgp_send_update(bgp)
struct proto_bgp *bgp;
{

    printf("bgp_send_update\n");
    
    return OKOK;
}

/*

  bgp_send_notify

*/
int bgp_send_notify(bgp)
struct proto_bgp *bgp;
{

    printf("bgp_send_notify\n");
    
    return OKOK;
}

/*

  bgp_recv_open

*/
int bgp_recv_open()
{

    printf("bgp_recv_open\n");
  
    return OKOK;
}

/*

  bgp_recv_keepalive

*/
int bgp_recv_keepalive()
{

    printf("bgp_recv_keepalive\n");
  
    return OKOK;
}

/*

  bgp_recv_update

*/
int bgp_recv_update()
{

    printf("bgp_recv_update\n");
  
    return OKOK;
}

/*

  bgp_recv_notify

*/
int bgp_recv_notify()
{

    printf("bgp_recv_notify\n");
  
    return OKOK;
}




  



