Line data Source code
1 : /*
2 : * Wi-Fi Protected Setup - attribute parsing
3 : * Copyright (c) 2008, Jouni Malinen <j@w1.fi>
4 : *
5 : * This software may be distributed under the terms of the BSD license.
6 : * See README for more details.
7 : */
8 :
9 : #include "includes.h"
10 :
11 : #include "common.h"
12 : #include "wps_defs.h"
13 : #include "wps_attr_parse.h"
14 :
15 : #ifndef CONFIG_WPS_STRICT
16 : #define WPS_WORKAROUNDS
17 : #endif /* CONFIG_WPS_STRICT */
18 :
19 :
20 877 : static int wps_set_vendor_ext_wfa_subelem(struct wps_parse_attr *attr,
21 : u8 id, u8 len, const u8 *pos)
22 : {
23 877 : wpa_printf(MSG_EXCESSIVE, "WPS: WFA subelement id=%u len=%u",
24 : id, len);
25 877 : switch (id) {
26 : case WFA_ELEM_VERSION2:
27 759 : if (len != 1) {
28 0 : wpa_printf(MSG_DEBUG, "WPS: Invalid Version2 length "
29 : "%u", len);
30 0 : return -1;
31 : }
32 759 : attr->version2 = pos;
33 759 : break;
34 : case WFA_ELEM_AUTHORIZEDMACS:
35 15 : attr->authorized_macs = pos;
36 15 : attr->authorized_macs_len = len;
37 15 : break;
38 : case WFA_ELEM_NETWORK_KEY_SHAREABLE:
39 0 : if (len != 1) {
40 0 : wpa_printf(MSG_DEBUG, "WPS: Invalid Network Key "
41 : "Shareable length %u", len);
42 0 : return -1;
43 : }
44 0 : attr->network_key_shareable = pos;
45 0 : break;
46 : case WFA_ELEM_REQUEST_TO_ENROLL:
47 103 : if (len != 1) {
48 0 : wpa_printf(MSG_DEBUG, "WPS: Invalid Request to Enroll "
49 : "length %u", len);
50 0 : return -1;
51 : }
52 103 : attr->request_to_enroll = pos;
53 103 : break;
54 : case WFA_ELEM_SETTINGS_DELAY_TIME:
55 0 : if (len != 1) {
56 0 : wpa_printf(MSG_DEBUG, "WPS: Invalid Settings Delay "
57 : "Time length %u", len);
58 0 : return -1;
59 : }
60 0 : attr->settings_delay_time = pos;
61 0 : break;
62 : case WFA_ELEM_REGISTRAR_CONFIGURATION_METHODS:
63 0 : if (len != 2) {
64 0 : wpa_printf(MSG_DEBUG, "WPS: Invalid Registrar Configuration Methods length %u",
65 : len);
66 0 : return -1;
67 : }
68 0 : attr->registrar_configuration_methods = pos;
69 0 : break;
70 : default:
71 0 : wpa_printf(MSG_MSGDUMP, "WPS: Skipped unknown WFA Vendor "
72 : "Extension subelement %u", id);
73 0 : break;
74 : }
75 :
76 877 : return 0;
77 : }
78 :
79 :
80 759 : static int wps_parse_vendor_ext_wfa(struct wps_parse_attr *attr, const u8 *pos,
81 : u16 len)
82 : {
83 759 : const u8 *end = pos + len;
84 : u8 id, elen;
85 :
86 2395 : while (pos + 2 <= end) {
87 877 : id = *pos++;
88 877 : elen = *pos++;
89 877 : if (pos + elen > end)
90 0 : break;
91 877 : if (wps_set_vendor_ext_wfa_subelem(attr, id, elen, pos) < 0)
92 0 : return -1;
93 877 : pos += elen;
94 : }
95 :
96 759 : return 0;
97 : }
98 :
99 :
100 768 : static int wps_parse_vendor_ext(struct wps_parse_attr *attr, const u8 *pos,
101 : u16 len)
102 : {
103 : u32 vendor_id;
104 :
105 768 : if (len < 3) {
106 0 : wpa_printf(MSG_DEBUG, "WPS: Skip invalid Vendor Extension");
107 0 : return 0;
108 : }
109 :
110 768 : vendor_id = WPA_GET_BE24(pos);
111 768 : switch (vendor_id) {
112 : case WPS_VENDOR_ID_WFA:
113 759 : return wps_parse_vendor_ext_wfa(attr, pos + 3, len - 3);
114 : }
115 :
116 : /* Handle unknown vendor extensions */
117 :
118 9 : wpa_printf(MSG_MSGDUMP, "WPS: Unknown Vendor Extension (Vendor ID %u)",
119 : vendor_id);
120 :
121 9 : if (len > WPS_MAX_VENDOR_EXT_LEN) {
122 0 : wpa_printf(MSG_DEBUG, "WPS: Too long Vendor Extension (%u)",
123 : len);
124 0 : return -1;
125 : }
126 :
127 9 : if (attr->num_vendor_ext >= MAX_WPS_PARSE_VENDOR_EXT) {
128 0 : wpa_printf(MSG_DEBUG, "WPS: Skipped Vendor Extension "
129 : "attribute (max %d vendor extensions)",
130 : MAX_WPS_PARSE_VENDOR_EXT);
131 0 : return -1;
132 : }
133 9 : attr->vendor_ext[attr->num_vendor_ext] = pos;
134 9 : attr->vendor_ext_len[attr->num_vendor_ext] = len;
135 9 : attr->num_vendor_ext++;
136 :
137 9 : return 0;
138 : }
139 :
140 :
141 7709 : static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
142 : const u8 *pos, u16 len)
143 : {
144 7709 : switch (type) {
145 : case ATTR_VERSION:
146 773 : if (len != 1) {
147 0 : wpa_printf(MSG_DEBUG, "WPS: Invalid Version length %u",
148 : len);
149 0 : return -1;
150 : }
151 773 : attr->version = pos;
152 773 : break;
153 : case ATTR_MSG_TYPE:
154 390 : if (len != 1) {
155 0 : wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type "
156 : "length %u", len);
157 0 : return -1;
158 : }
159 390 : attr->msg_type = pos;
160 390 : break;
161 : case ATTR_ENROLLEE_NONCE:
162 283 : if (len != WPS_NONCE_LEN) {
163 0 : wpa_printf(MSG_DEBUG, "WPS: Invalid Enrollee Nonce "
164 : "length %u", len);
165 0 : return -1;
166 : }
167 283 : attr->enrollee_nonce = pos;
168 283 : break;
169 : case ATTR_REGISTRAR_NONCE:
170 258 : if (len != WPS_NONCE_LEN) {
171 0 : wpa_printf(MSG_DEBUG, "WPS: Invalid Registrar Nonce "
172 : "length %u", len);
173 0 : return -1;
174 : }
175 258 : attr->registrar_nonce = pos;
176 258 : break;
177 : case ATTR_UUID_E:
178 256 : if (len != WPS_UUID_LEN) {
179 0 : wpa_printf(MSG_DEBUG, "WPS: Invalid UUID-E length %u",
180 : len);
181 0 : return -1;
182 : }
183 256 : attr->uuid_e = pos;
184 256 : break;
185 : case ATTR_UUID_R:
186 63 : if (len != WPS_UUID_LEN) {
187 0 : wpa_printf(MSG_DEBUG, "WPS: Invalid UUID-R length %u",
188 : len);
189 0 : return -1;
190 : }
191 63 : attr->uuid_r = pos;
192 63 : break;
193 : case ATTR_AUTH_TYPE_FLAGS:
194 95 : if (len != 2) {
195 0 : wpa_printf(MSG_DEBUG, "WPS: Invalid Authentication "
196 : "Type Flags length %u", len);
197 0 : return -1;
198 : }
199 95 : attr->auth_type_flags = pos;
200 95 : break;
201 : case ATTR_ENCR_TYPE_FLAGS:
202 95 : if (len != 2) {
203 0 : wpa_printf(MSG_DEBUG, "WPS: Invalid Encryption Type "
204 : "Flags length %u", len);
205 0 : return -1;
206 : }
207 95 : attr->encr_type_flags = pos;
208 95 : break;
209 : case ATTR_CONN_TYPE_FLAGS:
210 95 : if (len != 1) {
211 0 : wpa_printf(MSG_DEBUG, "WPS: Invalid Connection Type "
212 : "Flags length %u", len);
213 0 : return -1;
214 : }
215 95 : attr->conn_type_flags = pos;
216 95 : break;
217 : case ATTR_CONFIG_METHODS:
218 294 : if (len != 2) {
219 0 : wpa_printf(MSG_DEBUG, "WPS: Invalid Config Methods "
220 : "length %u", len);
221 0 : return -1;
222 : }
223 294 : attr->config_methods = pos;
224 294 : break;
225 : case ATTR_SELECTED_REGISTRAR_CONFIG_METHODS:
226 18 : if (len != 2) {
227 0 : wpa_printf(MSG_DEBUG, "WPS: Invalid Selected "
228 : "Registrar Config Methods length %u", len);
229 0 : return -1;
230 : }
231 18 : attr->sel_reg_config_methods = pos;
232 18 : break;
233 : case ATTR_PRIMARY_DEV_TYPE:
234 294 : if (len != WPS_DEV_TYPE_LEN) {
235 0 : wpa_printf(MSG_DEBUG, "WPS: Invalid Primary Device "
236 : "Type length %u", len);
237 0 : return -1;
238 : }
239 294 : attr->primary_dev_type = pos;
240 294 : break;
241 : case ATTR_RF_BANDS:
242 294 : if (len != 1) {
243 0 : wpa_printf(MSG_DEBUG, "WPS: Invalid RF Bands length "
244 : "%u", len);
245 0 : return -1;
246 : }
247 294 : attr->rf_bands = pos;
248 294 : break;
249 : case ATTR_ASSOC_STATE:
250 294 : if (len != 2) {
251 0 : wpa_printf(MSG_DEBUG, "WPS: Invalid Association State "
252 : "length %u", len);
253 0 : return -1;
254 : }
255 294 : attr->assoc_state = pos;
256 294 : break;
257 : case ATTR_CONFIG_ERROR:
258 329 : if (len != 2) {
259 0 : wpa_printf(MSG_DEBUG, "WPS: Invalid Configuration "
260 : "Error length %u", len);
261 0 : return -1;
262 : }
263 329 : attr->config_error = pos;
264 329 : break;
265 : case ATTR_DEV_PASSWORD_ID:
266 311 : if (len != 2) {
267 0 : wpa_printf(MSG_DEBUG, "WPS: Invalid Device Password "
268 : "ID length %u", len);
269 0 : return -1;
270 : }
271 311 : attr->dev_password_id = pos;
272 311 : break;
273 : case ATTR_OOB_DEVICE_PASSWORD:
274 9 : if (len < WPS_OOB_PUBKEY_HASH_LEN + 2 ||
275 : len > WPS_OOB_PUBKEY_HASH_LEN + 2 +
276 9 : WPS_OOB_DEVICE_PASSWORD_LEN ||
277 : (len < WPS_OOB_PUBKEY_HASH_LEN + 2 +
278 7 : WPS_OOB_DEVICE_PASSWORD_MIN_LEN &&
279 7 : WPA_GET_BE16(pos + WPS_OOB_PUBKEY_HASH_LEN) !=
280 : DEV_PW_NFC_CONNECTION_HANDOVER)) {
281 0 : wpa_printf(MSG_DEBUG, "WPS: Invalid OOB Device "
282 : "Password length %u", len);
283 0 : return -1;
284 : }
285 9 : attr->oob_dev_password = pos;
286 9 : attr->oob_dev_password_len = len;
287 9 : break;
288 : case ATTR_OS_VERSION:
289 95 : if (len != 4) {
290 0 : wpa_printf(MSG_DEBUG, "WPS: Invalid OS Version length "
291 : "%u", len);
292 0 : return -1;
293 : }
294 95 : attr->os_version = pos;
295 95 : break;
296 : case ATTR_WPS_STATE:
297 50 : if (len != 1) {
298 0 : wpa_printf(MSG_DEBUG, "WPS: Invalid Wi-Fi Protected "
299 : "Setup State length %u", len);
300 0 : return -1;
301 : }
302 50 : attr->wps_state = pos;
303 50 : break;
304 : case ATTR_AUTHENTICATOR:
305 233 : if (len != WPS_AUTHENTICATOR_LEN) {
306 0 : wpa_printf(MSG_DEBUG, "WPS: Invalid Authenticator "
307 : "length %u", len);
308 0 : return -1;
309 : }
310 233 : attr->authenticator = pos;
311 233 : break;
312 : case ATTR_R_HASH1:
313 36 : if (len != WPS_HASH_LEN) {
314 0 : wpa_printf(MSG_DEBUG, "WPS: Invalid R-Hash1 length %u",
315 : len);
316 0 : return -1;
317 : }
318 36 : attr->r_hash1 = pos;
319 36 : break;
320 : case ATTR_R_HASH2:
321 36 : if (len != WPS_HASH_LEN) {
322 0 : wpa_printf(MSG_DEBUG, "WPS: Invalid R-Hash2 length %u",
323 : len);
324 0 : return -1;
325 : }
326 36 : attr->r_hash2 = pos;
327 36 : break;
328 : case ATTR_E_HASH1:
329 40 : if (len != WPS_HASH_LEN) {
330 0 : wpa_printf(MSG_DEBUG, "WPS: Invalid E-Hash1 length %u",
331 : len);
332 0 : return -1;
333 : }
334 40 : attr->e_hash1 = pos;
335 40 : break;
336 : case ATTR_E_HASH2:
337 40 : if (len != WPS_HASH_LEN) {
338 0 : wpa_printf(MSG_DEBUG, "WPS: Invalid E-Hash2 length %u",
339 : len);
340 0 : return -1;
341 : }
342 40 : attr->e_hash2 = pos;
343 40 : break;
344 : case ATTR_R_SNONCE1:
345 29 : if (len != WPS_SECRET_NONCE_LEN) {
346 0 : wpa_printf(MSG_DEBUG, "WPS: Invalid R-SNonce1 length "
347 : "%u", len);
348 0 : return -1;
349 : }
350 29 : attr->r_snonce1 = pos;
351 29 : break;
352 : case ATTR_R_SNONCE2:
353 25 : if (len != WPS_SECRET_NONCE_LEN) {
354 0 : wpa_printf(MSG_DEBUG, "WPS: Invalid R-SNonce2 length "
355 : "%u", len);
356 0 : return -1;
357 : }
358 25 : attr->r_snonce2 = pos;
359 25 : break;
360 : case ATTR_E_SNONCE1:
361 29 : if (len != WPS_SECRET_NONCE_LEN) {
362 0 : wpa_printf(MSG_DEBUG, "WPS: Invalid E-SNonce1 length "
363 : "%u", len);
364 0 : return -1;
365 : }
366 29 : attr->e_snonce1 = pos;
367 29 : break;
368 : case ATTR_E_SNONCE2:
369 28 : if (len != WPS_SECRET_NONCE_LEN) {
370 0 : wpa_printf(MSG_DEBUG, "WPS: Invalid E-SNonce2 length "
371 : "%u", len);
372 0 : return -1;
373 : }
374 28 : attr->e_snonce2 = pos;
375 28 : break;
376 : case ATTR_KEY_WRAP_AUTH:
377 119 : if (len != WPS_KWA_LEN) {
378 0 : wpa_printf(MSG_DEBUG, "WPS: Invalid Key Wrap "
379 : "Authenticator length %u", len);
380 0 : return -1;
381 : }
382 119 : attr->key_wrap_auth = pos;
383 119 : break;
384 : case ATTR_AUTH_TYPE:
385 8 : if (len != 2) {
386 0 : wpa_printf(MSG_DEBUG, "WPS: Invalid Authentication "
387 : "Type length %u", len);
388 0 : return -1;
389 : }
390 8 : attr->auth_type = pos;
391 8 : break;
392 : case ATTR_ENCR_TYPE:
393 8 : if (len != 2) {
394 0 : wpa_printf(MSG_DEBUG, "WPS: Invalid Encryption "
395 : "Type length %u", len);
396 0 : return -1;
397 : }
398 8 : attr->encr_type = pos;
399 8 : break;
400 : case ATTR_NETWORK_INDEX:
401 8 : if (len != 1) {
402 0 : wpa_printf(MSG_DEBUG, "WPS: Invalid Network Index "
403 : "length %u", len);
404 0 : return -1;
405 : }
406 8 : attr->network_idx = pos;
407 8 : break;
408 : case ATTR_NETWORK_KEY_INDEX:
409 0 : if (len != 1) {
410 0 : wpa_printf(MSG_DEBUG, "WPS: Invalid Network Key Index "
411 : "length %u", len);
412 0 : return -1;
413 : }
414 0 : attr->network_key_idx = pos;
415 0 : break;
416 : case ATTR_MAC_ADDR:
417 58 : if (len != ETH_ALEN) {
418 0 : wpa_printf(MSG_DEBUG, "WPS: Invalid MAC Address "
419 : "length %u", len);
420 0 : return -1;
421 : }
422 58 : attr->mac_addr = pos;
423 58 : break;
424 : case ATTR_SELECTED_REGISTRAR:
425 18 : if (len != 1) {
426 0 : wpa_printf(MSG_DEBUG, "WPS: Invalid Selected Registrar"
427 : " length %u", len);
428 0 : return -1;
429 : }
430 18 : attr->selected_registrar = pos;
431 18 : break;
432 : case ATTR_REQUEST_TYPE:
433 365 : if (len != 1) {
434 0 : wpa_printf(MSG_DEBUG, "WPS: Invalid Request Type "
435 : "length %u", len);
436 0 : return -1;
437 : }
438 365 : attr->request_type = pos;
439 365 : break;
440 : case ATTR_RESPONSE_TYPE:
441 0 : if (len != 1) {
442 0 : wpa_printf(MSG_DEBUG, "WPS: Invalid Response Type "
443 : "length %u", len);
444 0 : return -1;
445 : }
446 0 : attr->response_type = pos;
447 0 : break;
448 : case ATTR_MANUFACTURER:
449 294 : attr->manufacturer = pos;
450 294 : attr->manufacturer_len = len;
451 294 : break;
452 : case ATTR_MODEL_NAME:
453 294 : attr->model_name = pos;
454 294 : attr->model_name_len = len;
455 294 : break;
456 : case ATTR_MODEL_NUMBER:
457 294 : attr->model_number = pos;
458 294 : attr->model_number_len = len;
459 294 : break;
460 : case ATTR_SERIAL_NUMBER:
461 95 : attr->serial_number = pos;
462 95 : attr->serial_number_len = len;
463 95 : break;
464 : case ATTR_DEV_NAME:
465 294 : attr->dev_name = pos;
466 294 : attr->dev_name_len = len;
467 294 : break;
468 : case ATTR_PUBLIC_KEY:
469 94 : attr->public_key = pos;
470 94 : attr->public_key_len = len;
471 94 : break;
472 : case ATTR_ENCR_SETTINGS:
473 151 : attr->encr_settings = pos;
474 151 : attr->encr_settings_len = len;
475 151 : break;
476 : case ATTR_CRED:
477 0 : if (attr->num_cred >= MAX_CRED_COUNT) {
478 0 : wpa_printf(MSG_DEBUG, "WPS: Skipped Credential "
479 : "attribute (max %d credentials)",
480 : MAX_CRED_COUNT);
481 0 : break;
482 : }
483 0 : attr->cred[attr->num_cred] = pos;
484 0 : attr->cred_len[attr->num_cred] = len;
485 0 : attr->num_cred++;
486 0 : break;
487 : case ATTR_SSID:
488 8 : attr->ssid = pos;
489 8 : attr->ssid_len = len;
490 8 : break;
491 : case ATTR_NETWORK_KEY:
492 8 : attr->network_key = pos;
493 8 : attr->network_key_len = len;
494 8 : break;
495 : case ATTR_AP_SETUP_LOCKED:
496 0 : if (len != 1) {
497 0 : wpa_printf(MSG_DEBUG, "WPS: Invalid AP Setup Locked "
498 : "length %u", len);
499 0 : return -1;
500 : }
501 0 : attr->ap_setup_locked = pos;
502 0 : break;
503 : case ATTR_REQUESTED_DEV_TYPE:
504 0 : if (len != WPS_DEV_TYPE_LEN) {
505 0 : wpa_printf(MSG_DEBUG, "WPS: Invalid Requested Device "
506 : "Type length %u", len);
507 0 : return -1;
508 : }
509 0 : if (attr->num_req_dev_type >= MAX_REQ_DEV_TYPE_COUNT) {
510 0 : wpa_printf(MSG_DEBUG, "WPS: Skipped Requested Device "
511 : "Type attribute (max %u types)",
512 : MAX_REQ_DEV_TYPE_COUNT);
513 0 : break;
514 : }
515 0 : attr->req_dev_type[attr->num_req_dev_type] = pos;
516 0 : attr->num_req_dev_type++;
517 0 : break;
518 : case ATTR_SECONDARY_DEV_TYPE_LIST:
519 50 : if (len > WPS_SEC_DEV_TYPE_MAX_LEN ||
520 25 : (len % WPS_DEV_TYPE_LEN) > 0) {
521 0 : wpa_printf(MSG_DEBUG, "WPS: Invalid Secondary Device "
522 : "Type length %u", len);
523 0 : return -1;
524 : }
525 25 : attr->sec_dev_type_list = pos;
526 25 : attr->sec_dev_type_list_len = len;
527 25 : break;
528 : case ATTR_VENDOR_EXT:
529 768 : if (wps_parse_vendor_ext(attr, pos, len) < 0)
530 0 : return -1;
531 768 : break;
532 : case ATTR_AP_CHANNEL:
533 0 : if (len != 2) {
534 0 : wpa_printf(MSG_DEBUG, "WPS: Invalid AP Channel "
535 : "length %u", len);
536 0 : return -1;
537 : }
538 0 : attr->ap_channel = pos;
539 0 : break;
540 : default:
541 8 : wpa_printf(MSG_DEBUG, "WPS: Unsupported attribute type 0x%x "
542 : "len=%u", type, len);
543 8 : break;
544 : }
545 :
546 7709 : return 0;
547 : }
548 :
549 :
550 901 : int wps_parse_msg(const struct wpabuf *msg, struct wps_parse_attr *attr)
551 : {
552 : const u8 *pos, *end;
553 : u16 type, len;
554 : #ifdef WPS_WORKAROUNDS
555 901 : u16 prev_type = 0;
556 : #endif /* WPS_WORKAROUNDS */
557 :
558 901 : os_memset(attr, 0, sizeof(*attr));
559 901 : pos = wpabuf_head(msg);
560 901 : end = pos + wpabuf_len(msg);
561 :
562 9511 : while (pos < end) {
563 7709 : if (end - pos < 4) {
564 0 : wpa_printf(MSG_DEBUG, "WPS: Invalid message - "
565 : "%lu bytes remaining",
566 0 : (unsigned long) (end - pos));
567 0 : return -1;
568 : }
569 :
570 7709 : type = WPA_GET_BE16(pos);
571 7709 : pos += 2;
572 7709 : len = WPA_GET_BE16(pos);
573 7709 : pos += 2;
574 7709 : wpa_printf(MSG_EXCESSIVE, "WPS: attr type=0x%x len=%u",
575 : type, len);
576 7709 : if (len > end - pos) {
577 0 : wpa_printf(MSG_DEBUG, "WPS: Attribute overflow");
578 0 : wpa_hexdump_buf(MSG_MSGDUMP, "WPS: Message data", msg);
579 : #ifdef WPS_WORKAROUNDS
580 : /*
581 : * Some deployed APs seem to have a bug in encoding of
582 : * Network Key attribute in the Credential attribute
583 : * where they add an extra octet after the Network Key
584 : * attribute at least when open network is being
585 : * provisioned.
586 : */
587 0 : if ((type & 0xff00) != 0x1000 &&
588 : prev_type == ATTR_NETWORK_KEY) {
589 0 : wpa_printf(MSG_DEBUG, "WPS: Workaround - try "
590 : "to skip unexpected octet after "
591 : "Network Key");
592 0 : pos -= 3;
593 0 : continue;
594 : }
595 : #endif /* WPS_WORKAROUNDS */
596 0 : return -1;
597 : }
598 :
599 : #ifdef WPS_WORKAROUNDS
600 7709 : if (type == 0 && len == 0) {
601 : /*
602 : * Mac OS X 10.6 seems to be adding 0x00 padding to the
603 : * end of M1. Skip those to avoid interop issues.
604 : */
605 : int i;
606 0 : for (i = 0; i < end - pos; i++) {
607 0 : if (pos[i])
608 0 : break;
609 : }
610 0 : if (i == end - pos) {
611 0 : wpa_printf(MSG_DEBUG, "WPS: Workaround - skip "
612 : "unexpected message padding");
613 0 : break;
614 : }
615 : }
616 : #endif /* WPS_WORKAROUNDS */
617 :
618 7709 : if (wps_set_attr(attr, type, pos, len) < 0)
619 0 : return -1;
620 :
621 : #ifdef WPS_WORKAROUNDS
622 7709 : prev_type = type;
623 : #endif /* WPS_WORKAROUNDS */
624 7709 : pos += len;
625 : }
626 :
627 901 : return 0;
628 : }
|