/************************************************************************/
/*	Routing Protocol Simulator	Release 1.0	1994/3/17	*/
/*                                              1.21    1997/2/10       */
/*									*/
/*		module 	: network management				*/
/*		file	: netmng.c				      	*/
/*									*/
/*   Copyright (c) 1994-1997 by Systems Development Laboratory Hitachi,	*/
/*   Ltd. All rights reserved.						*/
/*----------------------------------------------------------------------*/
/*	UPDATE HISTORY							*/
/*	1996.6.20       Add new function - net_link_state()		*/
/*           6.26       Add new function - abr_link_state()             */
/*                                         as_link_state()              */
/************************************************************************/
static char copyright[]=
  "@(#)Copyright (c) 1994-1997 by Systems Development Laboratory Hitachi,Ltd.\n All rights researved.\n";

#include "rps.h"
#include "netmng.h"

extern char *inetaddr_to_char();

void as_dump();
void area_dump();
void net_list_dump();
void net_dump();
void rt_dump();
void rt_if_dump();
struct AS_TBL *get_router_as();
struct NET_TBL *get_link_net();
void as_list_free();
void area_list_free();
void net_list_free();
void rtr_list_free();
void rt_intf_free();
void link_list_free();
void index_free();

struct AS_TBL *as_list=NULL;
struct AREA_TBL *area_list=NULL;
struct NET_TBL *net_list=NULL;
struct RT_TBL *rtr_list=NULL;
struct LINK_TBL *link_list=NULL;

int as_entry_num = 0;
int area_entry_num = 0;
u_int net_entry_num = 0;
u_int rtr_entry_num = 0;

char *if_state[] = { "none", "DOWN", "UP"};

/*

  get_as_list

*/
struct AS_TBL *get_as_list(as_num)
u_long as_num;
{
    struct AS_TBL *as;
    
    if(as_num == LIST_HEAD) {
	return as_list;
    }
    else {
	for(as=as_list;as!=NULL;as=as->next) {
	    if(as_num == as->number) return as;
	}
    }

    return NULL;
}

/*

  get_net_list

*/
struct NET_TBL *get_net_list(net_addr)
u_long net_addr;
{
    struct NET_TBL *net;
    
    if(net_addr == LIST_HEAD) {
	return net_list;
    }
    else {
	for(net=net_list;net!=NULL;net=net->next) {
	    if(net_addr == net->addr) return net;
	}
    }

    return NULL;
}

/*

  get_rt_list

*/
struct RT_TBL *get_rt_list(rt_id)
u_long rt_id;
{
    struct RT_TBL *rt;
    
    if(rt_id == LIST_HEAD) {
	return rtr_list;
    }
    else {
	for(rt=rtr_list;rt!=NULL;rt=rt->next) {
	    if(rt_id == rt->id) return rt;
	}
    }

    return NULL;
}



/*

  get_link_list

*/
struct LINK_TBL *get_link_list(org_rt,cnct_rt)
u_long org_rt;
u_long cnct_rt;
{
    struct LINK_TBL *link;
    
    if(org_rt == LIST_HEAD || cnct_rt == LIST_HEAD) {
	return link_list;
    }
    else {
	for(link=link_list;link!=NULL;link=link->next) {
	    if(org_rt == link->org->id
	    || cnct_rt == link->cnct->id) return link;
	}
    }

    return NULL;
}

/*

  add_astbl_list

*/
add_astbl_list(entry)
struct AS_TBL *entry;
{
    struct AS_TBL *astbl;
    
    if(as_list == NULL) {
	as_list = entry;
    }
    else {
	for(astbl=as_list;astbl->next!=NULL;astbl=astbl->next) ;
	astbl->next = entry;
    }
    as_entry_num++;
}

/*

  add_area_list

*/
void add_area_list(as,area)
struct AS_TBL *as;
struct AREA_TBL *area;
{
    struct AREA_TBL *list=as->alist;

    if(list == NULL) {
	as->alist = area;
    }
    else {
	for(;list->next!=NULL;list=list->next);
	list->next = area;
    }
    area_entry_num++;
}

/*

  add_net_list

*/
void add_net_list(entry)
struct NET_TBL *entry;
{
    struct NET_TBL *nettbl;
    
    if(net_list == NULL) {
	net_list = entry;
    }
    else {
	for(nettbl=net_list;nettbl->next!=NULL;nettbl=nettbl->next) ;
	nettbl->next = entry;
    }
    net_entry_num++;
}

/*

  add_index_list

*/
void add_index_list(head,index)
struct INDEX **head;
struct INDEX *index;
{
    struct INDEX *list;

    if(*head == NULL) {
	*head = index;
    }
    else {
	for(list=*head;list->next!=NULL;list=list->next);
	list->next = index;
    }
}

