]>
Commit | Line | Data |
---|---|---|
acddc0ed | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
12e41d03 | 2 | /* |
896014f4 DL |
3 | * PIM for Quagga |
4 | * Copyright (C) 2008 Everton da Silva Marques | |
896014f4 | 5 | */ |
12e41d03 DL |
6 | |
7 | #include <zebra.h> | |
8 | ||
9 | #include "log.h" | |
b815998a | 10 | #include "prefix.h" |
b0f525a8 | 11 | #include "plist.h" |
12e41d03 DL |
12 | |
13 | #include "pim_util.h" | |
14 | ||
15 | /* | |
16 | RFC 3376: 4.1.7. QQIC (Querier's Query Interval Code) | |
d62a17ae | 17 | |
12e41d03 DL |
18 | If QQIC < 128, QQI = QQIC |
19 | If QQIC >= 128, QQI = (mant | 0x10) << (exp + 3) | |
d62a17ae | 20 | |
12e41d03 DL |
21 | 0 1 2 3 4 5 6 7 |
22 | +-+-+-+-+-+-+-+-+ | |
23 | |1| exp | mant | | |
24 | +-+-+-+-+-+-+-+-+ | |
d62a17ae | 25 | |
12e41d03 DL |
26 | Since exp=0..7 then (exp+3)=3..10, then QQI has |
27 | one of the following bit patterns: | |
d62a17ae | 28 | |
12e41d03 DL |
29 | exp=0: QQI = 0000.0000.1MMM.M000 |
30 | exp=1: QQI = 0000.0001.MMMM.0000 | |
31 | ... | |
32 | exp=6: QQI = 001M.MMM0.0000.0000 | |
33 | exp=7: QQI = 01MM.MM00.0000.0000 | |
34 | --------- --------- | |
35 | 0x4 0x0 0x0 0x0 | |
36 | */ | |
37 | uint8_t igmp_msg_encode16to8(uint16_t value) | |
38 | { | |
d62a17ae | 39 | uint8_t code; |
40 | ||
41 | if (value < 128) { | |
42 | code = value; | |
43 | } else { | |
44 | uint16_t mask = 0x4000; | |
45 | uint8_t exp; | |
46 | uint16_t mant; | |
47 | for (exp = 7; exp > 0; --exp) { | |
48 | if (mask & value) | |
49 | break; | |
50 | mask >>= 1; | |
51 | } | |
52 | mant = 0x000F & (value >> (exp + 3)); | |
53 | code = ((uint8_t)1 << 7) | ((uint8_t)exp << 4) | (uint8_t)mant; | |
54 | } | |
55 | ||
56 | return code; | |
12e41d03 DL |
57 | } |
58 | ||
59 | /* | |
60 | RFC 3376: 4.1.7. QQIC (Querier's Query Interval Code) | |
d62a17ae | 61 | |
12e41d03 DL |
62 | If QQIC < 128, QQI = QQIC |
63 | If QQIC >= 128, QQI = (mant | 0x10) << (exp + 3) | |
d62a17ae | 64 | |
12e41d03 DL |
65 | 0 1 2 3 4 5 6 7 |
66 | +-+-+-+-+-+-+-+-+ | |
67 | |1| exp | mant | | |
68 | +-+-+-+-+-+-+-+-+ | |
69 | */ | |
70 | uint16_t igmp_msg_decode8to16(uint8_t code) | |
71 | { | |
d62a17ae | 72 | uint16_t value; |
73 | ||
74 | if (code < 128) { | |
75 | value = code; | |
76 | } else { | |
77 | uint16_t mant = (code & 0x0F); | |
78 | uint8_t exp = (code & 0x70) >> 4; | |
79 | value = (mant | 0x10) << (exp + 3); | |
80 | } | |
81 | ||
82 | return value; | |
12e41d03 DL |
83 | } |
84 | ||
85 | void pim_pkt_dump(const char *label, const uint8_t *buf, int size) | |
86 | { | |
d62a17ae | 87 | zlog_debug("%s: pkt dump size=%d", label, size); |
88 | zlog_hexdump(buf, size); | |
12e41d03 | 89 | } |
b815998a | 90 | |
d62a17ae | 91 | int pim_is_group_224_0_0_0_24(struct in_addr group_addr) |
06d1c450 | 92 | { |
d62a17ae | 93 | static int first = 1; |
94 | static struct prefix group_224; | |
95 | struct prefix group; | |
06d1c450 | 96 | |
d62a17ae | 97 | if (first) { |
2e8345c1 DS |
98 | if (!str2prefix("224.0.0.0/24", &group_224)) |
99 | return 0; | |
d62a17ae | 100 | first = 0; |
101 | } | |
06d1c450 | 102 | |
d62a17ae | 103 | group.family = AF_INET; |
104 | group.u.prefix4 = group_addr; | |
936fbaef | 105 | group.prefixlen = IPV4_MAX_BITLEN; |
06d1c450 | 106 | |
d62a17ae | 107 | return prefix_match(&group_224, &group); |
06d1c450 DS |
108 | } |
109 | ||
d62a17ae | 110 | int pim_is_group_224_4(struct in_addr group_addr) |
b815998a | 111 | { |
d62a17ae | 112 | static int first = 1; |
113 | static struct prefix group_all; | |
114 | struct prefix group; | |
b815998a | 115 | |
d62a17ae | 116 | if (first) { |
2e8345c1 DS |
117 | if (!str2prefix("224.0.0.0/4", &group_all)) |
118 | return 0; | |
d62a17ae | 119 | first = 0; |
120 | } | |
b815998a | 121 | |
d62a17ae | 122 | group.family = AF_INET; |
123 | group.u.prefix4 = group_addr; | |
12256b84 | 124 | group.prefixlen = IPV4_MAX_BITLEN; |
b815998a | 125 | |
d62a17ae | 126 | return prefix_match(&group_all, &group); |
b815998a | 127 | } |
b0f525a8 | 128 | |
80d9fa1e | 129 | bool pim_is_group_filtered(struct pim_interface *pim_ifp, pim_addr *grp) |
b0f525a8 QY |
130 | { |
131 | struct prefix grp_pfx; | |
132 | struct prefix_list *pl; | |
133 | ||
134 | if (!pim_ifp->boundary_oil_plist) | |
135 | return false; | |
136 | ||
80d9fa1e | 137 | pim_addr_to_prefix(&grp_pfx, *grp); |
b0f525a8 | 138 | |
80d9fa1e | 139 | pl = prefix_list_lookup(PIM_AFI, pim_ifp->boundary_oil_plist); |
ab2f9e89 DL |
140 | return pl ? prefix_list_apply_ext(pl, NULL, &grp_pfx, true) == |
141 | PREFIX_DENY | |
142 | : false; | |
b0f525a8 | 143 | } |
c6ced474 MR |
144 | |
145 | ||
146 | /* This function returns all multicast group */ | |
147 | int pim_get_all_mcast_group(struct prefix *prefix) | |
148 | { | |
149 | #if PIM_IPV == 4 | |
150 | if (!str2prefix("224.0.0.0/4", prefix)) | |
151 | return 0; | |
152 | #else | |
153 | if (!str2prefix("FF00::0/8", prefix)) | |
154 | return 0; | |
155 | #endif | |
156 | return 1; | |
157 | } | |
dce0f746 SP |
158 | |
159 | bool pim_addr_is_multicast(pim_addr addr) | |
160 | { | |
161 | #if PIM_IPV == 4 | |
8083e713 | 162 | if (IN_MULTICAST(ntohl(addr.s_addr))) |
dce0f746 SP |
163 | return true; |
164 | #else | |
165 | if (IN6_IS_ADDR_MULTICAST(&addr)) | |
166 | return true; | |
167 | #endif | |
168 | return false; | |
169 | } |