/* * Copyright (c) 1997 by the University of Southern California. * All rights reserved. * * Permission to use, copy, modify, and distribute this software and * its documentation in source and binary forms for lawful * non-commercial purposes and without fee is hereby granted, provided * that the above copyright notice appear in all copies and that both * the copyright notice and this permission notice appear in supporting * documentation, 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 Southern * California and/or Information Sciences Institute. * The name of the University of Southern California may not * be used to endorse or promote products derived from this software * without specific prior written permission. * * THE UNIVERSITY OF SOUTHERN CALIFORNIA DOES NOT MAKE ANY REPRESENTATIONS * ABOUT THE SUITABILITY OF THIS SOFTWARE FOR ANY PURPOSE. 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, TITLE, AND * NON-INFRINGEMENT. * * IN NO EVENT SHALL USC, OR ANY OTHER CONTRIBUTOR BE LIABLE FOR ANY * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES, WHETHER IN CONTRACT, * TORT, OR OTHER FORM OF ACTION, ARISING OUT OF OR IN CONNECTION WITH, * THE USE OR PERFORMANCE OF THIS SOFTWARE. * * Questions concerning this software should be directed to * eddy@isi.edu. * * $Id: pim.h,v 1.19 1998/11/21 03:53:26 eddy Exp $ */ #ifdef PROTO_PIM #ifndef PIM_INCLUDED #define PIM_INCLUDED 1 #define PIM_VERSION 2 #define PIM_ADDRLEN 4 #define PIM_HOST_MASKLEN 32 #define PIM_ALL_ROUTERS 0xe000000d /* 224.0.0.13 */ #define PIM_WILDCARD 0xe0000000 /* 224.0.0.0 */ #define PIM_WILDCARD_MASKLEN 4 /* bits */ #ifndef IPPROTO_PIM #define IPPROTO_PIM 103 /* for lacking in.h */ #endif IPPROTO_PIM #define PIM_DIRECT_PREFERENCE 0 #define PIM_STATIC_PREFERENCE 1 #define PIM_BASE_TYPE 0 #define PIM_HELLO 0 #define PIM_REGISTER 1 #define PIM_REGISTER_STOP 2 #define PIM_JOIN_PRUNE 3 #define PIM_BOOTSTRAP 4 #define PIM_ASSERT 5 #define PIM_GRAFT 6 /* dense mode only */ #define PIM_GRAFT_ACK 7 /* dense mode only */ #define PIM_CRP_ADV 8 /* candidate RP advertisement */ #define PIM_MAX_TYPE 9 static const bits pim_type_bits[] = { { PIM_HELLO, "Hello" }, { PIM_REGISTER, "Register" }, { PIM_REGISTER_STOP,"Register Stop" }, { PIM_JOIN_PRUNE, "Join/Prune" }, { PIM_BOOTSTRAP, "Bootstrap" }, { PIM_ASSERT, "Assert" }, { PIM_GRAFT, "Graft" }, { PIM_GRAFT_ACK, "Graft Ack" }, { PIM_CRP_ADV, "C-RP Advertisment" }, { 0 } }; #define PIM_ENABLED 0x01 /* PIM protocol status bit */ #define PIM_LIMIT_MRT_PERIOD 1, 3600 /* mrt clean period */ #define PIM_LIMIT_MRT_TIMEOUT 1, 0xffff /* mrt entry holdtime */ #define PIM_LIMIT_HELLO_PERIOD 1, 3600 /* to send hellos */ #define PIM_LIMIT_HELLO_HOLDTIME 1, 0xffff /* hello holdtime */ #define PIM_LIMIT_ASSERT_HOLDTIME 1, 0xffff #define PIM_LIMIT_ASSERT_TIMEOUT 1, 0xffff /* assert timeout */ #define PIM_LIMIT_HOLDTIME 1, 3600 /* ??? */ #define PIMSM_LIMIT_JP_PERIOD 1, 0xffff /* send jp period */ #define PIMSM_LIMIT_JP_HOLDTIME 1, 0xffff /* jp holdtime */ #define PIMSM_LIMIT_JP_SUP_TIMEOUT 1, 15 /* jp suppression timeout */ #define PIMSM_LIMIT_JP_DELAY_TIMEOUT 1, 15 /* jp del delay */ #define PIMSM_LIMIT_REG_SUP_TIMEOUT 1, 3600 #define PIMSM_LIMIT_PROBE_PERIOD 1, 3600 #define PIMSM_LIMIT_CRP_HOLDTIME 1, 0xffff #define PIMSM_LIMIT_BSR_PERIOD 1, 3600 #define PIMSM_LIMIT_BSR_TIMEOUT 1, 3600 #define PIMSM_LIMIT_THRESHOLD 1, 0xffff #define PIM_CONFIG_NONE 0 #define PIM_CONFIG_ENABLE 1 #define PIM_CONFIG_DISABLE 2 #define PIM_CONFIG_HELLO_PERIOD 3 #define PIM_CONFIG_HELLO_HOLDTIME 4 #define PIM_CONFIG_COMP_IFACES 5 #define PIMSM_CONFIG_JP_PERIOD 6 #define PIMSM_CONFIG_JP_HOLDTIME 7 #define PIMSM_CONFIG_JP_SUP_TIMEOUT 8 #define PIMSM_CONFIG_JP_DELAY_TIMEOUT 9 #define PIMSM_CONFIG_DELAY_TIMEOUT 10 #define PIMSM_CONFIG_CRP 11 #define PIMSM_CONFIG_CRP_PERIOD 12 #define PIMSM_CONFIG_CRP_HOLDTIME 13 #define PIMSM_CONFIG_CBSR_PRIORITY 14 #define PIMSM_CONFIG_CBSR_TIMEOUT 15 #define PIMSM_CONFIG_BSR_PERIOD 16 #define PIM_CONFIG_ASSERT_TIMEOUT 17 #define PIM_CONFIG_ASSERT_HOLDTIME 18 #define PIMDM_CONFIG_SENDER_IS_MEMBER 19 #define PIMSM_CONFIG_REG_SUP_TIMEOUT 20 #define PIMSM_CONFIG_PROBE_PERIOD 21 #define PIMSM_CONFIG_THRESHOLD_DR 22 #define PIMSM_CONFIG_THRESHOLD_RP 23 #define PIMSM_CONFIG_THRESHOLD 24 #define PIM_CONFIG_MAX 25 #define PIM_MIN_PACKET_LEN 4 #define PIMHELLO_HOLDTIME 1 #define PIMHELLO_TAGSWITCH 17 #define PIMHELLO_RATELIMIT 18 #define PIMHELLO_PRIORITY 19 #define PIMHELLO_HOLDTIME_LEN 2 #define PIMHELLO_PRIORITY_LEN 4 #define PIMHELLO_RESERVED 2 #define PIM_OFFSET 1 #define TR_PIM_DETAIL_HELLO TR_DETAIL_1 /* query */ #define TR_PIM_DETAIL_REGISTER TR_DETAIL_2 /* register, rp */ #define TR_PIM_DETAIL_REGISTER_STOP TR_DETAIL_2 /* register, rp */ #define TR_PIM_DETAIL_JOIN_PRUNE TR_DETAIL_3 /* join, prune */ #define TR_PIM_DETAIL_BOOTSTRAP TR_DETAIL_4 /* bootstrap */ #define TR_PIM_DETAIL_ASSERT TR_DETAIL_5 /* assert */ #define TR_PIM_DETAIL_GRAFT TR_DETAIL /* dense only */ #define TR_PIM_DETAIL_GRAFT_ACK TR_DETAIL /* dense only */ #define TR_PIM_DETAIL_CRP_ADV TR_DETAIL_4 /* register, rp */ #define TR_PIM_INDEX_PACKETS 0 #define TR_PIM_INDEX_HELLO 1 #define TR_PIM_INDEX_REGISTER 2 #define TR_PIM_INDEX_REGISTER_STOP 3 #define TR_PIM_INDEX_JOIN_PRUNE 4 #define TR_PIM_INDEX_BOOTSTRAP 5 #define TR_PIM_INDEX_ASSERT 6 #define TR_PIM_INDEX_GRAFT 7 #define TR_PIM_INDEX_GRAFT_ACK 8 #define TR_PIM_INDEX_CRP_ADV 9 #define ifa_name ifa_link->ifl_name /* * Interface specific parameters */ typedef struct pim_ifparm_ { task *pimif_new_task; /* pointer for new config'd component */ task_timer *pimif_hello_timer; /* hello timer */ u_int32 pimif_hello_period; /* time int for hello sends */ u_int8 pimif_hello_priority; /* can we use priorities on this interface? */ task_timer *pimif_nbr_timer; /* nbr timeout timer */ u_int32 pimif_nbr_period; /* time int for nbr to's */ task_job *pimif_nbr_job; /* nbr timeout job */ #ifdef PROTO_PIMSM task_timer *pimif_jp_timer; /* join/prune timer */ u_int32 pimif_jp_period; /* time int for jp sends */ task_job *pimif_jp_job; /* the join/prune job */ u_int pimif_cbsr_priority; u_int32 pimif_crp_period; /* XXX: misplaced? */ #endif /*PROTO_PIMSM*/ } pim_ifparm_t; #define pim_ips ifa_ps[RTPROTO_PIM] #define PIM_IF_PARMS(ifap) ((pim_ifparm_t *)(ifap->pim_if_parms)) #define PIM_IF_NEW_TASK(ifap) \ (((pim_ifparm_t*)(ifap->pim_if_params))->pimif_new_task) #define PIM_IF_HELLO_PERIOD(ifap) \ (((pim_ifparm_t*)(ifap->pim_if_params))->pimif_hello_period) #define PIM_IF_HELLO_TIMER(ifap) \ (((pim_ifparm_t*)(ifap->pim_if_params))->pimif_hello_timer) #define PIM_IF_NBR_TIMEOUT(ifap) \ (((pim_ifparm_t*)(ifap->pim_if_params))->pimif_nbr_period) #define PIM_IF_NBR_TIMER(ifap) \ (((pim_ifparm_t*)(ifap->pim_if_params))->pimif_nbr_timer) #define PIM_IF_NBR_JOB(ifap) \ (((pim_ifparm_t*)(ifap->pim_if_params))->pimif_nbr_job) #ifdef PROTO_PIMSM #define PIMSM_IF_JP_PERIOD(ifap) \ (((pim_ifparm_t*)(ifap->pim_if_params))->pimif_jp_period) #define PIMSM_IF_JP_TIMER(ifap) \ (((pim_ifparm_t*)(ifap->pim_if_params))->pimif_jp_timer) #define PIMSM_IF_JP_JOB(ifap) \ (((pim_ifparm_t*)(ifap->pim_if_params))->pimif_jp_job) #endif /*PROTO_PIMSM*/ #define PIM_ABLE_IFAP(ifap) \ (socktype (IFA_UNIQUE_ADDR(ifap)) == AF_INET && \ BIT_TEST(ifap->ifa_state, IFS_MULTICAST) && \ !BIT_TEST(ifap->ifa_state, IFS_LOOPBACK) && \ !BIT_TEST(ifap->ifa_state, IFS_REGISTER) && \ !BIT_TEST(ifap->ifa_state, IFS_TUNNEL)) /* * this telss if a running component should consider this interface * during normal processing, e.g. after initialization, put these checks in. * * BIT_SET(ips->ips_state, IFPS_NOIN); * BIT_SET(ips->ips_state, IFPS_NOOUT); */ PROTOTYPE(pim_ipsstate, flag_t, (if_addr *)); #define PIM_IPSSTATE(ifap) ((struct ifa_ps *)&((ifap)->ifa_ps[RTPROTO_PIM]))->ips_state #define PIM_IGNORE_IFAP(ifap) \ (!PIM_ABLE_IFAP(ifap) || \ !BIT_TEST((ifap)->ifa_state, IFS_UP) || \ mbr_get_ifproto(ifap) != RTPROTO_PIM || \ BIT_TEST(PIM_IPSSTATE(ifap), IFPS_NOOUT)) #define PIM_BCAST_IFAP(ifap) \ (!PIM_IGNORE_IFAP(ifap) && BIT_TEST(ifap->ifa_state, IFS_BROADCAST)) #define PIM_SETTYPE(p, t) (p)->pim_vers = (0x2f & (t)) #define IFPS_PIM_MODE IFPS_POLICY1 #define IFPS_DR_STATUS IFPS_KEEP1 #define NBR_ENQ(elem, pred) { \ register pimnbr_t *Xe = elem; \ register pimnbr_t *Xp = pred; \ Xp->forw = (Xe->forw = (Xe->back = Xp)->forw)->back = Xe; \ } #define NBR_DEQ(elem) { \ register pimnbr_t *Xe = elem; \ (Xe->back->forw = Xe->forw)->back = Xe->back; \ } /************************************************************************* * Multicast Route Table Stuff *************************************************************************/ extern trace *pim_trace_options; /* dm and sm have there own options */ extern const bits pim_trace_types[]; /* List of PIM specific trace flags */ #define ASSERT_RPT_BIT 0x80 /* for assert messages */ #define RPT_BIT 0x01 #define WC_BIT 0x02 #define SPT_BIT 0x04 #define SPARSE_BIT 0x04 #define NEG_CACHE_BIT 0x08 /* PIMDM only */ #define JOIN_SUPP_BIT 0x10 /* PIMDM only - a bit to facilitate suppression of join MBR alerts when creating the entry. Join alerts should not send PIM messages when this bit is set. */ #define ifa_name ifa_link->ifl_name #define PIM_HOLD_FOREVER 0xffff #define CRP_AUTH_BIT 0x80 /* C-RP authoratative bit */ #define WC 0x00000000 #define NODE_NOMASK 0xffffffff #define MFC_DENSE 0 #define MFC_SPARSE 1 #define MFC_NUM_TABLES 2 #define MRTTYPE_NONE 0 #define MRTTYPE_WC 1 /* spt = 0, wc = 1, rpt = 1 */ #define MRTTYPE_RP 2 /* spt = 1, wc = 1, rpt = 1 */ #define MRTTYPE_SG 3 /* spt = 0, wc = 0, rpt = 0 */ #define MRTTYPE_RPT 4 /* spt = 0, wc = 0, rpt = 1 */ #define MRTTYPE_SPT 5 /* spt = 1, wc = 0, rpt = 0 */ #define MRTFLAG_SG 0x0 #define EATYPE_NONE MRTTYPE_NONE #define EATYPE_WC MRTTYPE_WC #define EATYPE_RP MRTTYPE_RP #define EATYPE_RPT MRTTYPE_RPT #define EATYPE_SG MRTTYPE_SG #define EATYPE_SPARSE MRTTYPE_SPT /* These really do mean different things */ #define IS_SG(FLAGS) (!BIT_TEST(FLAGS, RPT_BIT) && \ !BIT_TEST(FLAGS, WC_BIT)) #define IS_SPT(FLAGS) (IS_SG(FLAGS) && \ BIT_TEST(FLAGS, SPT_BIT)) #define IS_xSG(FLAGS) (IS_SG(FLAGS) && \ !BIT_TEST(FLAGS, SPT_BIT)) #define IS_WC(FLAGS) (BIT_TEST (FLAGS, RPT_BIT) && \ BIT_TEST (FLAGS, WC_BIT) && \ !BIT_TEST (FLAGS, SPT_BIT)) #define IS_RPT(FLAGS) (BIT_TEST(FLAGS, RPT_BIT) && \ !BIT_TEST(FLAGS, WC_BIT) && \ !BIT_TEST(FLAGS, SPT_BIT)) #define IS_NEG_CACHE(FLAGS) (BIT_TEST(FLAGS, NEG_CACHE_BIT)) #define MRT_TYPE(FLAGS) IS_WC(FLAGS) ? MRTTYPE_WC : \ IS_RPT(FLAGS) ? MRTTYPE_RPT : \ IS_SPT(FLAGS) ? MRTTYPE_SPT : \ IS_SG(FLAGS) ? MRTTYPE_SG : MRTTYPE_NONE /* * This section is for encoded addrs found in J/P messages, basically * we have a 'sparse' bit rather than a spt bit */ #define IS_EWC(FLAGS) ((BIT_TEST(FLAGS, RPT_BIT)) && \ (BIT_TEST(FLAGS, WC_BIT))) /* * flags (wr) type * * 00 EATYPE_SG * 11 EATYPE_WC * 01 EATYPE_RP */ #define EADDR_TYPE(FLAGS) IS_SG(FLAGS) ? EATYPE_SG : \ IS_EWC(FLAGS) ? EATYPE_WC : \ !BIT_TEST(FLAGS, RPT_BIT) ? EATYPE_RPT : \ EATYPE_NONE #define HAS_RP(entry) (0) #define VALID_SRC_INADDR(inaddr) \ (!IN_BADCLASS(ntohl(inaddr)) || !IN_MULTICAST(ntohl(inaddr)) || \ inaddr != INADDR_ANY || inaddr != INADDR_BROADCAST) /* * The Address families, as per IANA */ #define ADDRF_RESERVED 0 #define ADDRF_IPv4 1 #define ADDRF_IPv6 2 #define ADDRF_NSAP 3 #define ADDRF_HDLC 4 #define ADDRF_BBN1822 5 #define ADDRF_802 6 #define ADDRF_E163 7 #define ADDRF_E164 8 #define ADDRF_F69 9 #define ADDRF_X121 10 #define ADDRF_IPX 11 #define ADDRF_APPLETALK 12 #define ADDRF_DECNETIV 13 #define ADDRF_BANYAN 14 #define ADDRF_E164NSAP 15 #define ADDRT_IPv4_NONE 0 #define ADDRT_IPv4 ADDRT_IPv4_NONE /* * encoded source and group addr, when it's a * group flags alway = 0, this could support other sizes. */ typedef struct eaddr_ { u_int8 ea_family; u_int8 ea_type; u_int8 ea_flags; u_int8 ea_masklen; u_int32 ea_addr; } eaddr_t; typedef struct euaddr_ { u_int8 eu_family; u_int8 eu_type; u_int32 eu_addr; } euaddr_t; typedef struct pim_ { u_int8 pim_vers; /* version and type flags */ u_int8 pim_resvd; /* addr len in bytes */ u_int16 pim_cksum; /* whole message or header? */ } pim_t; typedef struct hello_ { u_int16 hel_type; u_int16 hel_optlen; } hello_t; typedef struct regstop_ { eaddr_t rs_egrp; eaddr_t rs_esrc; } regstop_t; typedef struct jpgrp_ { eaddr_t jpg_egrp; u_int16 jpg_joins; u_int16 jpg_prunes; } jpgrp_t; typedef struct jp_ { u_int8 jp_rsvd; u_int8 jp_groups; u_int16 jp_holdtime; } jp_t; /* * the following messages will be unrolled by hand to there liberal use * of misaligned fields. */ typedef struct bootstrap_ { u_int16 bs_fragtag; u_int8 bs_masklen; u_int8 bs_priority; } bootstrap_t ; typedef struct assert_ { eaddr_t as_egrp; u_int32 as_src; u_int32 as_pref; /* R flag in msb */ u_int32 as_metric; } assert_t; typedef struct crp_ { u_int8 crp_prefs; /* prefix count */ u_int8 crp_auth; /* authoritative bit */ u_int16 crp_holdtime; } crp_t; /************************************************************************* * Packet formulation and decoding, taken from bgp *************************************************************************/ #define PUT_BYTE(val, cp) (*(cp)++ = (byte)(val)) #define PUT_SHORT(val, cp) \ do { \ register u_short Xv; \ Xv = (u_short)(val); \ *(cp)++ = (byte)(Xv >> 8); \ *(cp)++ = (byte)Xv; \ } while (0) #define PUT_LONG(val, cp) \ do { \ register u_long Xv; \ Xv = (u_long)(val); \ *(cp)++ = (byte)(Xv >> 24); \ *(cp)++ = (byte)(Xv >> 16); \ *(cp)++ = (byte)(Xv >> 8); \ *(cp)++ = (byte)Xv; \ } while (0) #define PUT_NETLONG(val, cp) \ do { \ register u_char *Xvp; \ u_long Xv = (u_long)(val); \ Xvp = (u_char *)&Xv; \ *(cp)++ = *Xvp++; \ *(cp)++ = *Xvp++; \ *(cp)++ = *Xvp++; \ *(cp)++ = *Xvp++; \ } while (0) /* * Macros to get various length values from the stream. cp must be a * (byte *) */ #define GET_BYTE(val, cp) ((val) = *(cp)++) #define GET_SHORT(val, cp) \ do { \ register unsigned int Xv; \ Xv = (*(cp)++) << 8; \ Xv |= *(cp)++; \ (val) = Xv; \ } while (0) #define GET_LONG(val, cp) \ do { \ register u_long Xv; \ Xv = (*(cp)++) << 24; \ Xv |= (*(cp)++) << 16; \ Xv |= (*(cp)++) << 8; \ Xv |= *(cp)++; \ (val) = Xv; \ } while (0) #define GET_NETLONG(val, cp) \ do { \ register u_char *Xvp; \ u_long Xv; \ Xvp = (u_char *) &Xv; \ *Xvp++ = *(cp)++; \ *Xvp++ = *(cp)++; \ *Xvp++ = *(cp)++; \ *Xvp++ = *(cp)++; \ (val) = Xv; \ } while (0) #define PUT_EADDR(saddr, smask, flags, cp) \ do { \ *cp++ = ADDRF_IPv4; /* family */ \ *cp++ = 0; /* type */ \ *cp++ = flags; /* flags */ \ *cp++ = inet_prefix_mask(smask); \ PUT_NETLONG(sock2ip(saddr) & \ sock2ip(smask), cp); \ } while(0) #define GET_EADDR(ea, cp) \ do { \ eaddr_t *Xea = (ea); \ ea->ea_family = *(cp)++; \ ea->ea_type = *(cp)++; \ ea->ea_flags = *(cp)++; \ ea->ea_masklen= *(cp)++; \ GET_NETLONG((ea)->ea_addr, cp); \ } while(0) #define EA2SOCK(ea, addr, mask) \ do { \ eaddr_t *Xea = (ea); \ int mlen; \ (addr) = (Xea->ea_family == ADDRF_IPv4 && \ Xea->ea_type == ADDRT_IPv4) ? \ sockbuild_in (0, Xea->ea_addr) : \ (sockaddr_un *)0; \ mlen = Xea->ea_masklen; \ (mask) = (addr) ? \ inet_mask_prefix(mlen) : \ (sockaddr_un *)0; \ } while (0) #define GET_EADDR_SOCK(eaddr, addr, mask, cp) \ { \ eaddr_t *Yea = (eaddr); \ GET_EADDR(Yea, cp); \ EA2SOCK(Yea, addr, mask); \ } #define GET_EUADDR(eu, cp) \ do { \ euaddr_t *Xeu = (eu); \ Xeu->eu_family = *(cp)++; \ Xeu->eu_type = *(cp)++; \ GET_NETLONG(Xeu->eu_addr, cp); \ } while(0) #define GET_EUADDR_SOCK(eaddr, addr, cp) \ { \ euaddr_t *Yea = (eaddr); \ GET_EUADDR(Yea, cp); \ (addr) = eu2sock(Yea); \ } #define PUT_EUADDR(saddr, cp) \ do { \ *cp++ = ADDRF_IPv4; \ *cp++ = ADDRT_IPv4; \ PUT_NETLONG(sock2ip(saddr), cp);\ } while(0) /********************************************************************* * downstream timer functions *********************************************************************/ #define pim_downstream_expired(dp) (dp->ds_timeout != PIM_HOLD_FOREVER && \ time_sec >= dp->ds_timeout) #define pim_downstream_holdtime(dp, holdtime) { \ dp->ds_holdtime = holdtime; \ (time_t) dp->ds_deldelay = holdtime / 3; \ } #define pim_downstream_refresh(src, dp) { \ dp->ds_rtime = time_sec; \ if (dp->ds_timeout != PIM_HOLD_FOREVER) { \ time_t nexp = time_sec + dp->ds_holdtime; \ if (nexp > dp->ds_timeout) \ dp->ds_timeout = nexp; \ } \ if (src->src_timeout < dp->ds_timeout) \ src->src_timeout = dp->ds_timeout; \ } /* * set's the src timeout to that of the highest downstream timeout. * if the entry is an RPT entry and the current timeout */ #define pim_reset_src_timeout(src) { \ downstream_t *dp; \ DOWNSTREAM_LIST(dp, src->src_downstream) { \ if (dp->ds_timeout > src->src_timeout) \ src->src_timeout = dp->ds_timeout; \ } DOWNSTREAM_LIST_END(dp, src->src_downstream); \ if (IS_RPT(src->src_flags) && \ src->src_timeout < time_sec + src->src_holdtime) \ src->src_timeout = time_sec + src->src_holdtime; \ } #define pim_crp_set_timer(src, holdtime) { \ src->src_timeout = src->src_rtime = time_sec; \ src->src_timeout += src->src_holdtime = holdtime; \ } #define pim_src_expired(src) (src->src_timeout != PIM_HOLD_FOREVER && \ time_sec >= src->src_timeout) /************************************************************************* * Join/Prune stuff *************************************************************************/ typedef struct jpentry_ { struct jpentry_ *forw; source_t *src; int join; u_int8 flags; } jpentry_t; typedef struct jplist_ { struct jplist_ *forw; group_t *group; jpentry_t *join; jpentry_t *prune; } jplist_t; #define ENQ_JPLIST(j, l) (j)->forw = (l); l = j #define PRUNE 0 #define JOIN 1 /************************************************************************* * The PIMSM Neighborhood *************************************************************************/ typedef struct pimnbr_ { struct pimnbr_ *forw, *back; sockaddr_un *nbr_addr; /* nbr's ip addr */ #ifdef PROTO_PIMSM struct jplist_ *nbr_jplist; /* the head of the jp list */ #endif time_t nbr_ctime; /* Creation time */ time_t nbr_rtime; /* Time of last refresh */ time_t nbr_holdtime; /* time to keep router active */ time_t nbr_timeout; /* the system time this is expired */ u_int32 nbr_priority; /* the DR priority, hello option 19 */ } pimnbr_t; #define pim_nbrs ifa_ps[RTPROTO_PIM].ips_datas[0] #define pim_ifap_config ifa_ps[RTPROTO_PIM].ips_datas[1] #define pim_if_params ifa_ps[RTPROTO_PIM].ips_datas[2] #define PIMNBR_LIST(nn, list) {\ for (nn = (list)->forw; nn != list; nn = nn->forw) #define PIMNBR_LIST_END(nn, list) if (nn == list) nn = (pimnbr_t *) 0; } #define PIMNBR_LIST_EMPTY(ifap) ((ifap)->pim_nbrs == \ ((pimnbr_t *) (ifap)->pim_nbrs)->forw) #define PIM_DR(ifap) (sockaddr_un *) (((pimnbr_t *) (ifap)->pim_nbrs)->forw->nbr_addr) #define PIM_IS_DR_ADDR(ifap) (sockaddrcmp_in (IFA_UNIQUE_ADDR(ifap), PIM_DR(ifap))) #define PIM_IS_DR(ifap) (BIT_TEST(ifap->ifa_ps[RTPROTO_PIM].ips_state, IFPS_DR_STATUS)) #define PIM_SET_DR(ifap) (BIT_SET(ifap->ifa_ps[RTPROTO_PIM].ips_state, IFPS_DR_STATUS)) /******************************* some externals *******************************/ extern task *pim_task; /* global of all pim tasks */ extern task *krt_task; extern int pim_config_status; /* if PIM SM is enabled in new config */ extern int pim_current_mode; #define PIM_NONE 0 #define PIM_SPARSE 1 #define PIM_DENSE 2 extern adv_entry *pim_int_policy; /* PIM SM control info */ extern adv_entry *pim_comp_policy; /* PIM SM control info */ extern sockaddr_un *pim_all_routers; /* All PIM Group - 224.0.0.13 */ extern sockaddr_un *pim_wildcard; /* 224.0.0.0 */ extern sockaddr_un *pim_wildcard_mask; /* /4 */ extern byte pim_wildcard_masklen; extern time_t pim_default_mrt_period; /* ??? */ extern time_t pim_default_mrt_timeout; /* Data-Timeout 210 */ extern time_t pim_default_hello_period; /* Hello-Period 30 */ extern time_t pim_default_hello_holdtime; /* Hello-Holdtime 105 */ extern time_t pim_default_assert_timeout; /* Assert-timeout 180 */ extern time_t pim_default_jp_period; /* Join/Prune-Period 60 */ extern time_t pim_default_jp_holdtime; /* Join/Prune-Holdtime 210 */ extern time_t pim_default_jp_sup_timeout; /* Join/Prune-Suppression-Timeout (per route) 75 */ extern time_t pim_default_jp_delay_timeout; /* Random-Delay-Join|-Timeout 4.5 */ extern time_t pimsm_default_reg_sup_timeout; /* Register-Suppression-Timer 60 */ extern time_t pimsm_default_probe_period; /* Probe-Time 5 */ extern time_t pimsm_default_crp_period; /* C-RP-Adv-Period 60 */ extern time_t pimsm_default_crp_holdtime; /* RP-Holdtime 150 */ extern time_t pimsm_default_bsr_period; /* Bootstrap-Period 60 */ extern time_t pimsm_default_bsr_timeout; /* Bootstrap-Timeout 130 */ extern u_long pimsm_default_threshold_dr; /* DR switch to the spt */ extern u_long pimsm_default_threshold_rp; /* RP switch to the rp */ extern time_t pimsm_default_threshold_period; /************************************************************************* * TASK-DEPENDENT VARIABLES *************************************************************************/ typedef struct pim_task_data_ { int pim_mode; /* sparse or dense */ mrt_table_t *pim_mrt; /* the mrt for this task (component) */ mrt_table_t *pim_mrttest; /* for testing the mrt */ adv_entry *pim_config_data; /* policy entry from gated.conf */ /* per task timers */ task_timer *pim_mrt_timer; /* timeout route table entries */ time_t pim_mrt_period; /* how often to run mrt_cleanup() */ time_t pim_mrt_timeout; /* active mrt timeout value in secs. */ time_t pim_hello_period; time_t pim_hello_holdtime; task_job *pim_jp_job; /* the j/p job */ task_timer *pim_jp_timer; /* the periodic j/p timer */ time_t pim_jp_period; /* the intvl for period. j/p's */ time_t pim_jp_holdtime; /* how long to hold oif entrys */ time_t pim_jp_sup_timeout; /* jp suppression */ time_t pim_jp_delay_timeout; /* deletion delay */ task_timer *pim_jp_delay_timer; /* the actual timer */ task_job *pim_jp_delay_job; /* random delay job */ mrt_src_list_t *pim_jp_delay_list; /* list of srcs for which jp delay applies */ #ifdef PROTO_PIMDM task_timer *pimdm_graft_retrans_timer; /* timer for graft retransmits */ mrt_src_list_t *pimdm_graft_src_list; /* list of active grafts */ #endif /*PROTO_PIMDM*/ #ifdef PROTO_PIMSM mrt_table_t *pimsm_rpset; /* our rpset */ task_timer *pimsm_rpset_timer; /* rpset timeout routine */ time_t pimsm_rpset_period; /* timeout the rpset */ int pimsm_crp; adv_entry *pimsm_crp_adv; /* c-rp status */ if_addr *pimsm_crp_ifap; /* c-rp ifap (if c-rp) */ addr_list *pimsm_crp_groups; /* groups were c-rp for */ task_timer *pimsm_crp_timer; /* for c-rp's only */ time_t pimsm_crp_period; /* for c-rp sending C-RP-Advs */ time_t pimsm_crp_holdtime; /* how long to hold c-rp in rpset */ sockaddr_un *pimsm_bsr; /* the bsr */ int pimsm_cbsr; /* c-bsr status */ if_addr *pimsm_cbsr_ifap; /* our candidate bsr_ifap (if c-bsr) */ int pimsm_bsr_pri; /* our bsr pri */ if_addr *pimsm_bsr_ifap; /* NULL unless we're the BSR */ time_t pimsm_bsr_period; /* sending rpset */ task_timer *pimsm_bsr_timer; /* for bsr job for elected bsr only */ time_t pimsm_reg_sup_timeout; /* active reg supp timeout */ task_timer *pimsm_probe_timer; /* NULL register probes */ time_t pimsm_probe_period; /* amount of time before reg_sup timeout */ task_job *pimsm_probe_job; /* pointer to a probe job, if scheduled */ mrt_src_list_t *pimsm_probe_list; /* the list of regsup src's to be probed */ task_job *pimsm_assert_job; /* assert job running */ task_timer *pimsm_assert_timer; /* the timer for the asserts */ time_t pimsm_assert_timeout; /* the assert timeouts */ mrt_src_list_t *pimsm_assert_list; /* src's whose iif has changed due to asserts */ mrt_src_list_t *pimsm_null_iif; /* list of src's with null iif's */ task_timer *pimsm_spt_timer; /* periodic timer for DR to switch */ time_t pimsm_spt_period; /* the period to do spt checks */ task_job *pimsm_spt_job; /* the job */ u_long pimsm_threshold_rp; /* bytes/second spt switch for RP */ u_long pimsm_threshold_dr; /* bytes/second spt switch for DR */ #endif /*PROTO_PIMSM*/ } pim_task_data_t; extern int pim_config_status; /* if pim is config'd */ PROTOTYPE (pim_init, extern void, (void)); PROTOTYPE (pim_terminate_component, extern void, (task *)); PROTOTYPE (pim_var_init, extern void, (void)); PROTOTYPE (config_append_dup, extern config_entry *, (config_entry *, config_entry *)); PROTOTYPE (pim_config_enabled, static config_entry **, (task *, if_addr *)); PROTOTYPE (pim_src_refresh, void, (source_t *)); PROTOTYPE (pim_jplist_alloc, jplist_t *, (void)); PROTOTYPE (pim_jpentry_alloc, jpentry_t *, (void)); PROTOTYPE (pim_get_neighbors, extern struct sockaddr_list *, (if_addr *)); PROTOTYPE (pim_nbr_locate, pimnbr_t *, (if_addr *, sockaddr_un *)); PROTOTYPE (ifaddr, extern void, (if_addr *)); PROTOTYPE (eu2sock, extern sockaddr_un *, (euaddr_t *)); PROTOTYPE (inti_pim_vars, extern void, (void)); /* from pim_mib.c */ PROTOTYPE (init_pim_vars, extern void, (void)); #endif /*PIM_INCLUDED*/ #endif /*PROTO_PIM*/