/*

  index_list_search

*/
struct INDEX *index_list_search(list,dst)
struct INDEX *list;
byte *dst;
{
    struct INDEX *index;

    for(index=list;index!=NULL;index=index->next) {
	if(dst == index->dst) return index;
    }

    return NULL;
}

/*

  add_rt_list

*/
void add_rt_list(rt)
struct RT_TBL *rt;
{
    struct RT_TBL *rttbl;
    
    if(rtr_list == NULL) {
	rtr_list = rt;
    }
    else {
	for(rttbl=rtr_list;rttbl->next!=NULL;rttbl=rttbl->next) ;
	rttbl->next = rt;
    }
    rtr_entry_num++;
}

/*

  net_search

*/
struct NET_TBL *net_search(addr,mask)
u_long addr;
u_long mask;
{
    struct NET_TBL *list;

    for(list=net_list;list!=NULL;list=list->next) {
	if(addr == list->addr && mask == list->mask)
	    return list;
    }

    return NULL;
}

/*

  abr_search

*/
struct RT_TBL *abr_search(area,rt)
struct AREA_TBL *area;
struct RT_TBL *rt;
{
    struct INDEX *index;

    for(index=area->abrlist;index!=NULL;index=index->next) {
	if(rt == (struct RT_TBL *)index->dst)
	  return rt;
    }

    return NULL;
}

/*

  asbr_search

*/
struct RT_TBL *asbr_search(as,rt)
struct AS_TBL *as;
struct RT_TBL *rt;
{
    struct INDEX *index;

    for(index=as->brlist;index!=NULL;index=index->next) {
	if(rt == (struct RT_TBL *)index->dst)
	  return rt;
    }

    return NULL;
}

/*

  rt_search

*/
struct RT_TBL *rt_search(id)
u_long id;
{
    struct RT_TBL *list;

    for(list=rtr_list;list!=NULL;list=list->next) {
	if(id == list->id) return list;
    }

    return NULL;
}

/*

  rt_area_search

*/
struct AREA_TBL *rt_area_search(id,area_num)
u_long id;
u_long area_num;
{
    struct RT_TBL *rt;
    struct AREA_TBL *area;
    struct RT_INTF *cnet;
    struct NET_TBL *net;
    
    if((rt = rt_search(id)) == NULL) return NULL;

    for(cnet=rt->ilist;cnet!=NULL;cnet=cnet->next) {
	if(cnet->state == INTF_DOWN) continue;
	net = cnet->net;
	if(net->domain_type == ITYPE_AREA) {
	    area = (struct AREA_TBL *)net->domain;
	    if(area_num == area->number) return area;
	}
    }
    
    return NULL;
}

/*

  rt_area_check

*/
int rt_area_check(rt1,rt2)
u_long rt1;
u_long rt2;
{
    struct RT_TBL *rt;
    struct AREA_TBL *area;
    struct RT_INTF *cnet;
    struct NET_TBL *net;
    
    if((rt = rt_search(rt1)) == NULL) return NULL;

    for(cnet=rt->ilist;cnet!=NULL;cnet=cnet->next) {
	net = cnet->net;
	if(net->domain_type == ITYPE_AREA) {
	    area = (struct AREA_TBL *)net->domain;
	    if(rt_area_search(rt2,area->number))
	       if(area->number)
		 return area->number;
	}
    }

       
    return 0;
}

/*

  rt_as_check    added 1996.6.28

*/
int rt_as_check(rt1,rt2)
u_long rt1;
u_long rt2;
{
    struct RT_TBL *rt;
    struct AREA_TBL *area;
    struct RT_INTF *cnet;
    struct NET_TBL *net;
    struct AS_TBL *as;
    
    if((rt = rt_search(rt1)) == NULL) return NULL;

    for(cnet=rt->ilist;cnet!=NULL;cnet=cnet->next) {
	net = cnet->net;
	if(net->domain_type == ITYPE_AREA) {
	    area = (struct AREA_TBL *)net->domain;
	    as = area->as_idx;
	    if(as->number)
	      return as->number;
	}
	else if (net->domain_type == ITYPE_AS) {
	    as = (struct AS_TBL *)net->domain;
	    if(as->number)
	      return as->number;
	}
    }

    return 0;
}

    
/*

  add_cnct_list

*/
void add_cnct_net(rt,net)
struct RT_TBL *rt;
struct RT_INTF *net;
{
    struct RT_INTF *list;

    if(rt->ilist == NULL) {
	rt->ilist = net;
    }
    else {
	for(list=rt->ilist;list->next != NULL;list=list->next);
	list->next = net;
    }
}

/*

  assign_if_addr

*/
void assign_if_addr(info)
struct RT_INTF *info;
{
    u_long naddr,iaddr;
    u_long num;
    struct RT_INTF *cnet;
    struct INDEX *index;
    struct NET_TBL *net;
    struct RT_TBL *rt;
    int flag;
    
    net = info->net;
    naddr = net->addr;

