File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / pimdd / pimdd.h
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Jun 12 07:58:55 2017 UTC (7 years, 6 months ago) by misho
Branches: pimdd, MAIN
CVS tags: v0_2_1p0, v0_2_1, HEAD
pimdd-dense 0.2.1.0_2

/*
 *  Copyright (c) 1998 by the University of Oregon.
 *  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 Oregon.
 *  The name of the University of Oregon may not be used to endorse or 
 *  promote products derived from this software without specific prior 
 *  written permission.
 *
 *  THE UNIVERSITY OF OREGON 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 UO, 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.
 */
/*
 *  Questions concerning this software should be directed to 
 *  Kurt Windisch (kurtw@antc.uoregon.edu)
 *
 *  $Id: pimdd.h,v 1.1.1.1 2017/06/12 07:58:55 misho Exp $
 */
/*
 * Part of this program has been derived from PIM sparse-mode pimd.
 * The pimd program is covered by the license in the accompanying file
 * named "LICENSE.pimd".
 *  
 * The pimd program is COPYRIGHT 1998 by University of Southern California.
 *
 * Part of this program has been derived from mrouted.
 * The mrouted program is covered by the license in the accompanying file
 * named "LICENSE.mrouted".
 * 
 * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of
 * Leland Stanford Junior University.
 *
 */

#include <netinet/pim.h>

#define PIM_PROTOCOL_VERSION	2
#define PIMD_VERSION		PIM_PROTOCOL_VERSION
#define PIMD_SUBVERSION         1
#if 0
#define PIM_CONSTANT            0x000eff00      /* constant portion of 'group' field */
#endif
#define PIM_CONSTANT            0
#define PIMD_LEVEL (PIM_CONSTANT | PIMD_VERSION | (PIMD_SUBVERSION << 8))

#define INADDR_ALL_PIM_ROUTERS  (u_int32)0xe000000D	     /* 224.0.0.13 */


/* PIM protocol timers (in seconds) */
#ifndef TIMER_INTERVAL
#define TIMER_INTERVAL		          5 /* virtual timer granularity */
#endif /* TIMER_INTERVAL */

#define PIM_DATA_TIMEOUT                210
#define PIM_TIMER_HELLO_PERIOD 	         30
#define PIM_JOIN_PRUNE_HOLDTIME         210
#define PIM_RANDOM_DELAY_JOIN_TIMEOUT     3
#define PIM_GRAFT_RETRANS_PERIOD          3
#define PIM_TIMER_HELLO_HOLDTIME       (3.5 * PIM_TIMER_HELLO_PERIOD)
#define PIM_ASSERT_TIMEOUT              210


/* Misc definitions */
#define SINGLE_SRC_MSKLEN	         32 /* the single source mask length */
#define SINGLE_GRP_MSKLEN	         32 /* the single group mask length  */
/* TODO: change? */
#define PIM_GROUP_PREFIX_DEFAULT_MASKLEN 16 /* The default group masklen if
					     * omitted in the config file.
					     */

#define UCAST_ROUTING_CHECK_INTERVAL       20 /* Unfortunately, if the unicast
					       * routing changes, the kernel
					       * or any of the existing
					       * unicast routing daemons
					       * don't send us a signal.
					       * Have to ask periodically the
					       * kernel for any route changes.
					       * Default: every 20 seconds.
					       * Sigh.
					       */


#define DEFAULT_PHY_RATE_LIMIT  0             /* default phyint rate limit  */

#define DEFAULT_LOCAL_PREF      101           /* Default assert preference */
#define DEFAULT_LOCAL_METRIC    1024          /* Default assert metric */

/**************************************************************************
 * PIM Encoded-Unicast, Encoded-Group and Encoded-Source Address formats  *
 *************************************************************************/
/* Address families definition */
#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_ETHERNET  ADDRF_802
#define ADDRF_E163      7
#define ADDRF_E164      8
#define ADDRF_SMDS      ADDRF_E164
#define ADDRF_ATM       ADDRF_E164
#define ADDRF_F69       9
#define ADDRF_TELEX     ADDRF_F69
#define ADDRF_X121      10
#define ADDRF_X25       ADDRF_X121
#define ADDRF_IPX       11
#define ADDRF_APPLETALK 12
#define ADDRF_DECNET_IV 13
#define ADDRF_BANYAN    14
#define ADDRF_E164_NSAP 15

