Annotation of embedaddon/pimd/pimd.h, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (c) 1998-2001
3: * University of Southern California/Information Sciences Institute.
4: * All rights reserved.
5: *
6: * Redistribution and use in source and binary forms, with or without
7: * modification, are permitted provided that the following conditions
8: * are met:
9: * 1. Redistributions of source code must retain the above copyright
10: * notice, this list of conditions and the following disclaimer.
11: * 2. Redistributions in binary form must reproduce the above copyright
12: * notice, this list of conditions and the following disclaimer in the
13: * documentation and/or other materials provided with the distribution.
14: * 3. Neither the name of the project nor the names of its contributors
15: * may be used to endorse or promote products derived from this software
16: * without specific prior written permission.
17: *
18: * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
19: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21: * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
22: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28: * SUCH DAMAGE.
29: */
30: /*
31: * $Id: pimd.h,v 1.27 2003/05/21 10:40:28 pavlin Exp $
32: */
33:
34:
35: #include <netdb.h>
36: #include <netinet/pim.h>
37:
38: #define PIM_PROTOCOL_VERSION 2
39: #define PIMD_VERSION PIM_PROTOCOL_VERSION
40: #define PIMD_SUBVERSION 1
41: #if 0
42: #define PIM_CONSTANT 0x000eff00 /* constant portion of 'group' field */
43: #endif
44: #define PIM_CONSTANT 0
45: #define PIMD_LEVEL (PIM_CONSTANT | PIMD_VERSION | (PIMD_SUBVERSION << 8))
46:
47: #define INADDR_ALL_PIM_ROUTERS (uint32_t)0xe000000D /* 224.0.0.13 */
48: #if !defined(INADDR_UNSPEC_GROUP)
49: #define INADDR_UNSPEC_GROUP (uint32_t)0xe0000000 /* 224.0.0.0 */
50: #endif /* !defined(INADDR_UNSPEC_GROUP) */
51:
52:
53: /* PIM protocol timers (in seconds) */
54: #ifndef TIMER_INTERVAL
55: #define TIMER_INTERVAL 5 /* virtual timer granularity */
56: #endif /* TIMER_INTERVAL */
57:
58: #define PIM_REGISTER_SUPPRESSION_TIMEOUT 60
59: #define PIM_REGISTER_PROBE_TIME 5 /* Used to send NULL_REGISTER */
60: #define PIM_DATA_TIMEOUT 210
61:
62: #define PIM_TIMER_HELLO_INTERVAL 30
63: #define PIM_JOIN_PRUNE_PERIOD 60
64: #define PIM_JOIN_PRUNE_HOLDTIME (3.5 * PIM_JOIN_PRUNE_PERIOD)
65: #define PIM_RANDOM_DELAY_JOIN_TIMEOUT 4.5
66:
67: /* TODO: XXX: cannot be shorter than 10 seconds (not in the spec)
68: * MAX: Cisco max value (16383) for ip pim rp-candidate interval. */
69: #define PIM_MIN_CAND_RP_ADV_PERIOD 10
70: #define PIM_DEFAULT_CAND_RP_ADV_PERIOD 60
71: #define PIM_MAX_CAND_RP_ADV_PERIOD 16383
72:
73: /* TODO: 60 is the original value. Temporarily set to 30 for debugging.
74: #define PIM_BOOTSTRAP_PERIOD 60 */
75: #define PIM_BOOTSTRAP_PERIOD 30
76:
77: #define PIM_BOOTSTRAP_TIMEOUT (2.5 * PIM_BOOTSTRAP_PERIOD + 10)
78: #define PIM_TIMER_HELLO_HOLDTIME (3.5 * PIM_TIMER_HELLO_INTERVAL)
79: #define PIM_ASSERT_TIMEOUT 180
80:
81: /* Misc definitions */
82: #define PIM_DEFAULT_CAND_RP_PRIORITY 0 /* 0 is the highest. Don't know
83: * why this is the default.
84: * See the PS version (Mar' 97),
85: * pp.22 bottom of the spec.
86: */
87: #define PIM_MAX_CAND_RP_PRIORITY 255 /* 255 is the highest. */
88:
89: #define PIM_DEFAULT_BSR_PRIORITY 0 /* 0 is the lowest */
90: #define PIM_MAX_CAND_BSR_PRIORITY PIM_MAX_CAND_RP_PRIORITY
91:
92: #define RP_DEFAULT_IPV4_HASHMASKLEN 30 /* the default group msklen used
93: * by the hash function to
94: * calculate the group-to-RP
95: * mapping
96: */
97: #define SINGLE_SRC_MSKLEN 32 /* the single source mask length */
98: #define SINGLE_GRP_MSKLEN 32 /* the single group mask length */
99: #define PIM_GROUP_PREFIX_DEFAULT_MASKLEN 16 /* The default group masklen if
100: * omitted in the config file.
101: * XXX: not set to 4, because
102: * a small mis-configuration
103: * may concentrate all multicast
104: * traffic in a single RP
105: */
106: #define PIM_GROUP_PREFIX_MIN_MASKLEN 4 /* group prefix minimum length */
107:
108: /* Datarate related definitions */
109:
110: /*
111: * This is the threshold for the last hop router, or the RP, to
112: * initiate switching to the shortest path tree. Like Cisco we
113: * change to SPT on first packet to the (S,G), but only after
114: * 100 seconds (Xorp does this and Pavlin knows his PIM-SM-FU)
115: */
116: #define SPT_THRESHOLD_DEFAULT_MODE SPT_PACKETS
117: #define SPT_THRESHOLD_DEFAULT_RATE 0
118: #define SPT_THRESHOLD_DEFAULT_PACKETS 0
119: #define SPT_THRESHOLD_MAX_PACKETS 0
120: #define SPT_THRESHOLD_DEFAULT_INTERVAL 100
121:
122: #define UCAST_ROUTING_CHECK_INTERVAL 20 /* Unfortunately, if the unicast
123: * routing changes, the kernel
124: * or any of the existing
125: * unicast routing daemons
126: * don't send us a signal.
127: * Have to ask periodically the
128: * kernel for any route changes.
129: * Default: every 20 seconds.
130: * Sigh.
131: */
132:
133:
134: #define DEFAULT_PHY_RATE_LIMIT 0 /* default phyint rate limit */
135: #define DEFAULT_REG_RATE_LIMIT 0 /* default register_vif rate limit */
136:
137: /**************************************************************************
138: * PIM Encoded-Unicast, Encoded-Group and Encoded-Source Address formats *
139: *************************************************************************/
140: /* Address families definition */
141: #define ADDRF_RESERVED 0
142: #define ADDRF_IPv4 1
143: #define ADDRF_IPv6 2
144: #define ADDRF_NSAP 3
145: #define ADDRF_HDLC 4
146: #define ADDRF_BBN1822 5
147: #define ADDRF_802 6
148: #define ADDRF_ETHERNET ADDRF_802
149: #define ADDRF_E163 7
150: #define ADDRF_E164 8
151: #define ADDRF_SMDS ADDRF_E164
152: #define ADDRF_ATM ADDRF_E164
153: #define ADDRF_F69 9
154: #define ADDRF_TELEX ADDRF_F69
155: #define ADDRF_X121 10
156: #define ADDRF_X25 ADDRF_X121
157: #define ADDRF_IPX 11
158: #define ADDRF_APPLETALK 12
159: #define ADDRF_DECNET_IV 13
160: #define ADDRF_BANYAN 14
161: #define ADDRF_E164_NSAP 15
162:
163: /* Addresses Encoding Type (specific for each Address Family */
164: #define ADDRT_IPv4 0
165:
166:
167: /* Encoded-Unicast: 6 bytes long */
168: typedef struct pim_encod_uni_addr_ {
169: uint8_t addr_family;
170: uint8_t encod_type;
171: uint32_t unicast_addr; /* XXX: Note the 32-bit boundary
172: * misalignment for the unicast
173: * address when placed in the
174: * memory. Must read it byte-by-byte!
175: */
176: } pim_encod_uni_addr_t;
177: #define PIM_ENCODE_UNI_ADDR_LEN 6
178:
179: /* Encoded-Group */
180: typedef struct pim_encod_grp_addr_ {
181: uint8_t addr_family;
182: uint8_t encod_type;
183: uint8_t reserved;
184: uint8_t masklen;
185: uint32_t mcast_addr;
186: } pim_encod_grp_addr_t;
187: #define PIM_ENCODE_GRP_ADDR_LEN 8
188:
189: /* Encoded-Source */
190: typedef struct pim_encod_src_addr_ {
191: uint8_t addr_family;
192: uint8_t encod_type;
193: uint8_t flags;
194: uint8_t masklen;
195: uint32_t src_addr;
196: } pim_encod_src_addr_t;
197: #define PIM_ENCODE_SRC_ADDR_LEN 8
198:
199: #define USADDR_RP_BIT 0x1
200: #define USADDR_WC_BIT 0x2
201: #define USADDR_S_BIT 0x4
202:
203: /**************************************************************************
204: * PIM Messages formats *
205: *************************************************************************/
206: /* TODO: XXX: some structures are probably not used at all */
207:
208: typedef struct pim pim_header_t;
209:
210: /* PIM Hello */
211: typedef struct pim_hello_ {
212: uint16_t option_type; /* Option type */
213: uint16_t option_length; /* Length of the Option Value field in bytes */
214: } pim_hello_t;
215:
216: /* PIM Register */
217: typedef struct pim_register_ {
218: uint32_t reg_flags;
219: } pim_register_t;
220:
221: /* PIM Register-Stop */
222: typedef struct pim_register_stop_ {
223: pim_encod_grp_addr_t encod_grp;
224: pim_encod_uni_addr_t encod_src; /* XXX: 6 bytes long, misaligned */
225: } pim_register_stop_t;
226:
227: /* PIM Join/Prune: XXX: all 32-bit addresses misaligned! */
228: typedef struct pim_jp_header_ {
229: pim_encod_uni_addr_t encod_upstream_nbr;
230: uint8_t reserved;
231: uint8_t num_groups;
232: uint16_t holdtime;
233: } pim_jp_header_t;
234:
235: typedef struct pim_jp_encod_grp_ {
236: pim_encod_grp_addr_t encod_grp;
237: uint16_t number_join_src;
238: uint16_t number_prune_src;
239: } pim_jp_encod_grp_t;
240:
241: #define PIM_ACTION_NOTHING 0
242: #define PIM_ACTION_JOIN 1
243: #define PIM_ACTION_PRUNE 2
244:
245: #define PIM_IIF_SOURCE 1
246: #define PIM_IIF_RP 2
247:
248: #define PIM_ASSERT_RPT_BIT 0x80000000
249:
250:
251: /* PIM messages type */
252: #ifndef PIM_HELLO
253: #define PIM_HELLO 0
254: #endif
255: #ifndef PIM_REGISTER
256: #define PIM_REGISTER 1
257: #endif
258: #ifndef PIM_REGISTER_STOP
259: #define PIM_REGISTER_STOP 2
260: #endif
261: #ifndef PIM_JOIN_PRUNE
262: #define PIM_JOIN_PRUNE 3
263: #endif
264: #ifndef PIM_BOOTSTRAP
265: #define PIM_BOOTSTRAP 4
266: #endif
267: #ifndef PIM_ASSERT
268: #define PIM_ASSERT 5
269: #endif
270: #ifndef PIM_GRAFT
271: #define PIM_GRAFT 6
272: #endif
273: #ifndef PIM_GRAFT_ACK
274: #define PIM_GRAFT_ACK 7
275: #endif
276: #ifndef PIM_CAND_RP_ADV
277: #define PIM_CAND_RP_ADV 8
278: #endif
279:
280: #define PIM_V2_HELLO PIM_HELLO
281: #define PIM_V2_REGISTER PIM_REGISTER
282: #define PIM_V2_REGISTER_STOP PIM_REGISTER_STOP
283: #define PIM_V2_JOIN_PRUNE PIM_JOIN_PRUNE
284: #define PIM_V2_BOOTSTRAP PIM_BOOTSTRAP
285: #define PIM_V2_ASSERT PIM_ASSERT
286: #define PIM_V2_GRAFT PIM_GRAFT
287: #define PIM_V2_GRAFT_ACK PIM_GRAFT_ACK
288: #define PIM_V2_CAND_RP_ADV PIM_CAND_RP_ADV
289:
290: #define PIM_V1_QUERY 0
291: #define PIM_V1_REGISTER 1
292: #define PIM_V1_REGISTER_STOP 2
293: #define PIM_V1_JOIN_PRUNE 3
294: #define PIM_V1_RP_REACHABILITY 4
295: #define PIM_V1_ASSERT 5
296: #define PIM_V1_GRAFT 6
297: #define PIM_V1_GRAFT_ACK 7
298:
299: /* Vartious options from PIM messages definitions */
300: /* PIM_HELLO definitions */
301: #define PIM_HELLO_HOLDTIME 1
302: #define PIM_HELLO_HOLDTIME_LEN 2
303: #define PIM_HELLO_HOLDTIME_FOREVER 0xffff
304:
305: #define PIM_HELLO_DR_PRIO 19
306: #define PIM_HELLO_DR_PRIO_LEN 4
307: #define PIM_HELLO_DR_PRIO_DEFAULT 1
308:
309: #define PIM_HELLO_GENID 20
310: #define PIM_HELLO_GENID_LEN 4
311:
312: /* PIM_REGISTER definitions */
313: #define PIM_REGISTER_BORDER_BIT 0x80000000
314: #define PIM_REGISTER_NULL_REGISTER_BIT 0x40000000
315:
316:
317: #define MASK_TO_MASKLEN(mask, masklen) \
318: do { \
319: uint32_t tmp_mask = ntohl((mask)); \
320: uint8_t tmp_masklen = sizeof((mask)) << 3; \
321: for ( ; tmp_masklen > 0; tmp_masklen--, tmp_mask >>= 1) \
322: if (tmp_mask & 0x1) \
323: break; \
324: (masklen) = tmp_masklen; \
325: } while (0)
326:
327: #define MASKLEN_TO_MASK(masklen, mask) \
328: do { \
329: (mask) = masklen ? htonl(~0U << ((sizeof(mask) << 3) - (masklen))) : 0; \
330: } while (0)
331:
332:
333: /*
334: * A bunch of macros because of the lack of 32-bit boundary alignment.
335: * All because of one misalligned address format. Hopefully this will be
336: * fixed in PIMv3. (cp) must be (uint8_t *) .
337: */
338: /* Originates from Eddy Rusty's (eddy@isi.edu) PIM-SM implementation for
339: * gated.
340: */
341:
342: #include <sys/types.h>
343: #ifdef HOST_OS_WINDOWS
344: #define LITTLE_ENDIAN 1234
345: #define BYTE_ORDER LITTLE_ENDIAN
346: #endif /* HOST_OS_WINDOWS */
347:
348: #if !defined(BYTE_ORDER)
349: #if defined(__BYTE_ORDER)
350: #define BYTE_ORDER __BYTE_ORDER
351: #define LITTLE_ENDIAN __LITTLE_ENDIAN
352: #define BIG_ENDIAN __BIG_ENDIAN
353: #else
354: #error "BYTE_ORDER not defined! Define it to either LITTLE_ENDIAN (e.g. i386, vax) or BIG_ENDIAN (e.g. 68000, ibm, net) based on your architecture!"
355: #endif
356: #endif
357:
358: /* PUT_NETLONG puts "network ordered" data to the datastream.
359: * PUT_HOSTLONG puts "host ordered" data to the datastream.
360: * GET_NETLONG gets the data and keeps it in "network order" in the memory
361: * GET_HOSTLONG gets the data, but in the memory it is in "host order"
362: * The same for all {PUT,GET}_{NET,HOST}{SHORT,LONG}
363: */
364: #define GET_BYTE(val, cp) ((val) = *(cp)++)
365: #define PUT_BYTE(val, cp) (*(cp)++ = (uint8_t)(val))
366:
367: #define GET_HOSTSHORT(val, cp) \
368: do { \
369: uint16_t Xv; \
370: Xv = (*(cp)++) << 8; \
371: Xv |= *(cp)++; \
372: (val) = Xv; \
373: } while (0)
374:
375: #define PUT_HOSTSHORT(val, cp) \
376: do { \
377: uint16_t Xv; \
378: Xv = (uint16_t)(val); \
379: *(cp)++ = (uint8_t)(Xv >> 8); \
380: *(cp)++ = (uint8_t)Xv; \
381: } while (0)
382:
383: #if defined(BYTE_ORDER) && (BYTE_ORDER == LITTLE_ENDIAN)
384: #define GET_NETSHORT(val, cp) \
385: do { \
386: uint16_t Xv; \
387: Xv = *(cp)++; \
388: Xv |= (*(cp)++) << 8; \
389: (val) = Xv; \
390: } while (0)
391: #define PUT_NETSHORT(val, cp) \
392: do { \
393: uint16_t Xv; \
394: Xv = (uint16_t)(val); \
395: *(cp)++ = (uint8_t)Xv; \
396: *(cp)++ = (uint8_t)(Xv >> 8); \
397: } while (0)
398: #else
399: #define GET_NETSHORT(val, cp) GET_HOSTSHORT(val, cp)
400: #define PUT_NETSHORT(val, cp) PUT_HOSTSHORT(val, cp)
401: #endif /* {GET,PUT}_NETSHORT */
402:
403: #define GET_HOSTLONG(val, cp) \
404: do { \
405: uint32_t Xv; \
406: Xv = (*(cp)++) << 24; \
407: Xv |= (*(cp)++) << 16; \
408: Xv |= (*(cp)++) << 8; \
409: Xv |= *(cp)++; \
410: (val) = Xv; \
411: } while (0)
412:
413: #define PUT_HOSTLONG(val, cp) \
414: do { \
415: uint32_t Xv; \
416: Xv = (uint32_t)(val); \
417: *(cp)++ = (uint8_t)(Xv >> 24); \
418: *(cp)++ = (uint8_t)(Xv >> 16); \
419: *(cp)++ = (uint8_t)(Xv >> 8); \
420: *(cp)++ = (uint8_t)Xv; \
421: } while (0)
422:
423: #if defined(BYTE_ORDER) && (BYTE_ORDER == LITTLE_ENDIAN)
424: #define GET_NETLONG(val, cp) \
425: do { \
426: uint32_t Xv; \
427: Xv = *(cp)++; \
428: Xv |= (*(cp)++) << 8; \
429: Xv |= (*(cp)++) << 16; \
430: Xv |= (*(cp)++) << 24; \
431: (val) = Xv; \
432: } while (0)
433:
434: #define PUT_NETLONG(val, cp) \
435: do { \
436: uint32_t Xv; \
437: Xv = (uint32_t)(val); \
438: *(cp)++ = (uint8_t)Xv; \
439: *(cp)++ = (uint8_t)(Xv >> 8); \
440: *(cp)++ = (uint8_t)(Xv >> 16); \
441: *(cp)++ = (uint8_t)(Xv >> 24); \
442: } while (0)
443: #else
444: #define GET_NETLONG(val, cp) GET_HOSTLONG(val, cp)
445: #define PUT_NETLONG(val, cp) PUT_HOSTLONG(val, cp)
446: #endif /* {GET,PUT}_HOSTLONG */
447:
448:
449: #define GET_ESADDR(esa, cp) \
450: do { \
451: (esa)->addr_family = *(cp)++; \
452: (esa)->encod_type = *(cp)++; \
453: (esa)->flags = *(cp)++; \
454: (esa)->masklen = *(cp)++; \
455: GET_NETLONG((esa)->src_addr, (cp)); \
456: } while(0)
457:
458: #define PUT_ESADDR(addr, masklen, flags, cp) \
459: do { \
460: uint32_t mask; \
461: MASKLEN_TO_MASK((masklen), mask); \
462: *(cp)++ = ADDRF_IPv4; /* family */ \
463: *(cp)++ = ADDRT_IPv4; /* type */ \
464: *(cp)++ = (flags); /* flags */ \
465: *(cp)++ = (masklen); \
466: PUT_NETLONG((addr) & mask, (cp)); \
467: } while(0)
468:
469: #define GET_EGADDR(ega, cp) \
470: do { \
471: (ega)->addr_family = *(cp)++; \
472: (ega)->encod_type = *(cp)++; \
473: (ega)->reserved = *(cp)++; \
474: (ega)->masklen = *(cp)++; \
475: GET_NETLONG((ega)->mcast_addr, (cp)); \
476: } while(0)
477:
478: #define PUT_EGADDR(addr, masklen, reserved, cp) \
479: do { \
480: uint32_t mask; \
481: MASKLEN_TO_MASK((masklen), mask); \
482: *(cp)++ = ADDRF_IPv4; /* family */ \
483: *(cp)++ = ADDRT_IPv4; /* type */ \
484: *(cp)++ = (reserved); /* reserved; should be 0 */ \
485: *(cp)++ = (masklen); \
486: PUT_NETLONG((addr) & mask, (cp)); \
487: } while(0)
488:
489: #define GET_EUADDR(eua, cp) \
490: do { \
491: (eua)->addr_family = *(cp)++; \
492: (eua)->encod_type = *(cp)++; \
493: GET_NETLONG((eua)->unicast_addr, (cp)); \
494: } while(0)
495:
496: #define PUT_EUADDR(addr, cp) \
497: do { \
498: *(cp)++ = ADDRF_IPv4; /* family */ \
499: *(cp)++ = ADDRT_IPv4; /* type */ \
500: PUT_NETLONG((addr), (cp)); \
501: } while(0)
502:
503: /* Check if group is in PIM-SSM range, x must be in network byte order */
504: #define IN_PIM_SSM_RANGE(x) ((ntohl((unsigned)(x)) & 0xff000000) == 0xe8000000)
505:
506: /* Check if address is in link-local range, x must be in network byte order */
507: #define IN_LINK_LOCAL_RANGE(x) ((ntohl((unsigned)(x)) & 0xffff0000) == 0xa9fe0000)
508:
509: /* TODO: Currently not used. Probably not need at all. Delete! */
510: #if 0
511: /* This is completely IGMP related stuff? */
512: #define PIM_LEAF_TIMEOUT (3.5 * IGMP_QUERY_INTERVAL)
513:
514: #define PIM_REGISTER_BIT_TIMEOUT 30 /* TODO: check if need to be 60 */
515:
516: #define PIM_ASSERT_RATE_TIMER 15
517: #endif /* 0 */
518:
519: #if (defined(__bsdi__) || defined(NetBSD) || defined(OpenBSD) || defined(IRIX))
520: /*
521: * Struct used to communicate from kernel to multicast router
522: * note the convenient similarity to an IP packet
523: */
524: struct igmpmsg {
525: uint32_t unused1;
526: uint32_t unused2;
527: uint8_t im_msgtype; /* what type of message */
528: #define IGMPMSG_NOCACHE 1
529: #define IGMPMSG_WRONGVIF 2
530: #define IGMPMSG_WHOLEPKT 3 /* used for user level encap*/
531: uint8_t im_mbz; /* must be zero */
532: uint8_t im_vif; /* vif rec'd on */
533: uint8_t unused3;
534: struct in_addr im_src, im_dst;
535: };
536: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>