    for(num=1;num<MAX_HOSTID;num++) {
	iaddr = naddr + num;
	flag = 0;
	for(index=net->cnct_rt;index!=NULL;index=index->next) {
	    rt=(struct RT_TBL *)index->dst;
	    for(cnet=rt->ilist;cnet!=NULL;cnet=cnet->next) {
		if(cnet != info) {
		    if(iaddr == cnet->ifaddr) {
			flag = 1;
			break;
		    }
		    
		}
	    }
	    if(flag == 1) break;
	}
	if(flag == 1) continue;
	else break;
    }

    info->ifaddr = iaddr;
}
      
/*

  add_link_list

*/
void add_link_list(link)
struct LINK_TBL *link;
{
    struct LINK_TBL *list;

    if(link_list == NULL) {
	link_list = link;
    }
    else {
	for(list=link_list;list->next!=NULL;list=list->next) ;
	list->next = link;
    }
}

/*

  get_as_num

*/
u_long get_as_num(rt_id)
u_long rt_id;
{
    struct AS_TBL *as;
    struct RT_TBL *rt;

    if((rt = rt_search(rt_id)) == NULL) return 0;

    as = get_router_as(rt);

    return as->number;
}

/*

  get_area_num

*/
u_long get_area_num(rt_id,ifaddr)
u_long rt_id;
u_long ifaddr;
{
    struct RT_TBL *rt;
    struct AREA_TBL *area;
    struct RT_INTF *cnet;
    struct NET_TBL *net;
    
    if((rt = rt_search(rt_id)) == NULL) return -1;

    for(cnet=rt->ilist;cnet!=NULL;cnet=cnet->next) {
	if(ifaddr == cnet->ifaddr) {
	    net = cnet->net;
	    if(net->domain_type = ITYPE_AREA) {
		area = (struct AREA_TBL *)net->domain;
		return area->number;
	    }
        }
    }

    return -1;
}

/*

  get_router_as

*/
struct AS_TBL *get_router_as(rt)
struct RT_TBL *rt;
{
    struct RT_INTF *cnct;
    struct NET_TBL *net;
    struct AREA_TBL *area;
    struct AS_TBL *as;
    
    for(cnct=rt->ilist;cnct!=NULL;cnct=cnct->next) {
	net = cnct->net;
	if(net->domain_type == ITYPE_AREA) {
	    area = (struct AREA_TBL *)net->domain;
	    as = area->as_idx;
	}
	else if(net->domain_type == ITYPE_AS) {
	    as = (struct AS_TBL *)net->domain;
	}
    }

    return as;
}

/*

  get_router_area

*/
int get_router_area(rt,list)
struct RT_TBL *rt;
struct INDEX **list;
{
    struct RT_INTF *cnct;
    struct NET_TBL *net;
    struct INDEX *index;
    struct AREA_TBL *area ,*parea;
    int num;
    
    *list = NULL;
    num=0;
    for(cnct=rt->ilist;cnct!=NULL;cnct=cnct->next) {
	net = cnct->net;
	if(net->domain_type == ITYPE_AREA)
	    area = (struct AREA_TBL *)net->domain;
	else
	    continue;
	
	if(index_list_search(list,(byte *)area))
	   continue;

	if((index = (struct INDEX *)malloc(sizeof(struct INDEX))) == NULL)
	      return 0;

	    bzero(index,sizeof(struct INDEX));
	    index->src_type = ITYPE_ROUTER;
	    index->src = (byte *)rt;
	    index->dst_type = ITYPE_AREA;
	    index->dst = (byte *)area;
	    add_index_list(list,index);
	    parea = area;
	    num++;

    }

    return num;
}

/*

  get_net_area

*/
u_long get_net_area(net_addr)
u_long net_addr;
{
    struct NET_TBL *net;
    struct AREA_TBL *area;
    u_long area_num;

    area_num = 0;
    net = get_net_list(net_addr);
    if(net->domain_type == ITYPE_AREA) {
	area = (struct AREA_TBL *)net->domain;
	area_num = area->number;
    }

    return area_num;
}

/*

  get_rtid_with_ifaddr

*/
u_long get_rtid_with_ifaddr(if_addr)
u_long if_addr;
{
    struct RT_TBL *rt;
    struct RT_INTF *cnct;
    
    for(rt=rtr_list;rt;rt=rt->next) {
	for(cnct=rt->ilist;cnct;cnct=cnct->next) {
	    if(if_addr == cnct->ifaddr)
	      return rt->id;
	}
    }

    return 0;
}
  
