1 /*
2  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3  *
4  * This Source Code Form is subject to the terms of the Mozilla Public
5  * License, v. 2.0. If a copy of the MPL was not distributed with this
6  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7  *
8  * See the COPYRIGHT file distributed with this work for additional
9  * information regarding copyright ownership.
10  */
11 
12 /*! \file */
13 
14 #include <ctype.h>
15 #include <errno.h>
16 #include <inttypes.h>
17 #include <limits.h>
18 #include <stdlib.h>
19 
20 #include <isc/parseint.h>
21 #include <isc/result.h>
22 
23 isc_result_t
isc_parse_uint32(uint32_t * uip,const char * string,int base)24 isc_parse_uint32(uint32_t *uip, const char *string, int base) {
25 	unsigned long n;
26 	uint32_t r;
27 	char *e;
28 	if (!isalnum((unsigned char)(string[0]))) {
29 		return (ISC_R_BADNUMBER);
30 	}
31 	errno = 0;
32 	n = strtoul(string, &e, base);
33 	if (*e != '\0') {
34 		return (ISC_R_BADNUMBER);
35 	}
36 	/*
37 	 * Where long is 64 bits we need to convert to 32 bits then test for
38 	 * equality.  This is a no-op on 32 bit machines and a good compiler
39 	 * will optimise it away.
40 	 */
41 	r = (uint32_t)n;
42 	if ((n == ULONG_MAX && errno == ERANGE) || (n != (unsigned long)r)) {
43 		return (ISC_R_RANGE);
44 	}
45 	*uip = r;
46 	return (ISC_R_SUCCESS);
47 }
48 
49 isc_result_t
isc_parse_uint16(uint16_t * uip,const char * string,int base)50 isc_parse_uint16(uint16_t *uip, const char *string, int base) {
51 	uint32_t val;
52 	isc_result_t result;
53 	result = isc_parse_uint32(&val, string, base);
54 	if (result != ISC_R_SUCCESS) {
55 		return (result);
56 	}
57 	if (val > 0xFFFF) {
58 		return (ISC_R_RANGE);
59 	}
60 	*uip = (uint16_t)val;
61 	return (ISC_R_SUCCESS);
62 }
63 
64 isc_result_t
isc_parse_uint8(uint8_t * uip,const char * string,int base)65 isc_parse_uint8(uint8_t *uip, const char *string, int base) {
66 	uint32_t val;
67 	isc_result_t result;
68 	result = isc_parse_uint32(&val, string, base);
69 	if (result != ISC_R_SUCCESS) {
70 		return (result);
71 	}
72 	if (val > 0xFF) {
73 		return (ISC_R_RANGE);
74 	}
75 	*uip = (uint8_t)val;
76 	return (ISC_R_SUCCESS);
77 }
78