/*
 * bgp4+.h (from bgp.h)
 */

/*
 * ------------------------------------------------------------------------
 * 
 * Copyright (c) 1996, 1997 The Regents of the University of Michigan
 * All Rights Reserved
 *  
 * Royalty-free licenses to redistribute GateD Release
 * 3 in whole or in part may be obtained by writing to:
 * 
 * 	Merit GateDaemon Project
 * 	4251 Plymouth Road, Suite C
 * 	Ann Arbor, MI 48105
 *  
 * THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
 * EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION WARRANTIES OF 
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE REGENTS OF THE
 * UNIVERSITY OF MICHIGAN AND MERIT DO NOT WARRANT THAT THE
 * FUNCTIONS CONTAINED IN THE SOFTWARE WILL MEET LICENSEE'S REQUIREMENTS OR
 * THAT OPERATION WILL BE UNINTERRUPTED OR ERROR FREE. The Regents of the
 * University of Michigan and Merit shall not be liable for
 * any special, indirect, incidental or consequential damages with respect
 * to any claim by Licensee or any third party arising from use of the
 * software. GateDaemon was originated and developed through release 3.0
 * by Cornell University and its collaborators.
 * 
 * Please forward bug fixes, enhancements and questions to the
 * gated mailing list: gated-people@gated.merit.edu.
 * 
 * ------------------------------------------------------------------------
 * 
 * Copyright (c) 1990,1991,1992,1993,1994,1995 by Cornell University.
 *     All rights reserved.
 * 
 * THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
 * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE.
 * 
 * GateD is based on Kirton's EGP, UC Berkeley's routing
 * daemon	 (routed), and DCN's HELLO routing Protocol.
 * Development of GateD has been supported in part by the
 * National Science Foundation.
 * 
 * ------------------------------------------------------------------------
 * 
 * Portions of this software may fall under the following
 * copyrights:
 * 
 * Copyright (c) 1988 Regents of the University of California.
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms are
 * permitted provided that the above copyright notice and
 * this paragraph are duplicated in all such forms and that
 * any documentation, advertising materials, and other
 * materials related to such distribution and use
 * acknowledge that the software was developed by the
 * University of California, Berkeley.  The name of the
 * University may not be used to endorse or promote
 * products derived from this software without specific
 * prior written permission.  THIS SOFTWARE IS PROVIDED
 * ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */


/*
 *	Gated implementation related BGP4+ definitions
 */

typedef struct in6_addr bgp_nexthop6;

/*
 * Metrics for BGP4+.  We store (to be) advertised metrics and nexthops in
 * a structure like this, and maintain a single copy of each distinct set
 * of metrics/nexthop, to make comparisons easy.
 */
typedef struct _bgp_metrics6 {
    bgp_nexthop6 bgpm_nexthop;
    bvalue_t bgpm_metric;
    bvalue_t bgpm_localpref;
    bvalue_t bgpm_tag;
    union {
	bvalue_t bgpm_MA_alltypes;
	struct {
	    btype_t bgpm_MT_metric;
	    btype_t bgpm_MT_localpref;
	    btype_t bgpm_MT_tag;
	    btype_t bgpm_MT_unused;
	} bgpm_MA_types;
    } bgpm_M_types;
#define	bgpm_tmetric	bgpm_M_types.bgpm_MA_types.bgpm_MT_metric
#define	bgpm_tlocalpref	bgpm_M_types.bgpm_MA_types.bgpm_MT_localpref
#define	bgpm_ttag	bgpm_M_types.bgpm_MA_types.bgpm_MT_tag
#define	bgpm_types	bgpm_M_types.bgpm_MA_alltypes
} bgp_metrics6;

/*
 * BGP4+ metrics node structure.  BGP4+ metrics are sorted into a patricia
 * tree, the node structure contains both the metrics and the associated
 * bookkeeping data.  This data type is actually private to bgp_rt.c,
 * but is defined here to keep it in front of its use.
 */
typedef struct _bgp_metrics_node6 {
    bgp_metrics6 bgpmn_metrics;
    u_int32 bgpmn_refcount;		/* references to node */
    struct _bgp_metrics_node6 *bgpmn_left;
    struct _bgp_metrics_node6 *bgpmn_right;
    u_int bgpmn_bit;
} bgp_metrics_node6;

/*
 * BGP4+ advertised route list.  This contains a pointer to a
 * route we have our bit set on, and the metrics the route
 * was advertised with (if any).
 */
typedef struct _bgp_adv_entry6 {
    bgp_adv_queue bgpe_q_entry;
    rt_entry *bgpe_rt;
    bgp_metrics6 *bgpe_metrics;
    flag_t bgpe_flags;
} bgp_adv_entry6;

/*
 * Flags we know about.  Only 1 currently.
 */
#define	BGPEF_QUEUED	BIT(0x2)

/*
 * BGP4+ outgoing route queue list for external peers
 */
