/************************************************************************/
/*	Routing Protocol Simulator	Release 1.0	1994/3/17	*/
/*                                              1.21    1997/2/10       */
/*									*/
/*		module 	: routing table management     			*/
/*		file	: lsdb.h	       				*/
/*									*/
/*   Copyright (c) 1994-1997 by Systems Development Laboratory Hitachi,	*/
/*   Ltd. All rights reserved.						*/
/*----------------------------------------------------------------------*/
/*	UPDATE HISTORY							*/
/*									*/
/************************************************************************/
#define LS_TYPE_RT		1
#define LS_TYPE_NET		2
#define LS_TYPE_SUM_NET		3
#define LS_TYPE_SUM_ASBR	4
#define LS_TYPE_ASE		5

#define INIT_LS_SEQ_NUM		0x80000001
#define MAX_SEQ_NUM		0x7fffffff

#define NEXT_LS_SEQ(seq) ((seq == MAX_SEQ_NUM) ? INIT_LS_SEQ_NUM ; (seq+1))
/* link state header */

#define MAX_LS_AGE		3600
#define MAX_LS_COST		0xffffff
#define MAX_AGE_DIFF		900

#define LSA_DATA_END            -2
#define AREA_DATA_END           -3

struct LS_HDR {
    u_short ls_age;
    u_char ls_option;
    u_char ls_type;
    u_long ls_id;
    u_long adv_rt;
    u_long ls_seq;
    u_short ls_chksum;
    u_short length;
};

#define LS_HDR_SIZE	20

/* router link advertisement */

struct LS_RT_TOS {
    u_short tos;
    u_short metric;
};

#define LS_RT_SIZE		12

struct LS_RT {
    u_long id;
    u_long data;
    u_char type;
    u_char tos_num;
    u_short tos0_metric;
};

struct LS_RT_LIST {
    struct LS_RT_LIST *next;
    u_long id;
    u_long data;
    u_char type;
    u_char tos_num;
    u_short tos0_metric;
};

#define	RTIF_TYPE_RT		1
#define RTIF_TYPE_TRANS_NET	2
#define RTIF_TYPE_STUB_NET	3
#define RTIF_TYPE_VIRTUAL	4

#define LS_RT_HDR_SIZE		24

struct LS_RT_HDR {
    struct LS_HDR hdr;
    u_short bits;
    u_short link;
    struct LS_RT rt_link;
};

struct LS_RT_HDR_LIST {
    struct LS_RT_HDR_LIST *next;
    struct LS_HDR hdr;
    u_short bits;
    u_short link;
    struct LS_RT_LIST *rt_link;
};

#define BORDER_BIT		0x100
#define EXTERNAL_BIT		0x200

/* network link advertisement */

#define LS_NET_SIZE	4

struct LS_NET {
    u_long cnct_rt;
};

struct LS_NET_LIST {
    struct LS_NET_LIST *next;
    u_long cnct_rt;
};

#define LS_NET_HDR_SIZE		24

struct LS_NET_HDR {
    struct LS_HDR hdr;
    u_long net_mask;
    struct LS_NET net_link;
};

struct LS_NET_HDR_LIST {
    struct LS_NET_HDR_LIST *next;    
    struct LS_HDR hdr;
    u_long net_mask;
    struct LS_NET_LIST *net_link;

};


/* summary link advertisement */

#define	LS_SUM_SIZE	4

struct LS_SUM {
    u_long tos_metric;
};

struct LS_SUM_LIST {
    struct LS_SUM_LIST *next;
    u_long tos_metric;    
};

#define LS_SUM_HDR_SIZE		24

struct LS_SUM_HDR {
    struct LS_HDR hdr;
    u_long net_mask;
    struct LS_SUM sum_link;
};

struct LS_SUM_HDR_LIST{
    struct LS_SUM_HDR_LIST *next;
    struct LS_HDR hdr;
    u_long net_mask;
    struct LS_SUM_LIST *sum_link;
};

/* AS external link advertisement */

#define LS_ASE_SIZE	12

struct LS_ASE {
    u_long tos_metric;
    u_long forward_addr;
    u_long ext_rt_tag;
};

struct LS_ASE_LIST {
    struct LS_ASE_LIST *next;
    u_long tos_metric;
    u_long forward_addr;
    u_long ext_rt_tag;
};

#define	LS_ASE_HDR_SIZE		24
#define ASE_E_bit               0x80000000

#define OSPF_ASE_TAG_AUTOGEN    0x80000000
#define OSPF_ASE_TAG_COMPLETE   0x40000000
#define OSPF_ASE_TAG_PATHLEN0   0x00000000
#define OSPF_ASE_TAG_PATHLEN1   0x10000000
#define OSPF_ASE_TAG_PATHLEN2   0x20000000
#define OSPF_ASE_DEFAULT_TAG    OSPF_ASE_TAG_AUTOGEN | OSPF_ASE_TAG_COMPLETE |\
                                OSPF_ASE_TAG_PATHLEN1
