/* 
 * $Id: idrp_attr_rec.c,v 1.4 1995/10/08 17:04:36 skh Exp $
 * Merit IDRP release 1.1 (gated 3.5.4).  Copyright (c) 1994 by Merit Network, Inc. 
 */

#include "include.h"
#include "iso.h"
#include "idrp.h"
#include <stdio.h>

/* idrp_attr_rec.c - all routines about attribute record 
 *  (only routines in from the idrp_rt.c file
 * once that compiles - we will pull the idrp.c file apart
 * 
 * %% rd path routines  
 * idrp_free_canon_rdpath (p_can_list,peer) - free this canon rd path 
 * idrp_canon_my_rdi_path (p_att,peer) - create canon path from my rdi
 * idrp_my_rdi_rdpath(p_att)
 * idrp_dump_rdi_path (p_rdl,peer) - dump rdi path in pretty print 
 * add_nlri_routeid_chain(p_rte,p_idrp_rt)
 * 
 * %% idrp transitive attribute records
 * idrp_free_transitive(p_trans,peer) 
 *
 */

/* free a cannonical RD path given a peer structure to free from  */

void
idrp_free_canon_rdpath(p_can_list)
idrp_canon_rdpath       *p_can_list;
{
idrp_canon_rdpath *p_can;
idrp_canon_rdpath *p_can_old;

	p_can = p_can_list;
        while (p_can)
                {
                p_can_old = p_can;
                p_can = p_can->p_next;
                IDRP_MEM_FIT_FREE(p_can_old);
                }

}

/* create an RDI path entry with just my RDI for this node
 * Does canonization make one a saint... this RDI PATH stuff
 * could use all the blessings it can get !!
 */

int
idrp_canon_my_rdi_path(p_att)
idrp_attribute_record *p_att;
{
idrp_canon_rdpath *p_can;

        p_can = (idrp_canon_rdpath *) idrp_local_mem_fit (sizeof(idrp_canon_rdpath));
        p_can->p_next = (idrp_canon_rdpath *) 0;
        bcopy(&rt_rdi,&(p_can->p_rdi),sizeof(rt_rdi));
        p_att->rd_path = p_can;
        return((rt_rdi.isoa_len+1));
}

int
idrp_my_rdi_rdpath(p_att)
idrp_attribute_record *p_att;
{
	/* I think a test for a hopcount of zero is enough.
	 * - however, we will compare the global pointers for
	 * the order path starts and ends with the local rdi path  
	 * the canonical path's first RDI is the same as this one
	 * - some of these test may be deleted later
	 * -- skh (4/21/94)
	 */ 

	if ((p_att->p_opts->hopcount == 0) && (p_my_rdpath == p_att->p_rd_opath) &&
		(p_att->p_rd_opath->p_start == p_att->p_rd_opath->p_end) &&
		(p_my_rdpath->p_start->rdi_list.p_rdi_array[0] == p_att->rd_path->p_rdi))  
		{
		return(TRUE);
		}
	return (FALSE);
}

void
idrp_dump_rdi_path(p_rdl,peer)
idrp_canon_rdpath 	*p_rdl;
idrpPeer		*peer;
{
idrp_canon_rdpath	*p_can;
int			i = 0;

	/* someday - we will want to make only one copy of
	 * a canonical RD list - but for now
	 * let's try to focus on just one copy of Attribute 
	 * - refocus as first pdu's flying
	 */
	
	trace_tf (idrp_trace_options, TR_NORMAL, 0, (" peer %s RDI path print ",peer->name));
	RDPATH_LIST(p_rdl,p_can)
		{
		/* @@@trace_tf(idrp_trace_options, TR_NORMAL,0,
			 ("RDI path: RDI %d =  %A",i,sockbuild_iso((byte *) p_can->p_rdi.rdi.isoa_genaddr,
			p_can->p_rdi.isoa_len))); */
		i++;
		}
}

int
add_new_routeid_chain(p_rte,p_att)
idrpRoute_entry		*p_rte;	/* idrpRoute entry */ 
idrp_attribute_record	*p_att;	/* pointer attribute record */
{
idrpRoute_entry	*p_route_ent;

	/* walk the route_id_list to the end and add the new route_id
	 * record at the end
	 */

	p_route_ent = p_att->route_id_list; 
	if (p_route_ent)
		{
		trace_log_tf (idrp_trace_options, 0, LOG_ERR,
			      ("Attribute record has route list with no entries"));
		return (FALSE);
		}
 
	while (p_route_ent->p_next)
		{
		p_route_ent = p_route_ent->p_next;
		}
	p_route_ent->p_next = p_rte;
	p_rte->p_next = (idrpRoute_entry *) 0;

	return (TRUE);
}

			

int
add_nlri_routeid_chain(p_rte,p_idrp_rt)
idrpRoute_entry	*p_rte;
idrpRoute	*p_idrp_rt;
{
int		nlri_id;	

	nlri_id = family_to_nlri_id(p_idrp_rt->family);

	/* Add a nlri to a route_id
	 * - Right now this is only  valid
	 *   for the idrp configured or
	 *   the EXT_INFO from this node.
	 * - checks are made to make sure this is
	 *   the only valid use
	 * - The rest of the route_id chains
	 *   are added when the UPDATE pdu is received
	 */

	if (p_rte->route_id != IDRP_LOCAL_ROUTE_ID  && 
	    p_rte->route_id != IDRP_EXT_INFO_ROUTE_ID )
		{
		/* not local or EXT_INFO - bogus */
		
		return (FALSE);
		}

	/* now add the idrp route to the beginning of the chain.  We 
	 * used to add to the end, but we don't need the chain in any
	 * specific order, and this is way cheaper.
	 */
	p_idrp_rt->p_next_nlri = p_rte->p_route[nlri_id];
	p_rte->p_route[nlri_id] = p_idrp_rt;
  
        /* last thing on the list, so point tail to it (chl 3/17/94) */
        if (p_idrp_rt->p_next_nlri == NULL)
	  p_rte->p_route_tail[nlri_id] = p_idrp_rt;

	return(TRUE);
}

void idrp_free_trans(p_tran_list)
idrp_attribute_entry_list	*p_tran_list;
{
idrp_attribute_entry_list	*p_tran;
idrp_attribute_entry_list	*p_tran_free;

	p_tran = p_tran_list;
	while (p_tran)
		{
		p_tran_free = p_tran;
		p_tran = p_tran->p_next;
		IDRP_MEM_FIT_FREE(p_tran_free);
		}
}


void
idrp_free_attr_list(p_att_list)
idrp_attribute_record 	*p_att_list;
{
idrp_attribute_record 	*p_att,*p_att_next;

/* free the attribute list 
 * and and all associated records	
 */

	trace_tf (idrp_trace_options, TR_NORMAL, 0, (" idrp_free_attr_list *** Not code !! "));
	task_quit(0);
	

	for (p_att = p_att_list;p_att; p_att = p_att_next)
		{
		p_att_next = p_att->next;
	
		/* 1) free any routes associated with the
		 * the attribute record 
		 * 2) free the attribute record 
		 *    
		 */


		}		


}		

void
idrp_free_oatt_list(p_oatt_list)
idrp_att_list 	*p_oatt_list;
{
idrp_attribute_record 	*p_att,*p_att_next;

/* free the attribute list 
 * and and all associated records	
 */

	trace_tf (idrp_trace_options, TR_NORMAL, 0, (" idrp_free_oatt_list *** Not coded !! "));
	task_quit(0);

	
}
