1 /*
2 * Copyright (c) 2017, The OpenThread Authors.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. Neither the name of the copyright holder nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 /**
30 * @file
31 * This file implements Filter IEEE 802.15.4 frame filtering based on MAC address.
32 */
33
34 #include "mac_filter.hpp"
35
36 #if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
37
38 #include "common/array.hpp"
39 #include "common/as_core_type.hpp"
40 #include "common/code_utils.hpp"
41
42 namespace ot {
43 namespace Mac {
44
Filter(void)45 Filter::Filter(void)
46 : mMode(kModeRssInOnly)
47 , mDefaultRssIn(kFixedRssDisabled)
48 {
49 for (FilterEntry &entry : mFilterEntries)
50 {
51 entry.mFiltered = false;
52 entry.mRssIn = kFixedRssDisabled;
53 }
54 }
55
FindEntry(const ExtAddress & aExtAddress)56 Filter::FilterEntry *Filter::FindEntry(const ExtAddress &aExtAddress)
57 {
58 FilterEntry *rval = nullptr;
59
60 for (FilterEntry &entry : mFilterEntries)
61 {
62 if (entry.IsInUse() && (aExtAddress == entry.mExtAddress))
63 {
64 ExitNow(rval = &entry);
65 }
66 }
67
68 exit:
69 return rval;
70 }
71
FindAvailableEntry(void)72 Filter::FilterEntry *Filter::FindAvailableEntry(void)
73 {
74 FilterEntry *rval = nullptr;
75
76 for (FilterEntry &entry : mFilterEntries)
77 {
78 if (!entry.IsInUse())
79 {
80 ExitNow(rval = &entry);
81 }
82 }
83
84 exit:
85 return rval;
86 }
87
AddAddress(const ExtAddress & aExtAddress)88 Error Filter::AddAddress(const ExtAddress &aExtAddress)
89 {
90 Error error = kErrorNone;
91 FilterEntry *entry = FindEntry(aExtAddress);
92
93 if (entry == nullptr)
94 {
95 VerifyOrExit((entry = FindAvailableEntry()) != nullptr, error = kErrorNoBufs);
96 entry->mExtAddress = aExtAddress;
97 }
98
99 entry->mFiltered = true;
100
101 exit:
102 return error;
103 }
104
RemoveAddress(const ExtAddress & aExtAddress)105 void Filter::RemoveAddress(const ExtAddress &aExtAddress)
106 {
107 FilterEntry *entry = FindEntry(aExtAddress);
108
109 if (entry != nullptr)
110 {
111 entry->mFiltered = false;
112 }
113 }
114
ClearAddresses(void)115 void Filter::ClearAddresses(void)
116 {
117 for (FilterEntry &entry : mFilterEntries)
118 {
119 entry.mFiltered = false;
120 }
121 }
122
GetNextAddress(Iterator & aIterator,Entry & aEntry) const123 Error Filter::GetNextAddress(Iterator &aIterator, Entry &aEntry) const
124 {
125 Error error = kErrorNotFound;
126
127 for (; aIterator < GetArrayLength(mFilterEntries); aIterator++)
128 {
129 const FilterEntry &entry = mFilterEntries[aIterator];
130
131 if (entry.mFiltered)
132 {
133 aEntry.mExtAddress = entry.mExtAddress;
134 aEntry.mRssIn = entry.mRssIn;
135 error = kErrorNone;
136 aIterator++;
137 break;
138 }
139 }
140
141 return error;
142 }
143
AddRssIn(const ExtAddress & aExtAddress,int8_t aRss)144 Error Filter::AddRssIn(const ExtAddress &aExtAddress, int8_t aRss)
145 {
146 Error error = kErrorNone;
147 FilterEntry *entry = FindEntry(aExtAddress);
148
149 if (entry == nullptr)
150 {
151 entry = FindAvailableEntry();
152 VerifyOrExit(entry != nullptr, error = kErrorNoBufs);
153
154 entry->mExtAddress = aExtAddress;
155 }
156
157 entry->mRssIn = aRss;
158
159 exit:
160 return error;
161 }
162
RemoveRssIn(const ExtAddress & aExtAddress)163 void Filter::RemoveRssIn(const ExtAddress &aExtAddress)
164 {
165 FilterEntry *entry = FindEntry(aExtAddress);
166
167 VerifyOrExit(entry != nullptr);
168
169 entry->mRssIn = kFixedRssDisabled;
170
171 exit:
172 return;
173 }
174
ClearAllRssIn(void)175 void Filter::ClearAllRssIn(void)
176 {
177 for (FilterEntry &entry : mFilterEntries)
178 {
179 entry.mRssIn = kFixedRssDisabled;
180 }
181
182 mDefaultRssIn = kFixedRssDisabled;
183 }
184
GetNextRssIn(Iterator & aIterator,Entry & aEntry)185 Error Filter::GetNextRssIn(Iterator &aIterator, Entry &aEntry)
186 {
187 Error error = kErrorNotFound;
188
189 for (; aIterator < GetArrayLength(mFilterEntries); aIterator++)
190 {
191 FilterEntry &entry = mFilterEntries[aIterator];
192
193 if (entry.mRssIn != kFixedRssDisabled)
194 {
195 aEntry.mExtAddress = entry.mExtAddress;
196 aEntry.mRssIn = entry.mRssIn;
197 error = kErrorNone;
198 aIterator++;
199 ExitNow();
200 }
201 }
202
203 // Return the default RssIn at the end of list
204 if ((aIterator == GetArrayLength(mFilterEntries)) && (mDefaultRssIn != kFixedRssDisabled))
205 {
206 AsCoreType(&aEntry.mExtAddress).Fill(0xff);
207 aEntry.mRssIn = mDefaultRssIn;
208 error = kErrorNone;
209 aIterator++;
210 }
211
212 exit:
213 return error;
214 }
215
Apply(const ExtAddress & aExtAddress,int8_t & aRss)216 Error Filter::Apply(const ExtAddress &aExtAddress, int8_t &aRss)
217 {
218 Error error = kErrorNone;
219 FilterEntry *entry = FindEntry(aExtAddress);
220 bool isInFilterList;
221
222 // Use the default RssIn setting for all receiving messages first.
223 aRss = mDefaultRssIn;
224
225 // In allowlist mode, entry must be present in the list, in
226 // denylist mode it must not be present.
227
228 isInFilterList = (entry != nullptr) && entry->mFiltered;
229
230 switch (mMode)
231 {
232 case kModeRssInOnly:
233 break;
234
235 case kModeAllowlist:
236 VerifyOrExit(isInFilterList, error = kErrorAddressFiltered);
237 break;
238
239 case kModeDenylist:
240 VerifyOrExit(!isInFilterList, error = kErrorAddressFiltered);
241 break;
242 }
243
244 if ((entry != nullptr) && (entry->mRssIn != kFixedRssDisabled))
245 {
246 aRss = entry->mRssIn;
247 }
248
249 exit:
250 return error;
251 }
252
253 } // namespace Mac
254 } // namespace ot
255
256 #endif // OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
257