/*

  get_net_with_ifaddr

*/
struct NET_TBL *get_net_with_ifaddr(id,if_addr)
u_long id;
u_long if_addr;
{
    struct RT_TBL *rt;
    struct RT_INTF *cnet;
    struct NET_TBL *net;
    
    if((rt = rt_search(id)) == NULL)
        return NULL;

    for(cnet=rt->ilist;cnet!=NULL;cnet=cnet->next) {
	if(if_addr == cnet->ifaddr) {
	    return cnet->net;
        }
    }

    return NULL;
}

    
/*

  get_abr

*/
struct INDEX *get_abr(s_area,d_area)
struct AREA_TBL *s_area;
struct AREA_TBL *d_area;
{
    struct INDEX *s_idx,*index,*abr_list,*tmp;
    struct RT_TBL *rt;

    abr_list = NULL;
    for(s_idx=s_area->abrlist;s_idx!=NULL;s_idx=s_idx->next) {
	rt = (struct RT_TBL *)s_idx->dst;
	get_min_path(rt->id);
	if(path_search_area(d_area->abrlist)) {
	    if((index=(struct INDEX *)malloc(sizeof(struct INDEX))) == NULL)
	      return NULL;

	    bzero(index,sizeof(struct INDEX));
	    index->dst = (byte *)rt;
	    
	    if(abr_list == NULL) {
		abr_list = index;
		tmp = index;
	    }
	    else {
		tmp->next = index;
		tmp = index;
	    }
	}
    }

    return abr_list;
}

/*

  get_nbr_list

*/
int get_nbr_list(my_id,if_addr,buff)
u_long my_id;
u_long if_addr;
u_long *buff;
{
    int nbr_num;
    struct NET_TBL *net;
    struct RT_TBL *rt;
    struct INDEX *index;
    
    net = get_net_with_ifaddr(my_id,if_addr);
    nbr_num = 0;
    for(index=net->cnct_rt;index;index=index->next) {
	rt = (struct RT_TBL *)index->dst;

	if(my_id == rt->id) continue;
	*buff++ = ntohl(rt->id);
	nbr_num++;
    }
    *buff = 0;

    return nbr_num;
}

/*

  get_nbr_num

*/
int get_nbr_num(my_id,if_addr)
u_long my_id;
u_long if_addr;
{
    int nbr_num;
    struct NET_TBL *net;
    struct RT_TBL *rt;
    struct INDEX *index;
    
    net = get_net_with_ifaddr(my_id,if_addr);
    nbr_num = 0;
    for(index=net->cnct_rt;index;index=index->next) {
	rt = (struct RT_TBL *)index->dst;

	if(my_id == rt->id) continue;
	nbr_num++;
    }

    return nbr_num;
}

    
/*

    get_dr_addr

*/
u_long get_dr_addr(net_addr)
u_long net_addr;
{
    struct RT_TBL *dr;
    struct RT_INTF *cnct;
    struct NET_TBL *net;

    for(net=net_list;net;net=net->next) {
	if(net_addr == net->addr) break;
    }

    if(net == NULL)
      return 0;
    
    dr=net->dr;
    for(cnct=dr->ilist;cnct!=NULL;cnct=cnct->next)
      if(cnct->net == net) break;
    
    if(cnct)                     /* if Non DR, return 0 1996.12.18 */
      return cnct->ifaddr;
    else
      return 0;
}

/*

  get_bdr_addr

*/
u_long get_bdr_addr(net_addr)
u_long net_addr;
{
    struct NET_TBL *net;
    struct RT_TBL *rt;
    struct RT_INTF *cnct;
    struct INDEX *index;
    
    for(net=net_list;net;net=net->next) {
	if(net_addr == net->addr) break;
    }

    if(net == NULL)
      return 0;

    for(index=net->cnct_rt;index;index=index->next) {
	rt = (struct RT_TBL *)index->dst;
	GET_LINK_NET(rt,cnct,net);
	if(cnct->type == IF_TYPE_BDR) return cnct->ifaddr;
    }

    return 0;
}

/*

  get_dr_id

*/
u_long get_dr_id(net_addr)
u_long net_addr;
{
    struct RT_TBL *dr;
    struct NET_TBL *net;

    for(net=net_list;net;net=net->next) {
	if(net_addr == net->addr) break;
    }

    if(net == NULL) return 0;
    
    dr=net->dr;

    return dr->id;
    
}

/*

  get_bdr_id

*/
u_long get_bdr_id(net_addr)
u_long net_addr;
{
    struct RT_TBL *rt;
    struct RT_INTF *cnct;
    struct INDEX *index;
    struct NET_TBL *net;
    
    for(net=net_list;net;net=net->next) {
	if(net_addr == net->addr) break;
    }

    if(net == NULL)
      return 0;
    
    for(index=net->cnct_rt;index;index=index->next) {
	rt = (struct RT_TBL *)index->dst;
	GET_LINK_NET(rt,cnct,net);
	if(cnct->type == IF_TYPE_BDR) return rt->id;
    }

    return 0;
}

