xref: /wlan-dirver/qca-wifi-host-cmn/qdf/src/qdf_types.c (revision 1397a33f48ea6455be40871470b286e535820eb8)
1 /*
2  * Copyright (c) 2018 The Linux Foundation. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for
5  * any purpose with or without fee is hereby granted, provided that the
6  * above copyright notice and this permission notice appear in all
7  * copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16  * PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include "qdf_mem.h"
20 #include "qdf_module.h"
21 #include "qdf_status.h"
22 #include "qdf_str.h"
23 #include "qdf_trace.h"
24 #include "qdf_types.h"
25 
26 const char *qdf_opmode_str(const enum QDF_OPMODE opmode)
27 {
28 	switch (opmode) {
29 	case QDF_STA_MODE:
30 		return "STA";
31 	case QDF_SAP_MODE:
32 		return "SAP";
33 	case QDF_P2P_CLIENT_MODE:
34 		return "P2P Client";
35 	case QDF_P2P_GO_MODE:
36 		return "P2P GO";
37 	case QDF_FTM_MODE:
38 		return "FTM";
39 	case QDF_IBSS_MODE:
40 		return "IBSS";
41 	case QDF_MONITOR_MODE:
42 		return "Monitor";
43 	case QDF_P2P_DEVICE_MODE:
44 		return "P2P Device";
45 	case QDF_OCB_MODE:
46 		return "OCB";
47 	case QDF_EPPING_MODE:
48 		return "EPPing";
49 	case QDF_QVIT_MODE:
50 		return "QVIT";
51 	case QDF_NDI_MODE:
52 		return "NDI";
53 	case QDF_WDS_MODE:
54 		return "WDS";
55 	case QDF_BTAMP_MODE:
56 		return "BTAMP";
57 	case QDF_AHDEMO_MODE:
58 		return "AHDEMO";
59 	default:
60 		return "Invalid operating mode";
61 	}
62 }
63 
64 static QDF_STATUS qdf_consume_char(const char **str, char c)
65 {
66 	if ((*str)[0] != c)
67 		return QDF_STATUS_E_FAILURE;
68 
69 	(*str)++;
70 
71 	return QDF_STATUS_SUCCESS;
72 }
73 
74 static QDF_STATUS qdf_consume_dec(const char **str, uint8_t *out_digit)
75 {
76 	uint8_t c = (*str)[0];
77 
78 	if (c >= '0' && c <= '9')
79 		*out_digit = c - '0';
80 	else
81 		return QDF_STATUS_E_FAILURE;
82 
83 	(*str)++;
84 
85 	return QDF_STATUS_SUCCESS;
86 }
87 
88 static QDF_STATUS qdf_consume_hex(const char **str, uint8_t *out_nibble)
89 {
90 	uint8_t c = (*str)[0];
91 
92 	if (c >= '0' && c <= '9')
93 		*out_nibble = c - '0';
94 	else if (c >= 'a' && c <= 'f')
95 		*out_nibble = c - 'a' + 10;
96 	else if (c >= 'A' && c <= 'F')
97 		*out_nibble = c - 'A' + 10;
98 	else
99 		return QDF_STATUS_E_FAILURE;
100 
101 	(*str)++;
102 
103 	return QDF_STATUS_SUCCESS;
104 }
105 
106 static QDF_STATUS qdf_consume_octet_dec(const char **str, uint8_t *out_octet)
107 {
108 	uint8_t len = 0;
109 	uint16_t octet = 0;
110 	int i;
111 
112 	/* consume up to 3 decimal digits */
113 	for (i = 0; i < 3; i++) {
114 		uint8_t digit;
115 
116 		if (QDF_IS_STATUS_ERROR(qdf_consume_dec(str, &digit)))
117 			break;
118 
119 		len++;
120 		octet = octet * 10 + digit;
121 	}
122 
123 	/* require at least 1 digit */
124 	if (!len)
125 		return QDF_STATUS_E_FAILURE;
126 
127 	if (octet > 255) {
128 		(*str) -= len;
129 		return QDF_STATUS_E_FAILURE;
130 	}
131 
132 	*out_octet = octet;
133 
134 	return QDF_STATUS_SUCCESS;
135 }
136 
137 static QDF_STATUS qdf_consume_hex_pair(const char **str, uint8_t *out_byte)
138 {
139 	QDF_STATUS status;
140 	uint8_t hi, low;
141 
142 	status = qdf_consume_hex(str, &hi);
143 	if (QDF_IS_STATUS_ERROR(status))
144 		return status;
145 
146 	status = qdf_consume_hex(str, &low);
147 	if (QDF_IS_STATUS_ERROR(status)) {
148 		(*str)--;
149 		return status;
150 	}
151 
152 	*out_byte = hi << 4 | low;
153 
154 	return QDF_STATUS_SUCCESS;
155 }
156 
157 static QDF_STATUS qdf_consume_hextet(const char **str, uint16_t *out_hextet)
158 {
159 	uint8_t len = 0;
160 	uint16_t hextet = 0;
161 	int i;
162 
163 	/* consume up to 4 hex digits */
164 	for (i = 0; i < 4; i++) {
165 		uint8_t digit;
166 
167 		if (QDF_IS_STATUS_ERROR(qdf_consume_hex(str, &digit)))
168 			break;
169 
170 		len++;
171 		hextet = (hextet << 4) + digit;
172 	}
173 
174 	/* require at least 1 digit */
175 	if (!len)
176 		return QDF_STATUS_E_FAILURE;
177 
178 	/* no need to check for overflow */
179 
180 	*out_hextet = hextet;
181 
182 	return QDF_STATUS_SUCCESS;
183 }
184 
185 static QDF_STATUS qdf_consume_radix(const char **str, uint8_t *out_radix)
186 {
187 	if ((*str)[0] == '0') {
188 		switch ((*str)[1]) {
189 		case 'b':
190 			*out_radix = 2;
191 			*str += 2;
192 			break;
193 		case 'o':
194 			*out_radix = 8;
195 			*str += 2;
196 			break;
197 		case 'x':
198 			*out_radix = 16;
199 			*str += 2;
200 			break;
201 		default:
202 			*out_radix = 10;
203 			break;
204 		}
205 
206 		return QDF_STATUS_SUCCESS;
207 	}
208 
209 	if (*str[0] >= '0' && *str[0] <= '9') {
210 		*out_radix = 10;
211 		return QDF_STATUS_SUCCESS;
212 	}
213 
214 	return QDF_STATUS_E_FAILURE;
215 }
216 
217 static QDF_STATUS
218 __qdf_int_parse_lazy(const char **int_str, uint64_t *out_int, bool *out_negate)
219 {
220 	QDF_STATUS status;
221 	bool negate = false;
222 	uint8_t radix;
223 	uint8_t digit;
224 	uint64_t value = 0;
225 	uint64_t next_value;
226 	const char *str = *int_str;
227 
228 	str = qdf_str_left_trim(str);
229 
230 	status = qdf_consume_char(&str, '-');
231 	if (QDF_IS_STATUS_SUCCESS(status))
232 		negate = true;
233 	else
234 		qdf_consume_char(&str, '+');
235 
236 	status = qdf_consume_radix(&str, &radix);
237 	if (QDF_IS_STATUS_ERROR(status))
238 		return status;
239 
240 	while (QDF_IS_STATUS_SUCCESS(qdf_consume_hex(&str, &digit))) {
241 		if (digit >= radix)
242 			return QDF_STATUS_E_FAILURE;
243 
244 		next_value = value * radix + digit;
245 		if (next_value < value)
246 			return QDF_STATUS_E_RANGE;
247 
248 		value = next_value;
249 	}
250 
251 	*int_str = str;
252 	*out_negate = negate;
253 	*out_int = value;
254 
255 	return QDF_STATUS_SUCCESS;
256 }
257 
258 static QDF_STATUS
259 qdf_int_parse(const char *int_str, uint64_t *out_int, bool *out_negate)
260 {
261 	QDF_STATUS status;
262 	bool negate;
263 	uint64_t value;
264 
265 	QDF_BUG(int_str);
266 	if (!int_str)
267 		return QDF_STATUS_E_INVAL;
268 
269 	QDF_BUG(out_int);
270 	if (!out_int)
271 		return QDF_STATUS_E_INVAL;
272 
273 	status = __qdf_int_parse_lazy(&int_str, &value, &negate);
274 	if (QDF_IS_STATUS_ERROR(status))
275 		return status;
276 
277 	int_str = qdf_str_left_trim(int_str);
278 	if (int_str[0] != '\0')
279 		return QDF_STATUS_E_FAILURE;
280 
281 	*out_negate = negate;
282 	*out_int = value;
283 
284 	return QDF_STATUS_SUCCESS;
285 }
286 
287 QDF_STATUS qdf_int32_parse(const char *int_str, int32_t *out_int)
288 {
289 	QDF_STATUS status;
290 	int64_t value;
291 
292 	status = qdf_int64_parse(int_str, &value);
293 	if (QDF_IS_STATUS_ERROR(status))
294 		return status;
295 
296 	if ((int32_t)value != value)
297 		return QDF_STATUS_E_RANGE;
298 
299 	*out_int = value;
300 
301 	return QDF_STATUS_SUCCESS;
302 }
303 qdf_export_symbol(qdf_int32_parse);
304 
305 QDF_STATUS qdf_uint32_parse(const char *int_str, uint32_t *out_int)
306 {
307 	QDF_STATUS status;
308 	uint64_t value;
309 
310 	status = qdf_uint64_parse(int_str, &value);
311 	if (QDF_IS_STATUS_ERROR(status))
312 		return status;
313 
314 	if ((uint32_t)value != value)
315 		return QDF_STATUS_E_RANGE;
316 
317 	*out_int = value;
318 
319 	return QDF_STATUS_SUCCESS;
320 }
321 qdf_export_symbol(qdf_uint32_parse);
322 
323 QDF_STATUS qdf_int64_parse(const char *int_str, int64_t *out_int)
324 {
325 	QDF_STATUS status;
326 	bool negate;
327 	uint64_t value;
328 	int64_t signed_value;
329 
330 	status = qdf_int_parse(int_str, &value, &negate);
331 	if (QDF_IS_STATUS_ERROR(status))
332 		return status;
333 
334 	if (negate) {
335 		signed_value = -value;
336 		if (signed_value > 0)
337 			return QDF_STATUS_E_RANGE;
338 	} else {
339 		signed_value = value;
340 		if (signed_value < 0)
341 			return QDF_STATUS_E_RANGE;
342 	}
343 
344 	*out_int = signed_value;
345 
346 	return QDF_STATUS_SUCCESS;
347 }
348 qdf_export_symbol(qdf_int64_parse);
349 
350 QDF_STATUS qdf_uint64_parse(const char *int_str, uint64_t *out_int)
351 {
352 	QDF_STATUS status;
353 	bool negate;
354 	uint64_t value;
355 
356 	status = qdf_int_parse(int_str, &value, &negate);
357 	if (QDF_IS_STATUS_ERROR(status))
358 		return status;
359 
360 	if (negate)
361 		return QDF_STATUS_E_RANGE;
362 
363 	*out_int = value;
364 
365 	return QDF_STATUS_SUCCESS;
366 }
367 qdf_export_symbol(qdf_uint64_parse);
368 
369 QDF_STATUS qdf_bool_parse(const char *bool_str, bool *out_bool)
370 {
371 	bool value;
372 
373 	QDF_BUG(bool_str);
374 	if (!bool_str)
375 		return QDF_STATUS_E_INVAL;
376 
377 	QDF_BUG(out_bool);
378 	if (!out_bool)
379 		return QDF_STATUS_E_INVAL;
380 
381 	bool_str = qdf_str_left_trim(bool_str);
382 
383 	switch (bool_str[0]) {
384 	case '1':
385 	case 'y':
386 	case 'Y':
387 		value = true;
388 		break;
389 	case '0':
390 	case 'n':
391 	case 'N':
392 		value = false;
393 		break;
394 	default:
395 		return QDF_STATUS_E_FAILURE;
396 	}
397 
398 	bool_str++;
399 	bool_str = qdf_str_left_trim(bool_str);
400 	if (bool_str[0] != '\0')
401 		return QDF_STATUS_E_FAILURE;
402 
403 	*out_bool = value;
404 
405 	return QDF_STATUS_SUCCESS;
406 }
407 qdf_export_symbol(qdf_bool_parse);
408 
409 QDF_STATUS qdf_mac_parse(const char *mac_str, struct qdf_mac_addr *out_addr)
410 {
411 	QDF_STATUS status;
412 	struct qdf_mac_addr addr;
413 	bool colons;
414 	int i;
415 
416 	QDF_BUG(mac_str);
417 	if (!mac_str)
418 		return QDF_STATUS_E_INVAL;
419 
420 	QDF_BUG(out_addr);
421 	if (!out_addr)
422 		return QDF_STATUS_E_INVAL;
423 
424 	mac_str = qdf_str_left_trim(mac_str);
425 
426 	/* parse leading hex pair */
427 	status = qdf_consume_hex_pair(&mac_str, &addr.bytes[0]);
428 	if (QDF_IS_STATUS_ERROR(status))
429 		return status;
430 
431 	/* dynamically detect colons */
432 	colons = mac_str[0] == ':';
433 
434 	for (i = 1; i < QDF_MAC_ADDR_SIZE; i++) {
435 		/* ensure colon separator if previously detected */
436 		if (colons) {
437 			status = qdf_consume_char(&mac_str, ':');
438 			if (QDF_IS_STATUS_ERROR(status))
439 				return status;
440 		}
441 
442 		/* parse next hex pair */
443 		status = qdf_consume_hex_pair(&mac_str, &addr.bytes[i]);
444 		if (QDF_IS_STATUS_ERROR(status))
445 			return status;
446 	}
447 
448 	mac_str = qdf_str_left_trim(mac_str);
449 	if (mac_str[0] != '\0')
450 		return QDF_STATUS_E_FAILURE;
451 
452 	*out_addr = addr;
453 
454 	return QDF_STATUS_SUCCESS;
455 }
456 qdf_export_symbol(qdf_mac_parse);
457 
458 QDF_STATUS qdf_ipv4_parse(const char *ipv4_str, struct qdf_ipv4_addr *out_addr)
459 {
460 	QDF_STATUS status;
461 	struct qdf_ipv4_addr addr;
462 	int i;
463 
464 	QDF_BUG(ipv4_str);
465 	if (!ipv4_str)
466 		return QDF_STATUS_E_INVAL;
467 
468 	QDF_BUG(out_addr);
469 	if (!out_addr)
470 		return QDF_STATUS_E_INVAL;
471 
472 	ipv4_str = qdf_str_left_trim(ipv4_str);
473 
474 	/* parse leading octet */
475 	status = qdf_consume_octet_dec(&ipv4_str, &addr.bytes[0]);
476 	if (QDF_IS_STATUS_ERROR(status))
477 		return status;
478 
479 	for (i = 1; i < QDF_IPV4_ADDR_SIZE; i++) {
480 		/* ensure dot separator */
481 		status = qdf_consume_char(&ipv4_str, '.');
482 		if (QDF_IS_STATUS_ERROR(status))
483 			return status;
484 
485 		/* parse next octet */
486 		status = qdf_consume_octet_dec(&ipv4_str, &addr.bytes[i]);
487 		if (QDF_IS_STATUS_ERROR(status))
488 			return status;
489 	}
490 
491 	ipv4_str = qdf_str_left_trim(ipv4_str);
492 	if (ipv4_str[0] != '\0')
493 		return QDF_STATUS_E_FAILURE;
494 
495 	*out_addr = addr;
496 
497 	return QDF_STATUS_SUCCESS;
498 }
499 qdf_export_symbol(qdf_ipv4_parse);
500 
501 static inline void qdf_ipv6_apply_zero_comp(struct qdf_ipv6_addr *addr,
502 					    uint8_t hextets,
503 					    uint8_t zero_comp_index)
504 {
505 	/* Given the following hypothetical ipv6 address:
506 	 * |---------------------------------------|
507 	 * | 01 | ab | cd | ef |    |    |    |    |
508 	 * |---------------------------------------|
509 	 *           ^--- zero_comp_index (2)
510 	 * from -----^
511 	 * to ---------------------------^
512 	 * |    hextets (4)    |
513 	 *                     |   zero comp size  |
514 	 *           | to move |
515 	 *
516 	 * We need to apply the zero compression such that we get:
517 	 * |---------------------------------------|
518 	 * | 01 | ab | 00 | 00 | 00 | 00 | cd | ef |
519 	 * |---------------------------------------|
520 	 *           |     zero comp     |
521 	 *                               |  moved  |
522 	 */
523 
524 	size_t zero_comp_size = (QDF_IPV6_ADDR_HEXTET_COUNT - hextets) * 2;
525 	size_t bytes_to_move = (hextets - zero_comp_index) * 2;
526 	uint8_t *from = &addr->bytes[zero_comp_index * 2];
527 	uint8_t *to = from + zero_comp_size;
528 
529 	if (bytes_to_move)
530 		qdf_mem_move(to, from, bytes_to_move);
531 
532 	qdf_mem_zero(from, to - from);
533 }
534 
535 QDF_STATUS qdf_ipv6_parse(const char *ipv6_str, struct qdf_ipv6_addr *out_addr)
536 {
537 	QDF_STATUS status;
538 	struct qdf_ipv6_addr addr;
539 	int8_t zero_comp = -1;
540 	uint8_t hextets_found = 0;
541 
542 	QDF_BUG(ipv6_str);
543 	if (!ipv6_str)
544 		return QDF_STATUS_E_INVAL;
545 
546 	QDF_BUG(out_addr);
547 	if (!out_addr)
548 		return QDF_STATUS_E_INVAL;
549 
550 	ipv6_str = qdf_str_left_trim(ipv6_str);
551 
552 	/* check for leading zero-compression ("::") */
553 	status = qdf_consume_char(&ipv6_str, ':');
554 	if (QDF_IS_STATUS_SUCCESS(status)) {
555 		status = qdf_consume_char(&ipv6_str, ':');
556 		if (QDF_IS_STATUS_SUCCESS(status))
557 			zero_comp = 0;
558 		else
559 			return QDF_STATUS_E_FAILURE;
560 	}
561 
562 	while (hextets_found < QDF_IPV6_ADDR_HEXTET_COUNT) {
563 		uint16_t hextet;
564 
565 		/* parse hextet */
566 		status = qdf_consume_hextet(&ipv6_str, &hextet);
567 		if (QDF_IS_STATUS_ERROR(status)) {
568 			/* we must end with hextet or zero compression */
569 			if (hextets_found != zero_comp)
570 				return QDF_STATUS_E_FAILURE;
571 
572 			break;
573 		}
574 
575 		addr.bytes[hextets_found * 2] = hextet >> 8;
576 		addr.bytes[hextets_found * 2 + 1] = hextet;
577 		hextets_found++;
578 
579 		/* parse ':' char */
580 		status = qdf_consume_char(&ipv6_str, ':');
581 		if (QDF_IS_STATUS_ERROR(status))
582 			break;
583 
584 		/* check for zero compression ("::") */
585 		status = qdf_consume_char(&ipv6_str, ':');
586 		if (QDF_IS_STATUS_SUCCESS(status)) {
587 			/* only one zero compression is allowed */
588 			if (zero_comp >= 0)
589 				return QDF_STATUS_E_FAILURE;
590 
591 			zero_comp = hextets_found;
592 		}
593 	}
594 
595 	ipv6_str = qdf_str_left_trim(ipv6_str);
596 	if (ipv6_str[0] != '\0')
597 		return QDF_STATUS_E_FAILURE;
598 
599 	/* we must have max hextets or a zero compression, but not both */
600 	if (hextets_found < QDF_IPV6_ADDR_HEXTET_COUNT) {
601 		if (zero_comp < 0)
602 			return QDF_STATUS_E_FAILURE;
603 
604 		qdf_ipv6_apply_zero_comp(&addr, hextets_found, zero_comp);
605 	} else if (zero_comp > -1) {
606 		return QDF_STATUS_E_FAILURE;
607 	}
608 
609 	*out_addr = addr;
610 
611 	return QDF_STATUS_SUCCESS;
612 }
613 qdf_export_symbol(qdf_ipv6_parse);
614 
615 QDF_STATUS qdf_uint8_array_parse(const char *in_str, uint8_t *out_array,
616 				 qdf_size_t array_size, qdf_size_t *out_size)
617 {
618 	QDF_STATUS status;
619 	bool negate;
620 	qdf_size_t size = 0;
621 	uint64_t value;
622 
623 	QDF_BUG(in_str);
624 	if (!in_str)
625 		return QDF_STATUS_E_INVAL;
626 
627 	QDF_BUG(out_array);
628 	if (!out_array)
629 		return QDF_STATUS_E_INVAL;
630 
631 	QDF_BUG(out_size);
632 	if (!out_size)
633 		return QDF_STATUS_E_INVAL;
634 
635 	while (size < array_size) {
636 		status = __qdf_int_parse_lazy(&in_str, &value, &negate);
637 		if (QDF_IS_STATUS_ERROR(status))
638 			return status;
639 
640 		if ((uint8_t)value != value || negate)
641 			return QDF_STATUS_E_RANGE;
642 
643 		in_str = qdf_str_left_trim(in_str);
644 
645 		switch (in_str[0]) {
646 		case ',':
647 			out_array[size++] = value;
648 			in_str++;
649 			break;
650 		case '\0':
651 			out_array[size++] = value;
652 			*out_size = size;
653 			return QDF_STATUS_SUCCESS;
654 		default:
655 			return QDF_STATUS_E_FAILURE;
656 		}
657 	}
658 
659 	return QDF_STATUS_E_FAILURE;
660 }
661 
662 qdf_export_symbol(qdf_uint8_array_parse);
663