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/code_utils.hpp"
39
40 namespace ot {
41 namespace Mac {
42
Filter(void)43 Filter::Filter(void)
44 : mMode(kModeRssInOnly)
45 , mDefaultRssIn(kFixedRssDisabled)
46 {
47 for (FilterEntry &entry : mFilterEntries)
48 {
49 entry.mFiltered = false;
50 entry.mRssIn = kFixedRssDisabled;
51 }
52 }
53
FindEntry(const ExtAddress & aExtAddress)54 Filter::FilterEntry *Filter::FindEntry(const ExtAddress &aExtAddress)
55 {
56 FilterEntry *rval = nullptr;
57
58 for (FilterEntry &entry : mFilterEntries)
59 {
60 if (entry.IsInUse() && (aExtAddress == entry.mExtAddress))
61 {
62 ExitNow(rval = &entry);
63 }
64 }
65
66 exit:
67 return rval;
68 }
69
FindAvailableEntry(void)70 Filter::FilterEntry *Filter::FindAvailableEntry(void)
71 {
72 FilterEntry *rval = nullptr;
73
74 for (FilterEntry &entry : mFilterEntries)
75 {
76 if (!entry.IsInUse())
77 {
78 ExitNow(rval = &entry);
79 }
80 }
81
82 exit:
83 return rval;
84 }
85
AddAddress(const ExtAddress & aExtAddress)86 Error Filter::AddAddress(const ExtAddress &aExtAddress)
87 {
88 Error error = kErrorNone;
89 FilterEntry *entry = FindEntry(aExtAddress);
90
91 if (entry == nullptr)
92 {
93 VerifyOrExit((entry = FindAvailableEntry()) != nullptr, error = kErrorNoBufs);
94 entry->mExtAddress = aExtAddress;
95 }
96
97 entry->mFiltered = true;
98
99 exit:
100 return error;
101 }
102
RemoveAddress(const ExtAddress & aExtAddress)103 void Filter::RemoveAddress(const ExtAddress &aExtAddress)
104 {
105 FilterEntry *entry = FindEntry(aExtAddress);
106
107 if (entry != nullptr)
108 {
109 entry->mFiltered = false;
110 }
111 }
112
ClearAddresses(void)113 void Filter::ClearAddresses(void)
114 {
115 for (FilterEntry &entry : mFilterEntries)
116 {
117 entry.mFiltered = false;
118 }
119 }
120
GetNextAddress(Iterator & aIterator,Entry & aEntry) const121 Error Filter::GetNextAddress(Iterator &aIterator, Entry &aEntry) const
122 {
123 Error error = kErrorNotFound;
124
125 for (; aIterator < OT_ARRAY_LENGTH(mFilterEntries); aIterator++)
126 {
127 const FilterEntry &entry = mFilterEntries[aIterator];
128
129 if (entry.mFiltered)
130 {
131 aEntry.mExtAddress = entry.mExtAddress;
132 aEntry.mRssIn = entry.mRssIn;
133 error = kErrorNone;
134 aIterator++;
135 break;
136 }
137 }
138
139 return error;
140 }
141
AddRssIn(const ExtAddress & aExtAddress,int8_t aRss)142 Error Filter::AddRssIn(const ExtAddress &aExtAddress, int8_t aRss)
143 {
144 Error error = kErrorNone;
145 FilterEntry *entry = FindEntry(aExtAddress);
146
147 if (entry == nullptr)
148 {
149 entry = FindAvailableEntry();
150 VerifyOrExit(entry != nullptr, error = kErrorNoBufs);
151
152 entry->mExtAddress = aExtAddress;
153 }
154
155 entry->mRssIn = aRss;
156
157 exit:
158 return error;
159 }
160
RemoveRssIn(const ExtAddress & aExtAddress)161 void Filter::RemoveRssIn(const ExtAddress &aExtAddress)
162 {
163 FilterEntry *entry = FindEntry(aExtAddress);
164
165 VerifyOrExit(entry != nullptr);
166
167 entry->mRssIn = kFixedRssDisabled;
168
169 exit:
170 return;
171 }
172
ClearAllRssIn(void)173 void Filter::ClearAllRssIn(void)
174 {
175 for (FilterEntry &entry : mFilterEntries)
176 {
177 entry.mRssIn = kFixedRssDisabled;
178 }
179
180 mDefaultRssIn = kFixedRssDisabled;
181 }
182
GetNextRssIn(Iterator & aIterator,Entry & aEntry)183 Error Filter::GetNextRssIn(Iterator &aIterator, Entry &aEntry)
184 {
185 Error error = kErrorNotFound;
186
187 for (; aIterator < OT_ARRAY_LENGTH(mFilterEntries); aIterator++)
188 {
189 FilterEntry &entry = mFilterEntries[aIterator];
190
191 if (entry.mRssIn != kFixedRssDisabled)
192 {
193 aEntry.mExtAddress = entry.mExtAddress;
194 aEntry.mRssIn = entry.mRssIn;
195 error = kErrorNone;
196 aIterator++;
197 ExitNow();
198 }
199 }
200
201 // Return the default RssIn at the end of list
202 if ((aIterator == OT_ARRAY_LENGTH(mFilterEntries)) && (mDefaultRssIn != kFixedRssDisabled))
203 {
204 static_cast<ExtAddress &>(aEntry.mExtAddress).Fill(0xff);
205 aEntry.mRssIn = mDefaultRssIn;
206 error = kErrorNone;
207 aIterator++;
208 }
209
210 exit:
211 return error;
212 }
213
Apply(const ExtAddress & aExtAddress,int8_t & aRss)214 Error Filter::Apply(const ExtAddress &aExtAddress, int8_t &aRss)
215 {
216 Error error = kErrorNone;
217 FilterEntry *entry = FindEntry(aExtAddress);
218 bool isInFilterList;
219
220 // Use the default RssIn setting for all receiving messages first.
221 aRss = mDefaultRssIn;
222
223 // In allowlist mode, entry must be present in the list, in
224 // denylist mode it must not be present.
225
226 isInFilterList = (entry != nullptr) && entry->mFiltered;
227
228 switch (mMode)
229 {
230 case kModeRssInOnly:
231 break;
232
233 case kModeAllowlist:
234 VerifyOrExit(isInFilterList, error = kErrorAddressFiltered);
235 break;
236
237 case kModeDenylist:
238 VerifyOrExit(!isInFilterList, error = kErrorAddressFiltered);
239 break;
240 }
241
242 if ((entry != nullptr) && (entry->mRssIn != kFixedRssDisabled))
243 {
244 aRss = entry->mRssIn;
245 }
246
247 exit:
248 return error;
249 }
250
251 } // namespace Mac
252 } // namespace ot
253
254 #endif // OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
255