/*

  dr_selection

*/
void dr_selection()
{
    int lock = int_lock();
    struct NET_TBL *net;
    struct RT_INTF *cnct,*dr_cnct,*bdr_cnct;
    struct RT_TBL *rt,*dr;
    struct INDEX *index;
    int down_if;

    dr = NULL;
    for(net=get_net_list(LIST_HEAD);net!=NULL;net=net->next) {
      /*      printf(" %s ", inetaddr_to_char(net->addr));
        if(net->dr)
	  printf(" : current dr = %s ->", 
		 inetaddr_to_char(net->dr->id));*/
        dr_cnct = bdr_cnct = NULL;
	down_if = 0;
        for(index=net->cnct_rt;index!=NULL;index=index->next) {
	    rt = (struct RT_TBL *)index->dst;
	    GET_LINK_NET(rt,cnct,net);
	    
	    if(cnct->state == INTF_DOWN) {
	      down_if++;
	      continue;
	    }

	    if(dr_cnct != NULL && dr->id < rt->id) {
		dr = rt;
		bdr_cnct = dr_cnct;
		dr_cnct = cnct;
	    }
	    else if(dr_cnct == NULL) {
		dr = rt;
		dr_cnct = cnct;
	    }
	}
    
        if(net->dr) {                      /* if no down interface in each */
	  if(down_if) net->dr = dr;        /* network, dr is unchanged */
	}                                  /* 1996.12.20 */
	else {
	  net->dr=dr;
	}
	if(bdr_cnct != NULL) bdr_cnct->type = IF_TYPE_BDR;
        if(dr_cnct != NULL) dr_cnct->type = IF_TYPE_DR;
	/*	if(dr_cnct)
	  printf(" DR %s \n", inetaddr_to_char(net->dr->id));
	else
	  printf(" Non DR \n");*/
	  
    }

    int_unlock(lock);
}

/*

  change_dr

*/
void change_dr(net_addr,new_dr,old_dr)
u_long net_addr;
u_long new_dr;
u_long old_dr;
{
    struct RT_TBL *rt;
    struct RT_INTF *cnet;
    struct INDEX *index;
    struct NET_TBL *net;
    
    for(net=net_list;net;net=net->next) {
	if(net_addr == net->addr) break;
    }

    for(index=net->cnct_rt;index;index=index->next) {
	rt = (struct RT_TBL *)index->dst;
	if(rt->id == new_dr) {
	    GET_LINK_NET(rt,cnet,net);
	    cnet->type = IF_TYPE_DR;
	    net->dr = rt;
	}
	else if(rt->id == old_dr) {
	    GET_LINK_NET(rt,cnet,net);
	    cnet->type = IF_TYPE_BDR;
	}
    }

}
	  

/*

  get_link_cost

*/
long get_link_cost(org,cnct)
u_long org;
u_long cnct;
{
    struct LINK_TBL *link;
    struct RT_INTF *cnet;
    struct NET_TBL *net;
    struct INDEX *index;

    for(link=link_list;link!=NULL;link=link->next) {
	if(link->org->id == org && link->cnct->id == cnct) {
	    net = link->link_net;
	    for(cnet=link->org->ilist;cnet!=NULL;cnet=cnet->next)
	      if(cnet->net == net) break;
	    
	    if(cnet->state == INTF_DOWN) return -1;

	    for(cnet=link->cnct->ilist;cnet!=NULL;cnet=cnet->next)
	      if(cnet->net == net) break;
	    
	    if(cnet->state == INTF_DOWN) return -1;
	    
	    return link->cost;
	}
    }

    return 0;
}

/*

  get_link_net

*/
struct NET_TBL *get_link_net(org,cnct)
u_long org;
u_long cnct;
{
    struct INDEX *index;
    struct RT_INTF *cnet;
    struct RT_TBL *o_rt,*c_rt,*rt;
    struct NET_TBL *net;
    
    o_rt = rt_search(org);
    c_rt = rt_search(cnct);
    
    for(cnet=o_rt->ilist;cnet!=NULL;cnet=cnet->next) {
	net = cnet->net;
	for(index=net->cnct_rt;index!=NULL;index=index->next) {
	    rt = (struct RT_TBL *)index->dst;
	    if(rt == c_rt) return net;
	}
    }

    return NULL;
}

/*

  add_abr_list

*/
void add_abr_list(area,rt)
struct AREA_TBL *area;
struct RT_TBL *rt;
{
    struct INDEX *index,*list;
    
    if((index = (struct INDEX *)malloc(sizeof(struct INDEX))) == NULL)
      return ;

    bzero(index,sizeof(struct INDEX));

    index->src = (byte *)area;
    index->dst = (byte *)rt;

    if(area->abrlist == NULL) {
	area->abrlist = index;
    }
    else {
	for(list=area->abrlist;list->next!=NULL;list=list->next) ;
	list->next = index;
    }
}

/*

  add_asbr_list

*/
void add_asbr_list(as,rt)
struct AS_TBL *as;
struct RT_TBL *rt;
{
    struct INDEX *index,*list;

