Line data Source code
1 : /*
2 : * PIM for Quagga
3 : * Copyright (C) 2008 Everton da Silva Marques
4 : *
5 : * This program is free software; you can redistribute it and/or modify
6 : * it under the terms of the GNU General Public License as published by
7 : * the Free Software Foundation; either version 2 of the License, or
8 : * (at your option) any later version.
9 : *
10 : * This program is distributed in the hope that it will be useful, but
11 : * WITHOUT ANY WARRANTY; without even the implied warranty of
12 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 : * General Public License for more details.
14 : *
15 : * You should have received a copy of the GNU General Public License along
16 : * with this program; see the file COPYING; if not, write to the Free Software
17 : * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 : */
19 :
20 : #include <zebra.h>
21 :
22 : #include "log.h"
23 : #include "prefix.h"
24 : #include "plist.h"
25 :
26 : #include "pim_util.h"
27 :
28 : /*
29 : RFC 3376: 4.1.7. QQIC (Querier's Query Interval Code)
30 :
31 : If QQIC < 128, QQI = QQIC
32 : If QQIC >= 128, QQI = (mant | 0x10) << (exp + 3)
33 :
34 : 0 1 2 3 4 5 6 7
35 : +-+-+-+-+-+-+-+-+
36 : |1| exp | mant |
37 : +-+-+-+-+-+-+-+-+
38 :
39 : Since exp=0..7 then (exp+3)=3..10, then QQI has
40 : one of the following bit patterns:
41 :
42 : exp=0: QQI = 0000.0000.1MMM.M000
43 : exp=1: QQI = 0000.0001.MMMM.0000
44 : ...
45 : exp=6: QQI = 001M.MMM0.0000.0000
46 : exp=7: QQI = 01MM.MM00.0000.0000
47 : --------- ---------
48 : 0x4 0x0 0x0 0x0
49 : */
50 55 : uint8_t igmp_msg_encode16to8(uint16_t value)
51 : {
52 55 : uint8_t code;
53 :
54 55 : if (value < 128) {
55 55 : code = value;
56 : } else {
57 : uint16_t mask = 0x4000;
58 : uint8_t exp;
59 : uint16_t mant;
60 0 : for (exp = 7; exp > 0; --exp) {
61 0 : if (mask & value)
62 : break;
63 0 : mask >>= 1;
64 : }
65 0 : mant = 0x000F & (value >> (exp + 3));
66 0 : code = ((uint8_t)1 << 7) | ((uint8_t)exp << 4) | (uint8_t)mant;
67 : }
68 :
69 55 : return code;
70 : }
71 :
72 : /*
73 : RFC 3376: 4.1.7. QQIC (Querier's Query Interval Code)
74 :
75 : If QQIC < 128, QQI = QQIC
76 : If QQIC >= 128, QQI = (mant | 0x10) << (exp + 3)
77 :
78 : 0 1 2 3 4 5 6 7
79 : +-+-+-+-+-+-+-+-+
80 : |1| exp | mant |
81 : +-+-+-+-+-+-+-+-+
82 : */
83 84 : uint16_t igmp_msg_decode8to16(uint8_t code)
84 : {
85 84 : uint16_t value;
86 :
87 84 : if (code < 128) {
88 84 : value = code;
89 : } else {
90 0 : uint16_t mant = (code & 0x0F);
91 0 : uint8_t exp = (code & 0x70) >> 4;
92 0 : value = (mant | 0x10) << (exp + 3);
93 : }
94 :
95 84 : return value;
96 : }
97 :
98 0 : void pim_pkt_dump(const char *label, const uint8_t *buf, int size)
99 : {
100 0 : zlog_debug("%s: pkt dump size=%d", label, size);
101 0 : zlog_hexdump(buf, size);
102 0 : }
103 :
104 0 : int pim_is_group_224_0_0_0_24(struct in_addr group_addr)
105 : {
106 0 : static int first = 1;
107 0 : static struct prefix group_224;
108 0 : struct prefix group;
109 :
110 0 : if (first) {
111 0 : if (!str2prefix("224.0.0.0/24", &group_224))
112 : return 0;
113 0 : first = 0;
114 : }
115 :
116 0 : group.family = AF_INET;
117 0 : group.u.prefix4 = group_addr;
118 0 : group.prefixlen = IPV4_MAX_BITLEN;
119 :
120 0 : return prefix_match(&group_224, &group);
121 : }
122 :
123 0 : int pim_is_group_224_4(struct in_addr group_addr)
124 : {
125 0 : static int first = 1;
126 0 : static struct prefix group_all;
127 0 : struct prefix group;
128 :
129 0 : if (first) {
130 0 : if (!str2prefix("224.0.0.0/4", &group_all))
131 : return 0;
132 0 : first = 0;
133 : }
134 :
135 0 : group.family = AF_INET;
136 0 : group.u.prefix4 = group_addr;
137 0 : group.prefixlen = IPV4_MAX_BITLEN;
138 :
139 0 : return prefix_match(&group_all, &group);
140 : }
141 :
142 4 : bool pim_is_group_filtered(struct pim_interface *pim_ifp, pim_addr *grp)
143 : {
144 4 : struct prefix grp_pfx;
145 4 : struct prefix_list *pl;
146 :
147 4 : if (!pim_ifp->boundary_oil_plist)
148 : return false;
149 :
150 0 : pim_addr_to_prefix(&grp_pfx, *grp);
151 :
152 0 : pl = prefix_list_lookup(PIM_AFI, pim_ifp->boundary_oil_plist);
153 0 : return pl ? prefix_list_apply_ext(pl, NULL, &grp_pfx, true) ==
154 : PREFIX_DENY
155 0 : : false;
156 : }
157 :
158 :
159 : /* This function returns all multicast group */
160 4 : int pim_get_all_mcast_group(struct prefix *prefix)
161 : {
162 : #if PIM_IPV == 4
163 : if (!str2prefix("224.0.0.0/4", prefix))
164 : return 0;
165 : #else
166 4 : if (!str2prefix("FF00::0/8", prefix))
167 0 : return 0;
168 : #endif
169 : return 1;
170 : }
171 :
172 0 : bool pim_addr_is_multicast(pim_addr addr)
173 : {
174 : #if PIM_IPV == 4
175 : if (IN_MULTICAST(addr.s_addr))
176 : return true;
177 : #else
178 0 : if (IN6_IS_ADDR_MULTICAST(&addr))
179 0 : return true;
180 : #endif
181 : return false;
182 : }
|