/* $Id: pim_def.h,v 1.1 1999/08/23 16:18:36 naamato Exp $ */
/*
 * Copyright(c) 1998 by Hitachi.Ltd All rights reserved.
 *
 */

#ifndef IPPROTO_PIM
#define IPPROTO_PIM                     103     /* for lacking in.h */
#endif  IPPROTO_PIM

#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

#define PIM_VERSION     2
#define ALL_PIM_ROUTERS 0xe000000d
#define HELLO_OPTION_HOLDTIME 0
#define HELLO_HOLDTIME  1
#define HELLO_HOLDTIME_LEN  2
#define DEFAULT_HOLDTIME  105
#define PIM_HELLO_INTERVAL 35

#define PIM_RP_HOLDTIME 150
#define PIM_JOIN_PRUNE_PERIOD  60
#define PIM_JOIN_PRUNE_HOLDTIME  210 /* 3.5 * PIM_JOIN_PRUNE_PERIOD */

#define PIM_BOOTSTRAP_PERIOD  60
#define PIM_BOOTSTRAP_TIMEOUT 150  /* 2.5 * PIM_BOOTSTRAP_PERIOD */
#define DEFAULT_HASHMASK_LEN 30

#define PIM_CRP_ADV_PERIOD  60

#define PIM_TTL  1

#define USADDR_RP_BIT 0x1
#define USADDR_WC_BIT 0x2
#define USADDR_S_BIT  0x4

#define REGISTER_PMBR_BIT  0x80000000
#define REGISTER_NULL_BIT  0x40000000

#define ASSERT_RPT_BIT 0x80000000

#define INADDR_ANY_SRC  0x00000000

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

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

#if defined(BYTE_ORDER) && (BYTE_ORDER == LITTLE_ENDIAN)
#define PUT_NETLONG(val, cp)                    \
        do {                                    \
                register u_long Xv;            \
                Xv = (u_long)(val);            \
                *(cp)++ = (u_char)Xv;           \
                *(cp)++ = (u_char)(Xv >>  8);   \
                *(cp)++ = (u_char)(Xv >> 16);   \
                *(cp)++ = (u_char)(Xv >> 24);   \
        } while (0)
#else
#define PUT_NETLONG(val,cp)  PUT_HOSTLONG(val,cp)
#endif

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

#define PUT_EADDR(addr, mask, cp) \
        do {                                    \
            *(cp)++ = 1; /* family */  \
            *(cp)++ = 0; /* type   */  \
            *(cp)++ = 0; /* reserved; should be 0 */  \
            *(cp)++ = mask_bits(addr,mask);                \
            PUT_NETLONG((addr) & htonl(mask), (cp)); \
	} while(0)

#define PUT_ESADDR(addr, mask, flags, cp)    \
        do {                                    \
            *(cp)++ = 1; /* family */  \
            *(cp)++ = 0; /* type   */  \
            *(cp)++ = (flags);    /* flags  */  \
            *(cp)++ = mask_bits(addr,mask);                \
            PUT_NETLONG((addr) & mask, (cp));   \
        } while(0)

#define mask_prefix(mask, len)    \
        while(len--) {  \
            mask = (mask >> 1) | 0x80000000l;  \
	}

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

#define GET_NETLONG(val, cp)    \
        do {     \
		u_char *Xvp;   \
                u_long Xv;              \
                Xvp = (u_char *) &Xv;   \
                *Xvp++ = *(cp)++;       \
                *Xvp++ = *(cp)++;       \
                *Xvp++ = *(cp)++;       \
                *Xvp++ = *(cp)++;       \
                (val) = Xv;             \
        } while(0)

#define GET_EADDR(ea, cp)       \
        do {   \
                struct pim_eaddr *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 GET_EADDR_SOCK(eaddr, addr, mask, cp)  \
        {   \
               struct pim_eaddr *Yea = (eaddr);    \
               int mlen;                            \
               GET_EADDR(Yea, cp);                  \
               addr.s_addr = (u_long)Yea->ea_addr;  \
	       mlen = Yea->ea_masklen;              \
	       mask.s_addr = 0;                     \
               mask_prefix(mask.s_addr, mlen);      \
        }

#define GET_EUADDR(eu, cp)      \
        do {  \
                struct pim_euaddr *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)   \
        {     \
                struct pim_euaddr *Yea = (eaddr);    \
                GET_EUADDR(Yea, cp);                 \
                addr.s_addr = (u_long)Yea->eu_addr; \
	}