    if((index = (struct INDEX *)malloc(sizeof(struct INDEX))) == NULL)
      return ;

    bzero(index,sizeof(struct INDEX));

    index->src = (byte *)as;
    index->dst = (byte *)rt;
    
    if(as->brlist == NULL) {
	as->brlist = index;
    }
    else {
	for(list=as->brlist;list->next!=NULL;list=list->next) {
	    if(list->dst == (byte *)rt) return;
	}
	if(list->dst != (byte *)rt) list->next = index;
    }
}

/*

  get_link_state

*/
int get_link_state(id,intf)
u_long id;
u_long intf;
{
    struct RT_TBL *rt;
    struct RT_INTF *cnet;

    rt = rt_search(id);

    for(cnet=rt->ilist;cnet!=NULL;cnet=cnet->next) {
	if(cnet->ifaddr == intf) {
	    return cnet->state;
	}
    }

    return INTF_DOWN;
}

/*

  hop_link_state

*/
void hop_link_state(id,state)
u_long id;
int state;
{
    struct RT_TBL *rt;
    struct RT_INTF *cnet;
    struct NET_TBL *net;
    
    rt = rt_search(id);
    
    for(cnet=rt->ilist;cnet!=NULL;cnet=cnet->next) {
	cnet->state = state;
	net=cnet->net;
/*	if(state == INTF_UP) {
	  log_trace(stderr," net %s ",inetaddr_to_char(net->addr));
	  log_trace(stderr," connect num %d \n",net->cnct_num);
        }
	else if(state == INTF_DOWN) {
	  log_trace(stderr," net %s ",inetaddr_to_char(net->addr));
	  log_trace(stderr," connect num %d \n",net->cnct_num);
	}
*/
    }

}


/*

  link_state_up

*/
void link_state_up(id,intf)
u_long id;
u_long intf;
{
    struct RT_TBL *rt;
    struct RT_INTF *cnet;

    rt = rt_search(id);

    for(cnet=rt->ilist;cnet!=NULL;cnet=cnet->next) {
	if(cnet->ifaddr == intf) {
	    cnet->state = INTF_UP;
	    break;
	}
    }
}

/*

  link_state_down

*/
void link_state_down(id,intf)
u_long id;
u_long intf;
{
    struct RT_TBL *rt;
    struct RT_INTF *cnet;

    rt = rt_search(id);

    for(cnet=rt->ilist;cnet!=NULL;cnet=cnet->next) {
	if(cnet->ifaddr == intf) {
	    cnet->state = INTF_DOWN;
	    break;
	}
    }
}

/*

  net_link_state

*/
u_long net_link_state(net_addr, state)
u_long net_addr;
int    state;
{
    struct NET_TBL *net;
    struct INDEX *index;
    struct RT_TBL *rt;
    struct RT_INTF *intf;
    int exist ;

    exist = 0;
    net = get_net_list(net_addr);
    for(index=net->cnct_rt;index;index=index->next) {
	rt = (struct RT_TBL *)index->dst;
	for(intf=rt->ilist;intf;intf=intf->next) {
	    if((intf->ifaddr & net->mask) == net_addr) {
		intf->state = state;
/*		log_trace(stderr,"%s interface change \n",inetaddr_to_char(intf->ifaddr)); */
		exist = 1;
	    }
	}
    }

    if(exist)
      return rt->id;
    else
      return 0;
}

/*

  get_abr_id

*/
u_long get_abr_id(area_id)
u_long area_id;
{
    struct AREA_TBL *area;
    struct RT_TBL   *rt;
    struct INDEX    *index;
    struct AS_TBL   *as;
    struct NET_TBL  *net;
    
    as = as_list;
    for(area=as->alist;area;area=area->next) {
	if(area->number == area_id) {
	    index = area->abrlist;
	    rt = (struct RT_TBL *)index->dst;
	    return rt->id;
	}
    }

    return 0;
}

/*

  get_asbr_id

*/
u_long get_asbr_id(as_num)
u_long as_num;
{
    struct AREA_TBL *area;
    struct RT_TBL   *rt;
    struct INDEX    *index;
    struct AS_TBL   *as;
    struct NET_TBL  *net;

    if(as_entry_num == 1) return 0;
    
    for(as=as_list;as;as=as->next) {
	if(as->number == as_num) {
	    for(index=as->brlist;index;index=index->next)
		rt = (struct RT_TBL *)index->dst;
	    return rt->id;
	}
    }
    
    return 0;
}

