1 /*
2 * Copyright (C) 2015-2018 Alibaba Group Holding Limited
3 */
4 #include "wifi_provision_internal.h"
5 #include "linkkit/infra/infra_defs.h"
6
7 #if defined(AWSS_SUPPORT_DISCOVER)
8 #if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
9 extern "C" {
10 #endif
11
12 #define AWS_DISCOVER_MIN_DURATION 100
13 #define MAX_MNGMT_FRAME_LEN 80
14 #define PRINT_DISCOVER_DEBUG 0
15 #define AWSS_DISCOVER_USE_QUICK_CRC
16 #define VER 0
17
18 #define POLY 0x04C11DB7
19 #define MNGMT_BEACON 0x80
20 #define MNGMT_RESPONSE 0x50
21
22 static const uint8_t BCAST_ADDR[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
23 static const uint8_t BEACON_INTER[] = { 0x2c, 0x01, 0x01, 0x00 };
24
25 typedef struct simulate_ap {
26 uint8_t bssid[6];
27 uint16_t seq_id;
28 uint8_t essid_len;
29 char essid[32];
30 } simulate_ap_t;
31
reflect(uint64_t ref,uint8_t ch)32 static uint64_t reflect(uint64_t ref, uint8_t ch)
33 {
34 int i;
35 uint64_t value = 0;
36 for (i = 1; i < (ch + 1); i++) {
37 if (ref & 1) {
38 value |= 1 << (ch - i);
39 }
40 ref >>= 1;
41 }
42 return value;
43 }
44
print_hex_array(uint8_t * array,uint16_t len)45 static void print_hex_array(uint8_t *array, uint16_t len)
46 {
47 #if PRINT_DISCOVER_DEBUG
48 int i;
49 for (i = 0; i < len; i++) {
50 HAL_Printf("%02x ", array[i]);
51 if (i != 0 && i % 10 == 0) {
52 HAL_Printf("\r\n");
53 }
54 }
55 #endif
56 }
57
58 #ifndef AWSS_DISCOVER_USE_QUICK_CRC
crc32_bit(uint8_t * ptr,uint32_t len)59 static uint32_t crc32_bit(uint8_t *ptr, uint32_t len)
60 {
61 uint8_t i;
62 uint32_t crc = 0xffffffff;
63 while (len--) {
64 for (i = 1; i != 0; i <<= 1) {
65 if ((crc & 0x80000000) != 0) {
66 crc <<= 1;
67 crc ^= POLY;
68 } else {
69 crc <<= 1;
70 }
71 if ((*ptr & i) != 0) {
72 crc ^= POLY;
73 }
74 }
75 ptr++;
76 }
77 return reflect(crc, 32) ^ 0xffffffff;
78 }
79
80 #else
81 static uint32_t Table2[256];
82
gen_normal_table(uint32_t * table)83 static void gen_normal_table(uint32_t *table)
84 {
85 uint32_t gx = 0x04c11db7;
86 uint32_t temp;
87 int i, j;
88 for (i = 0; i <= 0xFF; i++) {
89 temp = reflect(i, 8);
90 table[i] = temp << 24;
91 for (j = 0; j < 8; j++) {
92 unsigned long int t1, t2;
93 unsigned long int flag = table[i] & 0x80000000;
94 t1 = (table[i] << 1);
95 if (flag == 0) {
96 t2 = 0;
97 } else {
98 t2 = gx;
99 }
100 table[i] = t1 ^ t2;
101 }
102 table[i] = reflect(table[i], 32);
103 }
104 }
105
reverse_table_crc(uint8_t * data,int32_t len,uint32_t * table)106 static uint32_t reverse_table_crc(uint8_t *data, int32_t len, uint32_t *table)
107 {
108 uint32_t crc = 0xffffffff;
109 uint8_t *p = data;
110 int i;
111 for (i = 0; i < len; i++) {
112 crc = table[(crc ^ (*(p + i))) & 0xff] ^ (crc >> 8);
113 }
114 return ~crc;
115 }
116
crc32_bit(uint8_t * ptr,uint32_t len)117 static uint32_t crc32_bit(uint8_t *ptr, uint32_t len)
118 {
119 uint32_t crc;
120 static uint8_t init_table = 0;
121 if (init_table == 0) {
122 init_table = 1;
123 gen_normal_table(Table2);
124 }
125 crc = reverse_table_crc(ptr, len, Table2);
126 return crc;
127 }
128 #endif
129
get_fcs(uint8_t * p_buffer,uint16_t length)130 static void get_fcs(uint8_t *p_buffer, uint16_t length)
131 {
132 uint32_t crc;
133 if (length < 4) {
134 return;
135 }
136
137 crc = crc32_bit(p_buffer, length - 4);
138
139 p_buffer[length - 4] = (crc >> 24) & 0xff;
140 p_buffer[length - 3] = (crc >> 16) & 0xff;
141 p_buffer[length - 2] = (crc >> 8) & 0xff;
142 p_buffer[length - 1] = (crc) & 0xff;
143 }
144
create_mng_frame(uint8_t * p_buffer,uint8_t type,uint8_t dst[6],simulate_ap_t * p_ap)145 static uint16_t create_mng_frame(uint8_t *p_buffer, uint8_t type,
146 uint8_t dst[6], simulate_ap_t *p_ap)
147 {
148 uint16_t len = 0;
149 uint8_t t_i;
150 static uint16_t seq_id = 0;
151 uint64_t t_timestamp = HAL_UptimeMs() * 1000;
152
153 if (p_buffer == NULL || p_ap == NULL || dst == NULL) {
154 return 0;
155 }
156 p_ap->seq_id = seq_id;
157 /* memcpy(p_buffer, HEADER, 10);*/
158 p_buffer[len] = type;
159 len += 1; /*len = 1 */
160 p_buffer[len] = 0;
161 len += 1; /*len = 2 */
162 p_buffer[len] = 0;
163 len += 1; /*len = 3 */
164 p_buffer[len] = 0;
165 len += 1; /*len = 4 */
166 memcpy(p_buffer + len, dst, 6);
167 len += 6; /*len = 10 */
168 memcpy(p_buffer + len, p_ap->bssid, 6);
169 len += 6; /*len = 16 */
170 memcpy(p_buffer + len, p_ap->bssid, 6);
171 len += 6; /*len = 22 */
172 p_buffer[len] = (uint8_t)(p_ap->seq_id & 0xFF);
173 len += 1; /*len = 23 */
174 p_buffer[len] = (uint8_t)((p_ap->seq_id >> 8) & 0xFF);
175 len += 1; /*len = 24 */
176 seq_id += 0x10;
177
178 for (t_i = 0; t_i < 8; t_i++) {
179 p_buffer[len + t_i] = (uint8_t)((t_timestamp >> (t_i << 3)) & 0xFF);
180 }
181 len += 8; /*len = 32 */
182
183 memcpy(p_buffer + len, BEACON_INTER, 4);
184 len += 4; /*len = 36 */
185 p_buffer[len] = 0;
186 len += 1; /*len = 37 */
187 p_buffer[len] = p_ap->essid_len;
188 len += 1; /*len = 38 */
189 memcpy(p_buffer + len, p_ap->essid, p_ap->essid_len);
190 len += p_ap->essid_len; /*len = 38+p_ap->essid_len */
191
192 len += 4;
193 get_fcs(p_buffer, len);
194 print_hex_array(p_buffer, len);
195 return len;
196 }
197
awss_set_discover_content(simulate_ap_t * ap,char * data)198 static int awss_set_discover_content(simulate_ap_t *ap, char *data)
199 {
200 uint8_t len;
201 if (data == NULL || ap == NULL) {
202 return -1;
203 }
204
205 len = strlen(data);
206 if (len > 32) {
207 len = 32;
208 }
209 ap->essid_len = len;
210 memcpy(ap->essid, data, len);
211 return 0;
212 }
213
get_ability(char * src,uint8_t mac[6])214 static int get_ability(char *src, uint8_t mac[6])
215 {
216 uint32_t mac_org_bits = 0;
217 uint32_t ab_org_bits = 0;
218 uint32_t mac_dst_bits = 0;
219 uint32_t ab_dst_bits = 0;
220 uint8_t i;
221
222 if (src == NULL || mac == NULL) {
223 return 0;
224 }
225
226 mac_org_bits = mac[3] | (mac[4] << 8) | mac[5] << 16;
227 mac_dst_bits = (mac_org_bits & 0x3f) | (((mac_org_bits >> 6) & 0x3f) << 8) |
228 (((mac_org_bits >> 12) & 0x3f) << 16) |
229 (((mac_org_bits >> 18) & 0x3f) << 24);
230 ab_org_bits |= VER & 0x03;
231 #ifdef AWSS_SUPPORT_SMARTCONFIG
232 ab_org_bits |= 0x01 << 3;
233 #endif
234 #ifdef AWSS_SUPPORT_SMARTCONFIG_MCAST
235 ab_org_bits |= 0x01 << 4;
236 #endif
237 #ifdef AWSS_SUPPORT_SMARTCONFIG_WPS
238 ab_org_bits |= 0x01 << 5;
239 #endif
240 #ifdef AWSS_SUPPORT_AHA
241 ab_org_bits |= 0x01 << 6;
242 #endif
243 #ifdef AWSS_SUPPORT_DEV_AP
244 ab_org_bits |= 0x01 << 7;
245 #endif
246 #ifdef AWSS_SUPPORT_ZEROCONFIG
247 ab_org_bits |= 0x01 << 8;
248 #endif
249 ab_dst_bits = (ab_org_bits & 0x3f) | (((ab_org_bits >> 6) & 0x3f) << 8);
250
251 for (i = 0; i < 4; i++) {
252 src[i] = ((mac_dst_bits >> i * 8) & 0x3f) + 32;
253 }
254
255 for (i = 0; i < 4; i++) {
256 src[i + 4] = ((ab_dst_bits >> i * 8) & 0x3f) + 32;
257 }
258 return 8;
259 }
260
aws_discover_send(uint8_t ftype,uint8_t dst[6])261 static int aws_discover_send(uint8_t ftype, uint8_t dst[6])
262 {
263 int len;
264 int ssid_len;
265 uint8_t probe[MAX_MNGMT_FRAME_LEN] = { 0 };
266 char _product_key[IOTX_PRODUCT_KEY_LEN + 1] = { 0 };
267 char ssid[33] = { 0 };
268 simulate_ap_t ap;
269 memset(&ap, 0, sizeof(simulate_ap_t));
270
271 os_wifi_get_mac(ap.bssid);
272 HAL_GetProductKey(_product_key);
273 strcpy(ssid, "adn");
274 ssid_len = 3;
275 strncpy(ssid + ssid_len, _product_key, IOTX_PRODUCT_KEY_LEN);
276 ssid_len += strlen(_product_key);
277 strcpy(ssid + ssid_len, "_");
278 ssid_len += 1;
279 ssid_len += get_ability(ssid + ssid_len, ap.bssid);
280
281 awss_set_discover_content(&ap, ssid);
282
283 len = create_mng_frame(probe, ftype, dst, &ap);
284
285 HAL_Wifi_Send_80211_Raw_Frame(FRAME_BEACON, probe, len);
286 return 0;
287 }
288 /**
289 * @brief management frame handler
290 *
291 * @param[in] buffer @n 80211 raw frame or ie(information element) buffer
292 * @param[in] len @n buffer length
293 * @param[in] buffer_type @n 0 when buffer is a 80211 frame,
294 * 1 when buffer only contain IE info
295 * @return None.
296 * @see None.
297 * @note None.
298 */
aws_discover_callback(uint8_t * buffer,int length,int link_type,struct parser_res * res,signed char rssi)299 int aws_discover_callback(uint8_t *buffer, int length, int link_type,
300 struct parser_res *res, signed char rssi)
301 {
302 #define MGMT_BEACON (0x80)
303 #define MGMT_PROBE_REQ (0x40)
304 #define MGMT_PROBE_RESP (0x50)
305 #define MGMT_HDR_LEN (24)
306
307 static uint32_t last_time = 0;
308 /* fc(2) + dur(2) + da(6) + sa(6) + bssid(6) + seq(2) */
309 uint8_t dst[6] = { 0 };
310 int type = buffer[0];
311 switch (type) {
312 case MGMT_BEACON:
313 break;
314 case MGMT_PROBE_REQ:
315 {
316 if (time_elapsed_ms_since(last_time) < AWS_DISCOVER_MIN_DURATION) {
317 break;
318 }
319 last_time = os_get_time_ms();
320 if (length >= 16) {
321 memcpy(dst, buffer + 10, 6);
322 }
323 print_hex_array(buffer, length);
324 aws_discover_send(MNGMT_RESPONSE, dst);
325 }
326 break;
327 case MGMT_PROBE_RESP:
328 break;
329 default:
330 break;
331 }
332 return 0;
333 }
334
aws_discover_send_beacon()335 int aws_discover_send_beacon()
336 {
337 return aws_discover_send(MNGMT_BEACON, (uint8_t *)BCAST_ADDR);
338 }
339
340 #if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
341 }
342 #endif
343 #endif
344