/* Addresses Encoding Type (specific for each Address Family */
#define ADDRT_IPv4      0


/* Encoded-Unicast: 6 bytes long */
typedef struct pim_encod_uni_addr_ {
    u_int8      addr_family;
    u_int8      encod_type;
    u_int32     unicast_addr;        /* XXX: Note the 32-bit boundary
				      * misalignment for  the unicast
				      * address when placed in the
				      * memory. Must read it byte-by-byte!
				      */
} pim_encod_uni_addr_t;

/* Encoded-Group */
typedef struct pim_encod_grp_addr_ {
    u_int8      addr_family;
    u_int8      encod_type;
    u_int8      reserved;
    u_int8      masklen;
    u_int32     mcast_addr;
} pim_encod_grp_addr_t;

/* Encoded-Source */
typedef struct pim_encod_src_addr_ {
    u_int8      addr_family;
    u_int8      encod_type;
    u_int8      flags;
    u_int8      masklen;
    u_int32     src_addr;
} pim_encod_src_addr_t;
#define USADDR_RP_BIT 0x1
#define USADDR_WC_BIT 0x2
#define USADDR_S_BIT  0x4

/**************************************************************************
 *                       PIM Messages formats                             *
 *************************************************************************/
/* TODO: XXX: some structures are probably not used at all */

typedef struct pim pim_header_t;

/* PIM Hello */
typedef struct pim_hello_ {
    u_int16     option_type;   /* Option type */
    u_int16     option_length; /* Length of the Option Value field in bytes */
} pim_hello_t;

/* PIM Join/Prune: XXX: all 32-bit addresses misaligned! */
typedef struct pim_jp_header_ {
    pim_encod_uni_addr_t encod_upstream_nbr;
    u_int8     reserved;
    u_int8     num_groups;
    u_int16    holdtime;
} pim_jp_header_t;

typedef struct pim_jp_encod_grp_ {
    pim_encod_grp_addr_t   encod_grp;
    u_int16                number_join_src;
    u_int16                number_prune_src;
} pim_jp_encod_grp_t;

#define PIM_ACTION_NOTHING 0
#define PIM_ACTION_JOIN    1
#define PIM_ACTION_PRUNE   2

#define PIM_IIF_SOURCE     1
#define PIM_IIF_RP         2

#define PIM_ASSERT_RPT_BIT 0x80000000


/* PIM messages type */
#define PIM_HELLO               0
#ifndef PIM_REGISTER
#define PIM_REGISTER            1
#endif
#define PIM_REGISTER_STOP       2
#define PIM_JOIN_PRUNE          3
#define PIM_BOOTSTRAP		4
#define PIM_ASSERT              5
#define PIM_GRAFT               6
#define PIM_GRAFT_ACK           7
#define PIM_CAND_RP_ADV         8

#define PIM_V2_HELLO            PIM_HELLO
#define PIM_V2_REGISTER         PIM_REGISTER
#define PIM_V2_REGISTER_STOP    PIM_REGISTER_STOP
#define PIM_V2_JOIN_PRUNE       PIM_JOIN_PRUNE
#define PIM_V2_BOOTSTRAP	PIM_BOOTSTRAP
#define PIM_V2_ASSERT           PIM_ASSERT
#define PIM_V2_GRAFT            PIM_GRAFT
#define PIM_V2_GRAFT_ACK        PIM_GRAFT_ACK
#define PIM_V2_CAND_RP_ADV      PIM_CAND_RP_ADV

#define PIM_V1_QUERY            0
#define PIM_V1_REGISTER         1
#define PIM_V1_REGISTER_STOP    2
#define PIM_V1_JOIN_PRUNE       3
#define PIM_V1_RP_REACHABILITY  4
#define PIM_V1_ASSERT           5
#define PIM_V1_GRAFT            6
#define PIM_V1_GRAFT_ACK        7

/* Vartious options from PIM messages definitions */
/* PIM_HELLO definitions */
#define PIM_MESSAGE_HELLO_HOLDTIME              1
#define PIM_MESSAGE_HELLO_HOLDTIME_LENGTH       2
#define PIM_MESSAGE_HELLO_HOLDTIME_FOREVER      0xffff