/*

  abr_link_state

*/
void abr_link_state(abr_id,area_id,state)
u_long abr_id;
u_long area_id;
int state;
{
    struct RT_TBL *rt;
    struct AREA_TBL *area;
    struct RT_INTF *cnet;
    struct NET_TBL *net;
    struct AS_TBL *as;
    struct INDEX *index;
    
    as = as_list;
    for(area=as->alist;area;area=area->next) {
	if(area->number == area_id) {
	    index = area->abrlist;
	    rt = (struct RT_TBL *)index->dst;
	    break;
	}
    }
    
    for(index=area->nlist;index;index=index->next) {
	net = (struct NET_TBL *)index->dst;
	net_link_state(net->addr,state);
    }
    
}

/*

  as_link_state

*/
void as_link_state(as_num,state)
int as_num;
int state;
{
    struct RT_TBL *rt;
    struct AREA_TBL *area;
    struct RT_INTF *cnet;
    struct NET_TBL *net;
    struct AS_TBL *as;
    struct INDEX *index;
    
    for(as=as_list;as;as=as->next) {
	if(as->number == as_num) break;
    }
    
    for(index=as->nlist;index;index=index->next) {
	net = (struct NET_TBL *)index->dst;
	net_link_state(net->addr,state);
    }
    
}

/*

  as_list_dump

*/
void as_list_dump()
{
    struct AS_TBL *as;

    for(as=as_list;as!=NULL;as=as->next) {
	as_dump(as);
    }
}

/*

  as_dump

*/
void as_dump(as)
struct AS_TBL *as;
{
    struct INDEX *index;
    struct RT_TBL *rt;
    
    printf("\n AS %u\n",as->number);
    printf("  area = %d, net = %d\n",as->area_num,as->net_num);
    if(as->alist != NULL) area_dump(as->alist);
    for(index=as->nlist;index != NULL;index = index->next) {
	net_dump((struct NET_TBL *)index->dst);
    }
    printf("\n     < as border router list >\n");
    for(index=as->brlist;index!=NULL;index=index->next) {
	rt = (struct RT_TBL *)index->dst;
	printf("	Router ID : %s\n",inetaddr_to_char(rt->id));
    }

}

/*

  area_dump

*/
void area_dump(area)
struct AREA_TBL *area;
{
    struct AREA_TBL *list;
    struct INDEX *index;
    struct in_addr num;
    struct RT_TBL *rt;
    
    for(list=area;list != NULL;list=list->next) {
	num.s_addr = list->number;
	printf("\n   area %s \n",inet_ntoa(num));
	printf("         net = %d , my_as = %u\n",
	       		list->net_num,list->as_idx->number);
	printf("     < network list >\n");
	for(index=list->nlist;index!=NULL;index=index->next) {
	    net_dump((struct NET_TBL *)index->dst);
	}
	printf("\n     < area border router list >\n");
	for(index=list->abrlist;index!=NULL;index=index->next) {
	    rt = (struct RT_TBL *)index->dst;
	    printf("	Router ID : %s\n",inetaddr_to_char(rt->id));
	/*    rt_dump((struct RT_TBL *)index->dst);*/
	}
    }
}

/*

  net_list_dump

*/
void net_list_dump()
{
    struct NET_TBL *net;

    for(net=net_list;net != NULL;net=net->next) {
	net_dump(net);
    }
}

/*

  net_dump

*/
void net_dump(net)
struct NET_TBL *net;
{
    struct INDEX *index;
    struct RT_TBL *rt;
    struct AREA_TBL *area;
    struct AS_TBL *as;
    
    printf("\n      network %s ",	inetaddr_to_char(net->addr));
    printf("      mask %s \n",	inetaddr_to_char(net->mask));

    if(net->domain_type == ITYPE_AS) {
	as = (struct AS_TBL *)net->domain;
	printf("	DOMAIN : AS %u\n",as->number);
    }
    else if(net->domain_type == ITYPE_AREA) {
	area = (struct AREA_TBL *)net->domain;
	printf("	DOMAIN : AREA %s\n",inetaddr_to_char(area->number));
    }
    else if(net->domain_type == ITYPE_INTER_AS) {
	printf("	DOMAIN : INTER_AS \n");
    }
    else {
	printf("	DOMAIN : NONE \n");
    }
	
    printf("      conect rtr = %d\n",net->cnct_num);
    for(index=net->cnct_rt;index!=NULL;index=index->next) {
	rt = (struct RT_TBL *)index->dst;
	printf("	Router ID : %s\n",inetaddr_to_char(rt->id));
	rt_if_dump(net,rt);
    }
}

/*

  rt_list_dump

*/
void rt_list_dump()
{
    struct RT_TBL *rt;
    struct INDEX *index;
    struct AREA_TBL *area;
    struct AS_TBL *as;
    struct in_addr area_num;
    
    printf("\n ----- router dump ------\n\n");
    index = NULL;
    for(rt=rtr_list;rt!=NULL;rt=rt->next) {
	rt_dump(rt);
/*	num = get_router_area(rt,&index);*/
	for(;index!=NULL;index=index->next) {
	    area = (struct AREA_TBL *)index->dst;
	    area_num.s_addr = area->number;
	    printf("	  area = %s\n",inet_ntoa(area_num));
	}
	as = get_router_as(rt);
	printf("	  as = %u\n\n", as->number);
    }

}

