0fea3d5165
kernel IPv6 multicast routing support. pim6 dense mode daemon pim6 sparse mode daemon netstat support of IPv6 multicast routing statistics Merging to the current and testing with other existing multicast routers is done by Tatsuya Jinmei <jinmei@kame.net>, who writes and maintainances the base code in KAME distribution. Make world check and kernel build check was also successful.
342 lines
15 KiB
C
342 lines
15 KiB
C
/*
|
|
* Copyright (c) 1998 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
|
|
* 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.
|
|
*
|
|
* Other copyrights might apply to parts of this software and are so
|
|
* noted when applicable.
|
|
*
|
|
* $FreeBSD$
|
|
*/
|
|
/*
|
|
* Questions concerning this software should be directed to
|
|
* Mickael Hoerdt (hoerdt@clarinet.u-strasbg.fr) LSIIT Strasbourg.
|
|
*
|
|
*/
|
|
/*
|
|
* This program has been derived from pim6dd.
|
|
* The pim6dd program is covered by the license in the accompanying file
|
|
* named "LICENSE.pim6dd".
|
|
*/
|
|
/*
|
|
* This program has been derived from pimd.
|
|
* The pimd program is covered by the license in the accompanying file
|
|
* named "LICENSE.pimd".
|
|
*
|
|
*/
|
|
|
|
|
|
#ifndef MRT_H
|
|
#define MRT_H
|
|
|
|
#include <sys/param.h>
|
|
#include <sys/time.h>
|
|
#include <sys/types.h>
|
|
#include <sys/socket.h>
|
|
#include <net/route.h>
|
|
#include <netinet/in.h>
|
|
#include <netinet/ip_mroute.h>
|
|
#include <netinet6/ip6_mroute.h>
|
|
#include <string.h>
|
|
#include "defs.h"
|
|
|
|
|
|
/* flags for the mrt entries */
|
|
|
|
#define MRTF_SPT 0x0001 /* iif toward source */
|
|
#define MRTF_WC 0x0002 /* (*,G) entry */
|
|
#define MRTF_RP 0x0004 /* iif toward RP */
|
|
#define MRTF_NEW 0x0008 /* new created routing entry */
|
|
#define MRTF_IIF_REGISTER 0x0020 /* ??? */
|
|
#define MRTF_REGISTER 0x0080 /* ??? */
|
|
#define MRTF_KERNEL_CACHE 0x0200 /* a mirror for the kernel cache */
|
|
#define MRTF_NULL_OIF 0x0400 /* null oif cache.. ??? */
|
|
#define MRTF_REG_SUPP 0x0800 /* register suppress ??? */
|
|
#define MRTF_ASSERTED 0x1000 /* upstream is not that of src ??? */
|
|
#define MRTF_SG 0x2000 /* (S,G) pure, not hanging off of (*,G)*/
|
|
#define MRTF_PMBR 0x4000 /* (*,*,RP) entry (for interop) */
|
|
#define MRTF_MFC_CLONE_SG 0x8000 /* clone (S,G) MFC from (*,G) or (*,*,RP) */
|
|
|
|
#define CREATE TRUE
|
|
#define DONT_CREATE FALSE
|
|
|
|
|
|
#define MFC_MOVE_FORCE 0x1
|
|
#define MFC_UPDATE_FORCE 0x2
|
|
|
|
|
|
/* Macro to duplicate oif info (oif bits, timers) */
|
|
|
|
#define VOIF_COPY(from , to ) \
|
|
do { \
|
|
IF_COPY(&from->joined_oifs , &to->joined_oifs); \
|
|
IF_COPY(&from->oifs ,&to->oifs ); \
|
|
IF_COPY(&from->leaves , &to->leaves); \
|
|
IF_COPY(&from->pruned_oifs , &to->leaves ); \
|
|
IF_COPY(&from->asserted_oifs ,&to->asserted_oifs); \
|
|
bcopy(from->vif_timers , to->vif_timers , \
|
|
numvifs*sizeof(from->vif_timers[0])); \
|
|
bcopy(from->vif_deletion_delay , to->vif_deletion_delay , \
|
|
numvifs*sizeof(from->vif_deletion_delay[0])); \
|
|
} while (0)
|
|
|
|
|
|
#define FREE_MRTENTRY(mrtentry_ptr) \
|
|
do { \
|
|
kernel_cache_t *prev; \
|
|
kernel_cache_t *next; \
|
|
\
|
|
free( (char *)( (mrtentry_ptr)->vif_timers ) ); \
|
|
free( (char *)( (mrtentry_ptr)->vif_deletion_delay ) ); \
|
|
for( next=(mrtentry_ptr)->kernel_cache ; next!=(kernel_cache_t *)NULL ; ) \
|
|
{ \
|
|
prev=next; \
|
|
next=next->next; \
|
|
free(prev); \
|
|
} \
|
|
free( (char *)( (mrtentry_ptr)->kernel_cache ) ); \
|
|
free( (char *)(mrtentry_ptr) ); \
|
|
} while (0)
|
|
|
|
|
|
/*
|
|
* The complicated structure used by the more complicated Join/Prune
|
|
* message building
|
|
*/
|
|
|
|
|
|
typedef struct build_jp_message {
|
|
struct build_jp_message *next; /* Used to chain the free entries */
|
|
u_int8 *jp_message; /* The Join/Prune message */
|
|
u_int32 jp_message_size; /* Size of the Join/Prune message (in bytes) */
|
|
u_int16 holdtime; /* Join/Prune message holdtime field */
|
|
struct sockaddr_in6 curr_group; /* Current group address */
|
|
u_int8 curr_group_msklen; /* Current group masklen */
|
|
u_int8 *join_list; /* The working area for the join addresses */
|
|
u_int32 join_list_size; /* The size of the join_list (in bytes) */
|
|
u_int16 join_addr_number; /* Number of the join addresses in join_list */
|
|
u_int8 *prune_list; /* The working area for the prune addresses */
|
|
u_int32 prune_list_size; /* The size of the prune_list (in bytes) */
|
|
u_int16 prune_addr_number; /* Number of the prune addresses in prune_list*/
|
|
u_int8 *rp_list_join; /* The working area for RP join addresses */
|
|
u_int32 rp_list_join_size; /* The size of the rp_list_join (in bytes) */
|
|
u_int16 rp_list_join_number; /* Number of RP addresses in rp_list_join */
|
|
u_int8 *rp_list_prune; /* The working area for RP prune addresses */
|
|
u_int32 rp_list_prune_size; /* The size of the rp_list_prune (in bytes) */
|
|
u_int16 rp_list_prune_number; /* Number of RP addresses in rp_list_prune */
|
|
u_int8 *num_groups_ptr; /* Pointer to number_of_groups in jp_message */
|
|
} build_jp_message_t;
|
|
|
|
|
|
typedef struct pim_nbr_entry {
|
|
struct pim_nbr_entry *next; /* link to next neighbor */
|
|
struct pim_nbr_entry *prev; /* link to prev neighbor */
|
|
struct sockaddr_in6 address; /* neighbor address */
|
|
vifi_t vifi; /* which interface */
|
|
u_int16 timer; /* for timing out neighbor */
|
|
build_jp_message_t *build_jp_message; /* A structure for fairly
|
|
* complicated Join/Prune
|
|
* message construction.
|
|
*/
|
|
|
|
} pim_nbr_entry_t;
|
|
|
|
typedef struct srcentry {
|
|
struct srcentry *next; /* link to next entry */
|
|
struct srcentry *prev; /* link to prev entry */
|
|
struct sockaddr_in6 address; /* source or RP address */
|
|
struct mrtentry *mrtlink; /* link to routing entries */
|
|
vifi_t incoming; /* incoming vif */
|
|
struct pim_nbr_entry *upstream; /* upstream router */
|
|
u_int32 metric; /* Unicast Routing Metric to the source */
|
|
u_int32 preference; /* The metric preference (for assers)*/
|
|
u_int16 timer; /* Entry timer??? Delete? */
|
|
struct cand_rp *cand_rp; /* Used if this is rpentry_t */
|
|
} srcentry_t;
|
|
typedef srcentry_t rpentry_t;
|
|
|
|
/* (RP<->group) matching table related structures */
|
|
|
|
typedef struct cand_rp {
|
|
struct cand_rp *next; /* Next candidate RP */
|
|
struct cand_rp *prev; /* Previous candidate RP */
|
|
struct rp_grp_entry *rp_grp_next; /* The rp_grp_entry chain for that RP*/
|
|
rpentry_t *rpentry; /* Pointer to the RP entry */
|
|
} cand_rp_t;
|
|
|
|
typedef struct grp_mask {
|
|
struct grp_mask *next;
|
|
struct grp_mask *prev;
|
|
struct rp_grp_entry *grp_rp_next;
|
|
struct sockaddr_in6 group_addr;
|
|
struct in6_addr group_mask;
|
|
struct in6_addr hash_mask;
|
|
u_int16 fragment_tag; /* Used for garbage collection */
|
|
u_int8 group_rp_number; /* Used when assembling segments */
|
|
} grp_mask_t;
|
|
|
|
typedef struct rp_grp_entry {
|
|
struct rp_grp_entry *rp_grp_next; /* Next entry for same RP */
|
|
struct rp_grp_entry *rp_grp_prev; /* Prev entry for same RP */
|
|
struct rp_grp_entry *grp_rp_next; /* Next entry for same grp prefix */
|
|
struct rp_grp_entry *grp_rp_prev; /* Prev entry for same grp prefix */
|
|
struct grpentry *grplink; /* Link to all grps via this entry*/
|
|
u_int16 advholdtime; /* The advertised holdtime */
|
|
u_int16 holdtime; /* The RP holdtime (will be aged) */
|
|
u_int16 fragment_tag; /* The fragment tag from the
|
|
* received BSR message
|
|
*/
|
|
|
|
u_int8 priority; /* The RP priority */
|
|
grp_mask_t *group; /* Pointer to (group,mask) entry */
|
|
cand_rp_t *rp; /* Pointer to the RP */
|
|
} rp_grp_entry_t;
|
|
|
|
typedef struct grpentry {
|
|
struct grpentry *next; /* link to next entry */
|
|
struct grpentry *prev; /* link to prev entry */
|
|
struct grpentry *rpnext; /* next grp for the same RP */
|
|
struct grpentry *rpprev; /* prev grp for the same RP */
|
|
struct sockaddr_in6 group; /* subnet group of multicasts */
|
|
struct sockaddr_in6 rpaddr; /* The IPv6 address of the RP */
|
|
struct mrtentry *mrtlink; /* link to (S,G) routing entries */
|
|
rp_grp_entry_t *active_rp_grp; /* Pointer to the active rp_grp entry*/
|
|
struct mrtentry *grp_route; /* Pointer to the (*,G) routing entry*/
|
|
} grpentry_t;
|
|
|
|
typedef struct mrtentry {
|
|
struct mrtentry *grpnext; /* next entry of same group */
|
|
struct mrtentry *grpprev; /* prev entry of same group */
|
|
struct mrtentry *srcnext; /* next entry of same source */
|
|
struct mrtentry *srcprev; /* prev entry of same source */
|
|
struct grpentry *group; /* pointer to group entry */
|
|
struct srcentry *source; /* pointer to source entry (or RP) */
|
|
vifi_t incoming; /* the iif (either toward S or RP) */
|
|
if_set oifs; /* The current result oifs */
|
|
if_set joined_oifs; /* The joined oifs (Join received) */
|
|
if_set pruned_oifs; /* The pruned oifs (Prune received) */
|
|
if_set asserted_oifs; /* The asserted oifs (lost Assert) */
|
|
if_set leaves; /* Has directly connected members */
|
|
struct pim_nbr_entry *upstream; /* upstream router, needed because
|
|
* of the asserts it may be different
|
|
* than the source (or RP) upstream
|
|
* router.
|
|
*/
|
|
|
|
u_int32 metric; /* Routing Metric for this entry */
|
|
u_int32 preference; /* The metric preference value */
|
|
struct sockaddr_in6 pmbr_addr; /* The PMBR address (for interop) */
|
|
u_int16 *vif_timers; /* vifs timer list */
|
|
u_int16 *vif_deletion_delay; /* vifs deletion delay list */
|
|
|
|
u_int16 flags; /* The MRTF_* flags */
|
|
u_int16 timer; /* entry timer */
|
|
u_int16 jp_timer; /* The Join/Prune timer */
|
|
u_int16 rs_timer; /* Register-Suppression Timer */
|
|
u_int assert_timer;
|
|
u_int assert_rate_timer;
|
|
struct kernel_cache *kernel_cache; /* List of the kernel cache entries */
|
|
#ifdef RSRR
|
|
struct rsrr_cache *rsrr_cache; /* Used to save RSRR requests for
|
|
* routes change notification.
|
|
*/
|
|
#endif /* RSRR */
|
|
|
|
} mrtentry_t;
|
|
|
|
|
|
/*
|
|
* Used to get forwarded data related counts (number of packet, number of
|
|
* bits, etc)
|
|
*/
|
|
|
|
struct sg_count {
|
|
u_quad_t pktcnt; /* Number of packets for (s,g) */
|
|
u_quad_t bytecnt; /* Number of bytes for (s,g) */
|
|
u_quad_t wrong_if; /* Number of packets received on wrong iif for (s,g) */
|
|
};
|
|
|
|
/*
|
|
* Structure to keep track of existing (S,G) MFC entries in the kernel
|
|
* for particular (*,G) or (*,*,RP) entry. We must keep track for
|
|
* each active source which doesn't have (S,G) entry in the daemon's
|
|
* routing table. We need to keep track of such sources for two reasons:
|
|
*
|
|
* (1) If the kernel does not support (*,G) MFC entries (currently, the
|
|
* "official" mcast code doesn't), we must know all installed (s,G) entries
|
|
* in the kernel and modify them if the iif or oif for the (*,G) changes.
|
|
*
|
|
* (2) By checking periodically the traffic coming from the shared tree,
|
|
* we can either delete the idle sources or switch to the shortest path.
|
|
*
|
|
* Note that even if we have (*,G) implemented in the kernel, we still
|
|
* need to have this structure because of (2)
|
|
*/
|
|
|
|
|
|
typedef struct kernel_cache {
|
|
struct kernel_cache *next;
|
|
struct kernel_cache *prev;
|
|
struct sockaddr_in6 source;
|
|
struct sockaddr_in6 group;
|
|
struct sg_count sg_count; /* The (s,g) data retated counters (see above) */
|
|
} kernel_cache_t;
|
|
|
|
struct vif_count {
|
|
u_long icount; /* Input packet count on vif */
|
|
u_long ocount; /* Output packet count on vif */
|
|
u_long ibytes; /* Input byte count on vif */
|
|
u_long obytes; /* Output byte count on vif */
|
|
};
|
|
|
|
/* globals and functions exportations */
|
|
|
|
extern srcentry_t *srclist;
|
|
extern grpentry_t *grplist;
|
|
|
|
extern void init_pim6_mrt __P(());
|
|
extern mrtentry_t *find_route __P((struct sockaddr_in6 *source,
|
|
struct sockaddr_in6 *group,
|
|
u_int16 flags, char create));
|
|
extern grpentry_t *find_group __P((struct sockaddr_in6 *group));
|
|
extern srcentry_t *find_source __P((struct sockaddr_in6 *source));
|
|
extern void delete_mrtentry __P((mrtentry_t *mrtentry_ptr));
|
|
extern void delete_srcentry __P((srcentry_t *srcentry_ptr));
|
|
extern void delete_grpentry __P((grpentry_t *grpentry_ptr));
|
|
extern void delete_mrtentry_all_kernel_cache __P((mrtentry_t *mrtentry_ptr));
|
|
extern void delete_single_kernel_cache __P((mrtentry_t *mrtentry_ptr,
|
|
kernel_cache_t *kernel_cache_ptr));
|
|
extern void delete_single_kernel_cache_addr __P((mrtentry_t *mrtentry_ptr,
|
|
struct sockaddr_in6 *source,
|
|
struct sockaddr_in6 *group));
|
|
extern void add_kernel_cache __P((mrtentry_t *mrtentry_ptr,
|
|
struct sockaddr_in6 *source, struct sockaddr_in6 *group,
|
|
u_int16 flags));
|
|
|
|
|
|
#endif
|