1 | /** @file wlan_mac_addr_mac_filter.c |
---|
2 | * @brief Address Filter |
---|
3 | * |
---|
4 | * This contains code for the filtering MAC addresses |
---|
5 | * |
---|
6 | * @copyright Copyright 2014-2019, Mango Communications. All rights reserved. |
---|
7 | * Distributed under the Mango Communications Reference Design License |
---|
8 | * See LICENSE.txt included in the design archive or |
---|
9 | * at http://mangocomm.com/802.11/license |
---|
10 | * |
---|
11 | * This file is part of the Mango 802.11 Reference Design (https://mangocomm.com/802.11) |
---|
12 | */ |
---|
13 | |
---|
14 | /***************************** Include Files *********************************/ |
---|
15 | |
---|
16 | #include "wlan_mac_high_sw_config.h" |
---|
17 | |
---|
18 | #include "stdio.h" |
---|
19 | #include "stdlib.h" |
---|
20 | #include "string.h" |
---|
21 | #include "xil_types.h" |
---|
22 | #include "wlan_mac_addr_filter.h" |
---|
23 | #include "wlan_mac_dl_list.h" |
---|
24 | #include "wlan_mac_high.h" |
---|
25 | #include "wlan_mac_network_info.h" |
---|
26 | |
---|
27 | |
---|
28 | /*************************** Constant Definitions ****************************/ |
---|
29 | |
---|
30 | |
---|
31 | /*********************** Global Variable Definitions *************************/ |
---|
32 | |
---|
33 | |
---|
34 | /*************************** Variable Definitions ****************************/ |
---|
35 | |
---|
36 | |
---|
37 | // ********************************************************************** |
---|
38 | // White-list for address ranges |
---|
39 | // |
---|
40 | // For the mask, bits that are 0 are treated as "any" and bits that are 1 are treated as "must equal" |
---|
41 | // For the compare, locations of one bits in the mask must match whitelist_range_compare for incoming addresses |
---|
42 | // |
---|
43 | |
---|
44 | dl_list addr_filter; |
---|
45 | |
---|
46 | // Defines for Mango Hardware |
---|
47 | static u8 mango_range_mask[MAC_ADDR_LEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00 }; |
---|
48 | static u8 mango_range_compare[MAC_ADDR_LEN] = { 0x40, 0xD8, 0x55, 0x04, 0x20, 0x00 }; |
---|
49 | |
---|
50 | |
---|
51 | /*************************** Functions Prototypes ****************************/ |
---|
52 | |
---|
53 | u8 addr_is_allowed(u8* addr, u8* mask, u8* compare); |
---|
54 | |
---|
55 | /******************************** Functions **********************************/ |
---|
56 | |
---|
57 | /*****************************************************************************/ |
---|
58 | /** |
---|
59 | * @brief Initialize the Address Filter |
---|
60 | * |
---|
61 | * This function will initialize the address filter |
---|
62 | * |
---|
63 | * @param None. |
---|
64 | * @return None. |
---|
65 | */ |
---|
66 | void wlan_mac_addr_filter_init() { |
---|
67 | // Setup the address filter |
---|
68 | dl_list_init(&addr_filter); |
---|
69 | } |
---|
70 | |
---|
71 | |
---|
72 | |
---|
73 | /*****************************************************************************/ |
---|
74 | /** |
---|
75 | * @brief Reset the Address Filter |
---|
76 | * |
---|
77 | * This function will reset the address filter back to the default state of |
---|
78 | * "allow all" (ie mask = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, range = |
---|
79 | * { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }) and free all memory associated |
---|
80 | * with the white-list ranges. |
---|
81 | * |
---|
82 | * @param None. |
---|
83 | * @return None. |
---|
84 | */ |
---|
85 | void wlan_mac_addr_filter_reset() { |
---|
86 | int iter; |
---|
87 | whitelist_range* curr_range; |
---|
88 | dl_entry* next_range_dl_entry; |
---|
89 | dl_entry* curr_range_dl_entry; |
---|
90 | |
---|
91 | iter = addr_filter.length; |
---|
92 | next_range_dl_entry = addr_filter.first; |
---|
93 | |
---|
94 | // Remove all ranges from the address filter |
---|
95 | while ((next_range_dl_entry != NULL) && (iter-- > 0)) { |
---|
96 | curr_range_dl_entry = next_range_dl_entry; |
---|
97 | next_range_dl_entry = dl_entry_next(curr_range_dl_entry); |
---|
98 | |
---|
99 | curr_range = (whitelist_range*)(curr_range_dl_entry->data); |
---|
100 | |
---|
101 | dl_entry_remove(&addr_filter, curr_range_dl_entry); |
---|
102 | |
---|
103 | // Free allocated memory |
---|
104 | wlan_mac_high_free(curr_range_dl_entry); |
---|
105 | wlan_mac_high_free(curr_range); |
---|
106 | } |
---|
107 | |
---|
108 | if (addr_filter.length != 0) { |
---|
109 | xil_printf("ERROR: Could not fully reset address filter."); |
---|
110 | } |
---|
111 | } |
---|
112 | |
---|
113 | |
---|
114 | |
---|
115 | /*****************************************************************************/ |
---|
116 | /** |
---|
117 | * @brief Add a white-list range to the Address Filter |
---|
118 | * |
---|
119 | * This function will allocate memory for a white-list range and add that to |
---|
120 | * the current list being used to filter addresses. |
---|
121 | * |
---|
122 | * @param u8 * mask - Mask for the white-list range |
---|
123 | * @param u8 * compare - Compare address for the white-list range |
---|
124 | * @return int - Was this filter added successfully |
---|
125 | * - nonzero if error |
---|
126 | */ |
---|
127 | int wlan_mac_addr_filter_add(u8* mask, u8* compare) { |
---|
128 | whitelist_range* range; |
---|
129 | dl_entry* entry; |
---|
130 | |
---|
131 | // Allocate memory for the entry and the white-list range |
---|
132 | entry = wlan_mac_high_malloc(sizeof(dl_entry)); |
---|
133 | |
---|
134 | if (entry == NULL) { |
---|
135 | return WLAN_FAILURE; |
---|
136 | } |
---|
137 | |
---|
138 | range = wlan_mac_high_malloc(sizeof(whitelist_range)); |
---|
139 | |
---|
140 | if (range == NULL) { |
---|
141 | wlan_mac_high_free(entry); |
---|
142 | return WLAN_FAILURE; |
---|
143 | } |
---|
144 | |
---|
145 | entry->data = (void*)range; |
---|
146 | |
---|
147 | // Copy the mask and compare address to the new range |
---|
148 | memcpy(&(range->mask[0]), mask, MAC_ADDR_LEN); |
---|
149 | memcpy(&(range->compare[0]), compare, MAC_ADDR_LEN); |
---|
150 | |
---|
151 | // Add this range at the end of the address filter |
---|
152 | dl_entry_insertEnd(&addr_filter, entry); |
---|
153 | |
---|
154 | return WLAN_SUCCESS; |
---|
155 | } |
---|
156 | |
---|
157 | |
---|
158 | |
---|
159 | /*****************************************************************************/ |
---|
160 | /** |
---|
161 | * @brief Is the given address allowed? |
---|
162 | * |
---|
163 | * This function will apply the filter to the given address and return whether |
---|
164 | * the address passed the filter. |
---|
165 | * |
---|
166 | * @param u8 * addr - Address to check against the filter |
---|
167 | * @return u8 |
---|
168 | * - ADDR_FILTER_ADDR_NOT_ALLOWED if address is not allowed |
---|
169 | * - ADDR_FILTER_ADDR_ALLOWED if address is allowed |
---|
170 | */ |
---|
171 | u8 wlan_mac_addr_filter_is_allowed(u8* addr){ |
---|
172 | int iter; |
---|
173 | u32 list_len = addr_filter.length; |
---|
174 | whitelist_range* curr_range; |
---|
175 | dl_entry* curr_range_dl_entry; |
---|
176 | |
---|
177 | // Check if the list is empty |
---|
178 | // - By default, we allow all addresses |
---|
179 | // |
---|
180 | if (list_len == 0) { return ADDR_FILTER_ADDR_ALLOWED; } |
---|
181 | |
---|
182 | |
---|
183 | // Check if the incoming address is within the allowable range of addresses |
---|
184 | iter = addr_filter.length; |
---|
185 | curr_range_dl_entry = addr_filter.first; |
---|
186 | |
---|
187 | while ((curr_range_dl_entry != NULL) && (iter-- > 0)) { |
---|
188 | |
---|
189 | curr_range = (whitelist_range*)(curr_range_dl_entry->data); |
---|
190 | |
---|
191 | if (addr_is_allowed(addr, (curr_range->mask), (curr_range->compare)) == ADDR_FILTER_ADDR_ALLOWED) { |
---|
192 | return ADDR_FILTER_ADDR_ALLOWED; |
---|
193 | } |
---|
194 | |
---|
195 | curr_range_dl_entry = dl_entry_next(curr_range_dl_entry); |
---|
196 | } |
---|
197 | |
---|
198 | // If the code made it this far, we aren't allowing this address to join the network. |
---|
199 | return ADDR_FILTER_ADDR_NOT_ALLOWED; |
---|
200 | } |
---|
201 | |
---|
202 | /*****************************************************************************/ |
---|
203 | /** |
---|
204 | * @brief Is the given address a Mango node? |
---|
205 | * |
---|
206 | * This function will check if the given address is in the Mango address range. |
---|
207 | * |
---|
208 | * @param u8 * addr - Address to check against the filter |
---|
209 | * @return u8 |
---|
210 | * - ADDR_FILTER_ADDR_NOT_ALLOWED if address is not a Mango address |
---|
211 | * - ADDR_FILTER_ADDR_ALLOWED if address is a Mango address |
---|
212 | */ |
---|
213 | u8 wlan_mac_addr_is_mango(u8* addr){ |
---|
214 | return addr_is_allowed(addr, mango_range_mask, mango_range_compare); |
---|
215 | } |
---|
216 | |
---|
217 | /*****************************************************************************/ |
---|
218 | /** |
---|
219 | * @brief Internal address checking method |
---|
220 | * |
---|
221 | * This function will check the address against the given address range. |
---|
222 | * |
---|
223 | * @param u8 * addr - Address to check against the address range |
---|
224 | * @param u8 * mask - Mask of the address range |
---|
225 | * @param u8 * compare - Compare address of the address range |
---|
226 | * @return u8 |
---|
227 | * - ADDR_FILTER_ADDR_NOT_ALLOWED if address is not in the range |
---|
228 | * - ADDR_FILTER_ADDR_ALLOWED if address is in the range |
---|
229 | */ |
---|
230 | u8 addr_is_allowed(u8* addr, u8* mask, u8* compare){ |
---|
231 | u32 i; |
---|
232 | u32 sum; |
---|
233 | |
---|
234 | sum = 0; |
---|
235 | |
---|
236 | for (i = 0; i < MAC_ADDR_LEN; i++) { |
---|
237 | sum += (mask[i] & compare[i]) == (mask[i] & addr[i]); |
---|
238 | } |
---|
239 | |
---|
240 | if (sum == MAC_ADDR_LEN) { |
---|
241 | return ADDR_FILTER_ADDR_ALLOWED; |
---|
242 | } else { |
---|
243 | return ADDR_FILTER_ADDR_NOT_ALLOWED; |
---|
244 | } |
---|
245 | } |
---|
246 | |
---|
247 | |
---|
248 | |
---|
249 | |
---|
250 | |
---|