#define MASK_TO_MASKLEN(mask, masklen)                           \
    do {                                                         \
        register u_int32 tmp_mask = ntohl((mask));               \
        register u_int8  tmp_masklen = sizeof((mask)) << 3;      \
        for ( ; tmp_masklen > 0; tmp_masklen--, tmp_mask >>= 1)  \
            if (tmp_mask & 0x1)                                  \
                break;                                           \
        (masklen) = tmp_masklen;                                 \
    } while (0)

#define MASKLEN_TO_MASK(masklen, mask)                                       \
do {                                                                         \
    (mask) = (masklen)? htonl(~0 << ((sizeof((mask)) << 3) - (masklen))) : 0;\
} while (0)


/*
 * A bunch of macros because of the lack of 32-bit boundary alignment.
 * All because of one misalligned address format. Hopefully this will be
 * fixed in PIMv3. (cp) must be (u_int8 *) .
 */
/* Originates from Eddy Rusty's (eddy@isi.edu) PIM-SM implementation for
 * gated.
 */

/* PUT_NETLONG puts "network ordered" data to the datastream.
 * PUT_HOSTLONG puts "host ordered" data to the datastream.
 * GET_NETLONG gets the data and keeps it in "network order" in the memory
 * GET_HOSTLONG gets the data, but in the memory it is in "host order"
 * The same for all {PUT,GET}_{NET,HOST}{SHORT,LONG}
 */
#define GET_BYTE(val, cp)       ((val) = *(cp)++)
#define PUT_BYTE(val, cp)       (*(cp)++ = (u_int8)(val))

#define GET_HOSTSHORT(val, cp)                  \
        do {                                    \
                register u_int16 Xv;            \
                Xv = (*(cp)++) << 8;            \
                Xv |= *(cp)++;                  \
                (val) = Xv;                     \
        } while (0)

#define PUT_HOSTSHORT(val, cp)                  \
        do {                                    \
                register u_int16 Xv;            \
                Xv = (u_int16)(val);            \
                *(cp)++ = (u_int8)(Xv >> 8);    \
                *(cp)++ = (u_int8)Xv;           \
        } while (0)

#if defined(BYTE_ORDER) && (BYTE_ORDER == LITTLE_ENDIAN)
#define GET_NETSHORT(val, cp)                   \
        do {                                    \
                register u_int16 Xv;            \
                Xv = *(cp)++;                   \
                Xv |= (*(cp)++) << 8;           \
                (val) = Xv;                     \
        } while (0)
#define PUT_NETSHORT(val, cp)                   \
        do {                                    \
                register u_int16 Xv;            \
                Xv = (u_int16)(val);            \
                *(cp)++ = (u_int8)Xv;           \
                *(cp)++ = (u_int8)(Xv >> 8);    \
        } while (0)
#else
#define GET_NETSHORT(val, cp) GET_HOSTSHORT(val, cp)
#define PUT_NETSHORT(val, cp) PUT_HOSTSHORT(val, cp)
#endif /* {GET,PUT}_NETSHORT */

#define GET_HOSTLONG(val, cp)                   \
        do {                                    \
                register u_long Xv;             \
                Xv  = (*(cp)++) << 24;          \
                Xv |= (*(cp)++) << 16;          \
                Xv |= (*(cp)++) <<  8;          \
                Xv |= *(cp)++;                  \
                (val) = Xv;                     \
        } while (0)

#define PUT_HOSTLONG(val, cp)                   \
        do {                                    \
                register u_int32 Xv;            \
                Xv = (u_int32)(val);            \
                *(cp)++ = (u_int8)(Xv >> 24);   \
                *(cp)++ = (u_int8)(Xv >> 16);   \
                *(cp)++ = (u_int8)(Xv >>  8);   \
                *(cp)++ = (u_int8)Xv;           \
        } while (0)

#if defined(BYTE_ORDER) && (BYTE_ORDER == LITTLE_ENDIAN)
#define GET_NETLONG(val, cp)                    \
        do {                                    \
                register u_long Xv;             \
                Xv  = *(cp)++;                  \
                Xv |= (*(cp)++) <<  8;          \
                Xv |= (*(cp)++) << 16;          \
                Xv |= (*(cp)++) << 24;          \
                (val) = Xv;                     \
        } while (0)