#define OSPF_ASE_TAG_ASMASK     0x0000ffff

struct LS_ASE_HDR {
    struct LS_HDR hdr;
    u_long net_mask;
    struct LS_ASE ase_link;
};

struct LS_ASE_HDR_LIST {
    struct LS_ASE_HDR_LIST *next;
    struct LS_HDR hdr;
    u_long net_mask;
    struct LS_ASE_LIST *ase_link;
};

struct LSDB_SUM_LIST {
    struct LSDB_SUM_LIST *next;
    struct LS_HDR *lsh;
    byte *list;
    time_t age;
    int state;
    int change;
};

#define LSDB_STATE_DELETE	0
#define LSDB_STATE_DOWN		1
#define LSDB_STATE_ACTIVE	2

#define LSDB_NOCHANGE           0
#define LSDB_CHANGE             1

struct LSDB {
    char *area;
    struct LS_RT_HDR *rt;
    struct LS_NET_HDR *net;
    struct LS_SUM_HDR *sum_net;
    struct LS_SUM_HDR *sum_asbr;
    struct LS_ASE_HDR *ase;
};

struct LSDB_LIST {
    struct LSDB_LIST *next;
    char *area;
    u_long  rt_id;
    struct LS_RT_HDR_LIST *rt;
    struct LS_NET_HDR_LIST *net;
    struct LS_SUM_HDR_LIST *sum_net;
    struct LS_SUM_HDR_LIST *sum_asbr;
    struct LS_ASE_HDR_LIST *ase;
    struct LS_SUM_HDR_LIST *default_sum;
    int my_entry_num;
    struct LSDB_SUM_LIST *my_lsdb;
    int nbr_entry_num;
    struct LSDB_SUM_LIST *nbr_lsdb;
    struct LSDB_SUM_LIST *next_sum;
    struct LSDB_SUM_LIST *next_adv;
};

struct LSA_LIST {
    struct LSDB_LIST *lsdb;
    int my_entry_num;
    struct LSDB_SUM_LIST *my_lsdb;
    int nbr_entry_num;
    struct LSDB_SUM_LIST *nbr_lsdb;
    struct LSDB_SUM_LIST *next_sum;
    struct LSDB_SUM_LIST *next_adv;
};

#define OSPF_MALLOC(ptr,type,size) \
	{ \
    	  if((ptr = (struct type *)calloc(1,size)) == NULL) { \
		return NULL; \
	  } \
	  else { \
	        bzero(ptr,size); \
          } \
	}							     

#define OSPF_FREE(ptr)	free(ptr)

#define LS_LEN(lsh)	(((struct LS_HDR *)lsh)->length)
#define LS_TYPE(lsh)	(((struct LS_HDR *)lsh)->ls_type)
#define LS_ID(lsh)      (((struct LS_HDR *)lsh)->ls_id)
#define LS_SEQ(lsh)     (((struct LS_HDR *)lsh)->ls_seq)
#define LS_ADVRTR(lsh)  (((struct LS_HDR *)lsh)->adv_rt)

#define LS_LIST_LEN(type,ptr,len) \
{ \
    if(type == LS_TYPE_RT) len = ((struct LS_RT_HDR_LIST *)ptr)->hdr.length; \
    else if(type == LS_TYPE_NET) len = ((struct LS_NET_HDR_LIST *)ptr)->hdr.length; \
    else if(type == LS_TYPE_SUM_NET || type == LS_TYPE_SUM_ASBR) \
      len = ((struct LS_SUM_HDR_LIST *)ptr)->hdr.length; \
	else if(type == LS_TYPE_ASE) len = ((struct LS_ASE_HDR_LIST *)ptr)->hdr.length; \
      }

#define LSDB_ENTRY(sum)         ((struct LSDB_SUM_LIST *)sum)->lsh
#define LSDB_ENTRY_LEN(sum)	LS_LEN(((struct LSDB_SUM_LIST *)sum)->lsh)
#define LSDB_ENTRY_TYPE(sum)	LS_TYPE(((struct LSDB_SUM_LIST *)sum)->lsh)
#define LSDB_ENTRY_ID(sum)	LS_ID(((struct LSDB_SUM_LIST *)sum)->lsh)
#define LSDB_ENTRY_SEQ(sum)	LS_SEQ(((struct LSDB_SUM_LIST *)sum)->lsh)
#define LSDB_ENTRY_ADVRTR(sum)	LS_ADVRTR(((struct LSDB_SUM_LIST *)sum)->lsh)