typedef struct _bgp_rto_entry6 {
    struct _bgp_rto_entry6 *bgpo_next;		/* next entry in chain */
    struct _bgp_rto_entry6 *bgpo_prev;		/* previous entry in chain */
    time_t bgpo_time;				/* time to send new route */
    bgp_adv_entry6 *bgpo_advrt;
    bgp_metrics6 *bgpo_metrics;			/* metric/nh sent previously */
    as_path *bgpo_asp;				/* AS path sent previously */
} bgp_rto_entry6;


/*
 * BGP4+ old route info, used for internal/igp/routing/test peer group
 * outgoing lists
 */
typedef struct _bgpg_rtinfo_entry6 {
    struct _bgpg_rtinfo_entry6 *bgp_info_next;	/* next info struct in chain */
    bgp_metrics6 *bgp_info_metrics;		/* metrics last sent */
    as_path *bgp_info_asp;			/* AS path last sent */
    bgp_bits bgp_info_bits[1];			/* peer bits, expandable */
} bgpg_rtinfo_entry6;


/*
 * BGP4+ outgoing route queue list for internal/igp/test peer groups
 */
typedef struct _bgpg_rto_entry6 {
    struct _bgpg_rto_entry6 *bgpgo_next;	/* next entry in chain */
    struct _bgpg_rto_entry6 *bgpgo_prev;	/* previous entry in chain */
    time_t bgpgo_time;				/* time to send new route */
    bgp_adv_entry6 *bgpgo_advrt;		/* pointer to adv route entry */
    bgpg_rtinfo_entry6 *bgpgo_info;		/* old route info */
} bgpg_rto_entry6;


/*
 * BGP4+ AS path list pointer.  Routes in the list are sorted by outgoing
 * AS path to make collection of common path attributes simpler when
 * actually announcing the routes.  This structure heads each list.
 */
typedef struct _bgp_asp_list6 {
    union {
        bgp_rto_entry6 *bgpl_X2_rto_next;
	bgpg_rto_entry6 *bgpl_X2_grto_next;
    } bgpl_X2;
    union {
        bgp_rto_entry6 *bgpl_X1_rto_prev;
	bgpg_rto_entry6 *bgpl_X1_grto_prev;
    } bgpl_X1;
    bgp_rt_queue bgpl_asp_queue;
} bgp_asp_list6;



/*
 * Support for BGP4+ internal routing synchronization with an IGP.  The
 * scheme here is track both IGP routes and IBGP routes, building a
 * radix trie which contains the IGP routes and the IBGP next hops.
 * This way a next hop for an IBGP route may be found by finding
 * the IBGP next hop in the routing table, then walking back up
 * the trie to the first node with an IGP route attached.  The
 * latter contributes the next hops.
 */

/*
 * BGP synchronization next hops.  We keep a private next hop
 * structure so we don't lose changes, and to make installation
 * convenient.
 */
typedef struct _bsy_nexthop6 {
    struct _bsy_nexthop6 *bsynh_next;	/* next in hash chain */
    u_long bsynh_refcount;		/* reference count for this nh set */
    u_short bsynh_hash;			/* hash value for next hop */
    u_short bsynh_n_gw;			/* number of next hops */
    bgp_nexthop6 bsynh_nexthop[RT_N_MULTIPATH];
} bsy_nexthop6;

/*
 * We hash the next hops we're using to speed lookups.  The hashing
 * is actually done on the next hops in the rt_entry, so we assume
 * this is what we're given to compute the hash.
 */

#undef	BSYNH_HASH

#if	RT_N_MULTIPATH == 1
#define	BSYNH_HASH(n_gw, gws, hash) \
    ((hash) = ((u_int32 *)&sock2in6(*(gws)))[3] % BSYNH_HASH_SIZE)
#else	/* RT_N_MULTIPATH == 1 */
#define	BSYNH_HASH(n_gw, gws, hash) \
    do { \
	register int Xn_gw = (n_gw); \
	register sockaddr_un **Xgws = (gws); \
	register u_int32 Xtmp = 0; \
	do { \
	    Xtmp ^= ((int *)&sock2in6(*(Xgws)))[3];
	    Xgws++; \
	} while ((--Xn_gw) > 0); \
	(hash) = Xtmp % BSYNH_HASH_SIZE; \
    } while (0)
#endif	/* RT_N_MULTIPATH == 1 */

/*
 * This is an internal node in a BGP4+ synchronization radix trie.  There
 * are pointers to both an IGP route and an IBGP next hop.
 */
typedef struct _bsy_rt_internal6 {
    struct _bsy_rt_internal6 *bsyi_left;	/* child when bit is zero */
    struct _bsy_rt_internal6 *bsyi_right;	/* child when bit is one */
    struct _bsy_rt_internal6 *bsyi_parent;	/* parent of this node */
    struct in6_addr bsyi_bit;			/* bit for this node */
    struct in6_addr bsyi_dest;
    struct _bsy_nh_entry6 *bsyi_nexthop; /* next hop node, if any */
    struct _bsy_igp_rt6 *bsyi_igp_rt;	/* IGP route, if any */
} bsy_rt_internal6;

