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