#define LSDB_ENTRY_CHANGE(sum)  ((struct LSDB_SUM_LIST *)sum)->change

#define LS_COMPARE(lsh1,lsh2)   (lsh1->ls_type == (lsh2)->ls_type && \
                                 ntohl(lsh1->ls_id) == (lsh2)->ls_id && \
                                 ntohl(lsh1->ls_seq) == (lsh2)->ls_seq && \
                                 ntohl(lsh1->adv_rt) == (lsh2)->adv_rt)

#define DB_SUM_COPY(ls_type,ptr) \
{ \
    struct ls_type *ptr; \
    for(ptr=lsdb->ptr;ptr;ptr=(ptr)->next) { \
	if(ptr->hdr.adv_rt == adv_rt) continue; \
        (*list) = (ptr)->hdr; \
	list->ls_age = (short)get_time_diff(make_lsdb_time); \
	num++; \
        list++; \
    } \
}

#define MY_LSDB_CHECK(my_id,hdr,nbr_id) \
   ((hdr)->ls_type == LS_TYPE_RT || (hdr)->ls_type == LS_TYPE_NET) \
   && my_id != (hdr)->adv_rt && adv_rt_check(my_id,hdr,nbr_id) 

#define MY_LSDB_CHECK1(my_id,hdr,nbr_id) \
   ( (hdr)->ls_type == LS_TYPE_SUM_NET \
   ||(hdr)->ls_type == LS_TYPE_SUM_ASBR \
   ||(hdr)->ls_type == LS_TYPE_ASE)  \
   && my_id != (hdr)->adv_rt \
   && adv_rt_check(my_id,hdr,nbr_id)

/*	if((ptr)->hdr.adv_rt == nbr_id) { */

#define DB_ENTRY_LIST(ls_type,ptr) \
{ \
    struct ls_type *ptr; \
    for(ptr=lsdb->ptr;ptr;ptr=(ptr)->next) { \
        MALLOC(entry,LSDB_SUM_LIST); \
	entry->lsh = &(ptr)->hdr; \
        entry->list = (byte *)ptr; \
	entry->state = LSDB_STATE_ACTIVE; \
	entry->change = LSDB_CHANGE; \
	entry->age += currnt_time; \
	if((ptr)->hdr.adv_rt == nbr_id \
	|| MY_LSDB_CHECK(my_id,entry->lsh,nbr_id) \
        || MY_LSDB_CHECK1(my_id,entry->lsh,nbr_id)) { \
	    if(lsdb->nbr_lsdb == NULL) { \
		lsdb->nbr_lsdb = nbr_list = entry; \
	    } \
	    else { \
		nbr_list->next = entry; \
		nbr_list = entry;\
	    } \
	    lsdb->nbr_entry_num++; \
	} \
	else { \
	    if(lsdb->my_lsdb == NULL) { \
		lsdb->my_lsdb = my_list = entry; \
	    } \
	    else { \
 		my_list->next = entry; \
		my_list = entry; \
	    } \
	    lsdb->my_entry_num++; \
	} \
    } \
}

#define DB_SCAN(type,ptr) \
{ \
    struct type *ptr; \
    for(ptr=lsdb->ptr;ptr;ptr=ptr->next) { \
        if(ptr->hdr.ls_id == id && ptr->hdr.adv_rt == adv_rt) \
        return (char *)ptr; \
    } \
}

#define LSHDR_COPY(lsh,lshp) \
{\
    lsh->ls_option = lshp->hdr.ls_option; \
    lsh->ls_type = lshp->hdr.ls_type; \
    lsh->ls_id = htonl(lshp->hdr.ls_id);\
    lsh->adv_rt = htonl(lshp->hdr.adv_rt);\
    lsh->ls_seq = htonl(lshp->hdr.ls_seq);\
    lsh->ls_chksum = htons(lshp->hdr.ls_chksum);\
    lsh->length = htons(lshp->hdr.length);\
}

/* define function in lsdb.c */      

struct LS_RT_HDR_LIST *make_rt_link();
struct LS_RT_HDR_LIST *make_rt_link_virtual();
struct LS_RT_HDR_LIST *get_rt_link();
struct LS_NET_HDR_LIST *make_net_link();
struct LS_SUM_HDR_LIST *make_sum_net_link();
struct LS_SUM_HDR_LIST *make_sum_asbr_link();
struct LS_ASE_HDR_LIST *make_ase_link();
struct LS_ASE_HDR_LIST *make_ase_hdr();
struct LS_SUM_HDR_LIST *make_default_sum_link();
void add_ase_hdr_list();
void lsdb_dump();
void rt_link_dump();
void ls_link_dump();
void net_link_dump();
void ls_hdr_dump();
void sum_net_link_dump();
void sum_asbr_link_dump();
void ase_link_dump();