/*
 * This structure is used to keep track of IGP routes we're seen.
 * It has a pointer to the current next hop structure for this
 * route, and a private copy of the route's metric.
 */
typedef struct _bsy_igp_rt6 {
    bsy_rt_internal6 *bsy_igp_rti;	/* This entry's internal node */
    rt_entry *bsy_igp_rt;		/* The IGP route in question */
    u_int32 bsy_igp_metric;		/* IGP metric for this route */
    bsy_nexthop6 *bsy_igp_nexthop;	/* Current IGP next hops */
} bsy_igp_rt6;

/*
 * This is used to keep track of IBGP routes whose next hop/preference
 * we are managing.
 */
typedef struct _bsy_ibgp_rt6 {
    struct _bsy_ibgp_rt6 *bsyb_next;	/* Circular list chain pointers */
    struct _bsy_ibgp_rt6 *bsyb_prev;
    struct _bsy_nh_entry6 *bsyb_nh;	/* Point to nh entry we're with */
    rt_entry *bsyb_rt;			/* Route this refers to */
    pref_t bsyb_pref;			/* Route's (natural) preference */
    flag_t bsyb_flags;			/* Flags for route */
} bsy_ibgp_rt6;

#undef	BSY_NEXTHOP
#define	BSY_NEXTHOP(brt) \
    (struct in6_addr *)((brt)->bsyb_nh->bsyn_ibgp_rti->bsyi_dest)

/*
 * This structure keeps track of next hops which arrived in IBGP routes,
 * and the IBGP routes which possessed these next hops.  It also keeps
 * track of IGP metrics, since these are used for equal preference
 * tie breaking.
 */
typedef struct _bsy_nh_entry6 {
    bsy_ibgp_rt6 *bsyn_next;		/* Circular list pointer for routes */
    bsy_ibgp_rt6 *bsyn_prev;
    bsy_rt_internal6 *bsyn_ibgp_rti;	/* Internal node we're attached to */
    bsy_nexthop6 *bsyn_igp_nexthop;	/* Current next hop(s) for route */
    u_int32 bsyn_igp_metric;		/* Current IGP metric for route */
    struct _bsy_nh_entry6 *bsyn_change_next;	/* Changed list pointer */
} bsy_nh_entry6;

/*
 * The BGP4+ synchronization structure.  This is the structure by which
 * the synchronization instance is referred to external to the module.
 * It holds the local task pointer, a pointer to the root of our radix
 * trie, the group that we are running with and an indicator of the IGP
 * we are running with.
 */
typedef struct _bgp_sync6 {
    task *bgp_sync_task;		/* Our task (holds our rtbit) */
    bsy_rt_internal6 *bgp_sync_trie;	/* Root of our radix trie */
    bsy_nh_entry6 *bgp_sync_nh_changes;	/* List of IBGP routes with changes */
    proto_t bgp_sync_proto;		/* The IGP we are sync'ing to */
    struct _bgpPeerGroup *bgp_sync_group;	/* Our group */
    u_int bgp_sync_n_hashed;		/* Number of hashed next hops */
    bsy_nexthop6 *bgp_sync_nh_hash[BSYNH_HASH_SIZE];	/* Next hop hash list */
    char bgp_sync_name[BGPSYNCTASKNAMELENGTH];	/* Name for task */
} bgp_sync6;


/*
 * Variables in bgp4+_init.c
 */
extern int doing_bgp4mp;		/* Are we running BGP4+ protocols? */
extern trace *bgp4mp_default_trace_options;
extern pref_t bgp4mp_default_preference;
extern pref_t bgp4mp_default_preference2;
extern metric_t bgp4mp_default_metric;

extern adv_entry *bgp4mp_import_list;
extern adv_entry *bgp4mp_import_aspath_list;
extern adv_entry *bgp4mp_export_list;

#define	BGP4MP_GROUP_LIST(bgp)	\
	for (bgp = bgp4mp_groups; bgp; bgp = bgp->bgpg_next)

#define	BGP4MP_GROUP_LIST_END(bgp)

/*
 * Routines in bgp4+_init.c
 */
PROTOTYPE(bgp4mp_var_init,
	  extern void,
	  (void));
PROTOTYPE(bgp4mp_conf_check,
	  extern int,
	  (char *));
PROTOTYPE(bgp4mp_conf_group_alloc, extern bgpPeerGroup *, (void));
PROTOTYPE(bgp4mp_conf_peer_alloc,
	  extern bgpPeer *,
	  (bgpPeerGroup *));
PROTOTYPE(bgp4mp_conf_group_add,
	  extern bgpPeerGroup *,
	  (bgpPeerGroup *,
	   char *));
PROTOTYPE(bgp4mp_conf_group_check,
	  extern int,
	  (bgpPeerGroup *,
	   char *));
PROTOTYPE(bgp4mp_conf_peer_add,
	  extern bgpPeer *,
	 (bgpPeerGroup *,
	  bgpPeer *,
	  char *));
PROTOTYPE(bgp4mp_init,
	  extern void,
	  (void));