#define PUT_NETLONG(val, cp)                    \
        do {                                    \
                register u_int32 Xv;            \
                Xv = (u_int32)(val);            \
                *(cp)++ = (u_int8)Xv;           \
                *(cp)++ = (u_int8)(Xv >>  8);   \
                *(cp)++ = (u_int8)(Xv >> 16);   \
                *(cp)++ = (u_int8)(Xv >> 24);   \
        } while (0)
#else
#define GET_NETLONG(val, cp) GET_HOSTLONG(val, cp)
#define PUT_NETLONG(val, cp) PUT_HOSTLONG(val, cp)
#endif /* {GET,PUT}_HOSTLONG */


#define GET_ESADDR(esa, cp)                     \
        do {                                    \
            (esa)->addr_family = *(cp)++;       \
            (esa)->encod_type  = *(cp)++;       \
            (esa)->flags       = *(cp)++;       \
            (esa)->masklen     = *(cp)++;       \
            GET_NETLONG((esa)->src_addr, (cp)); \
        } while(0)

#define PUT_ESADDR(addr, masklen, flags, cp)    \
        do {                                    \
            u_int32 mask;                       \
            MASKLEN_TO_MASK((masklen), mask);   \
            *(cp)++ = ADDRF_IPv4; /* family */  \
            *(cp)++ = ADDRT_IPv4; /* type   */  \
            *(cp)++ = (flags);    /* flags  */  \
            *(cp)++ = (masklen);                \
            PUT_NETLONG((addr) & mask, (cp));   \
        } while(0)

#define GET_EGADDR(ega, cp)                     \
        do {                                    \
            (ega)->addr_family = *(cp)++;       \
            (ega)->encod_type  = *(cp)++;       \
            (ega)->reserved    = *(cp)++;       \
            (ega)->masklen     = *(cp)++;       \
            GET_NETLONG((ega)->mcast_addr, (cp)); \
        } while(0)

#define PUT_EGADDR(addr, masklen, reserved, cp) \
        do {                                    \
            u_int32 mask;                       \
            MASKLEN_TO_MASK((masklen), mask);   \
            *(cp)++ = ADDRF_IPv4; /* family */  \
            *(cp)++ = ADDRT_IPv4; /* type   */  \
            *(cp)++ = (reserved); /* reserved; should be 0 */  \
            *(cp)++ = (masklen);                \
            PUT_NETLONG((addr) & mask, (cp)); \
        } while(0)

#define GET_EUADDR(eua, cp)                     \
        do {                                    \
            (eua)->addr_family = *(cp)++;       \
            (eua)->encod_type  = *(cp)++;       \
            GET_NETLONG((eua)->unicast_addr, (cp)); \
        } while(0)

#define PUT_EUADDR(addr, cp)                    \
        do {                                    \
            *(cp)++ = ADDRF_IPv4; /* family */  \
            *(cp)++ = ADDRT_IPv4; /* type   */  \
            PUT_NETLONG((addr), (cp));          \
        } while(0)


/* TODO: Currently not used. Probably not need at all. Delete! */
#ifdef NOSUCHDEF
/* This is completely IGMP related stuff? */
#define PIM_LEAF_TIMEOUT               (3.5 * IGMP_QUERY_INTERVAL)
#endif /* NOSUCHDEF */

#if (defined(BSDI) || defined(NetBSD) || defined(IRIX))
/*
 * Struct used to communicate from kernel to multicast router
 * note the convenient similarity to an IP packet
 */ 
struct igmpmsg {
    u_long          unused1;
    u_long          unused2;
    u_char          im_msgtype;                 /* what type of message     */
#define IGMPMSG_NOCACHE         1
#define IGMPMSG_WRONGVIF        2
#define IGMPMSG_WHOLEPKT        3               /* used for user level encap*/
    u_char          im_mbz;                     /* must be zero             */
    u_char          im_vif;                     /* vif rec'd on             */
    u_char          unused3;
    struct in_addr  im_src, im_dst;
};
#endif

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>