/*

  rt_dump

*/
void rt_dump(rt)
struct RT_TBL *rt;
{
    struct RT_INTF *net;
    
    printf("	Router ID : %s \n",inetaddr_to_char(rt->id));
    printf("	  net =  %d \n",rt->cnct_num);
    for(net=rt->ilist;net!=NULL;net=net->next) {
	printf("	  interface %s cost %d <%s>\n",
	       inetaddr_to_char(net->ifaddr),net->cost,if_state[net->state]);

    }
}

/*

  rt_print

*/
void rt_print(id)
u_long id;
{
    struct RT_TBL *rt;

    rt = rt_search(id);

    if(rt)
      rt_dump(rt);

}

/*

  rt_if_dump

*/
void rt_if_dump(net,rt)
struct NET_TBL *net;
struct RT_TBL *rt;
{
    struct RT_INTF *cnet;
    
    for(cnet=rt->ilist;cnet!=NULL;cnet=cnet->next) {
	if(net == cnet->net)  {
	    printf("	  interface %s cost %d \n",
	   	inetaddr_to_char(cnet->ifaddr),cnet->cost);
	}
    }
}

/*

  link_list_dump

*/
void link_list_dump()
{
    struct LINK_TBL *link;
    struct in_addr addr;
    struct INDEX *index;

    printf("\n ----- link dump ------\n\n");
    for(link=link_list;link!=NULL;link=link->next) {
	printf("\n Link ID : %d\n",link->id);
	addr.s_addr = link->link_net->addr;
	printf("   link network = %s\n",inet_ntoa(addr));
	addr.s_addr = link->org->id;
	printf("   router id = %s\n",inet_ntoa(addr));
	addr.s_addr = link->cnct->id;
	printf("   router id = %s\n",inet_ntoa(addr));
	printf("   cost = %d\n",link->cost);
    }
}

/*

  net_info_dump

*/
void net_info_dump(fp)
FILE *fp;
{
    log_trace(fp,"\n");
    log_trace(fp,"   as entry      : %5d\n",as_entry_num);
    log_trace(fp,"   area entry    : %5d\n",area_entry_num);
    log_trace(fp,"   network entry : %5u\n",net_entry_num);
    log_trace(fp,"   router entry  : %5u\n",rtr_entry_num);
    log_trace(fp,"\n");
}
    
/*

  net_free

*/
void net_free()
{
    as_list_free();
    net_list_free();
    rtr_list_free();
    link_list_free();
}

/*

  as_list_free

*/
void as_list_free()
{
    struct AS_TBL *as,*nas;
    
    if(as_list == NULL) return;

    for(as=as_list;as;) {
	nas = as->next;
	if(as->alist) area_list_free(as->alist);
	if(as->nlist) index_free(as->nlist);
	if(as->brlist) index_free(as->brlist);
	free((char *)as);
	as=nas;
    }
    as_list = NULL;
}

/*

  area_list_free

*/
void area_list_free(area_list)
struct AREA_TBL *area_list;
{
    struct AREA_TBL *area,*narea;

    for(area=area_list;area;) {
	narea = area->next;
	if(area->nlist) index_free(area->nlist);
	if(area->abrlist) index_free(area->abrlist);
	free((char *)area);
	area=narea;
    }
}

/*

  net_list_free

*/
void net_list_free()
{
    struct NET_TBL *net,*next;

    for(net=net_list;net;) {
	next = net->next;
	if(net->cnct_rt) index_free(net->cnct_rt);
	free((char *)net);
	net=next;
    }
    net_list=NULL;
}

/*

  rtr_list_free

*/
void rtr_list_free()
{
    struct RT_TBL *rt,*next;
    
    for(rt=rtr_list;rt;) {
	next = rt->next;
	if(rt->ilist) rt_intf_free(rt->ilist);
	if(rt->domain) index_free(rt->domain);
	free((char *)rt);
	rt=next;
    }
    rtr_list=NULL;
}

/*

  rt_intf_free

*/
void rt_intf_free(list)
struct RT_INTF *list;
{
    struct RT_INTF *rt_if,*next;

    for(rt_if=list;rt_if;) {
	next=rt_if->next;
	free((char *)rt_if);
	rt_if=next;
    }
}

/*

  link_list_free

*/
void link_list_free()
{
    struct LINK_TBL *link,*next;

    for(link=link_list;link;) {
        next=link->next;
	free((char *)link);
	link=next;
    }
    link_list=NULL;
}

/*

  index_free

*/
void index_free(list)
struct INDEX *list;
{
    struct INDEX *idx,*next;

    for(idx=list;idx;) {
	next=idx->next;
	free((char *)idx);
	idx=next;
    }
}


	










