From: Alan T. DeKok Date: Tue, 18 Jan 2022 15:47:37 +0000 (-0500) Subject: move "parse scope" to fr_inet_pton6() X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b63ba37d39a96528e1fb2770b3ca3de2d488c200;p=thirdparty%2Ffreeradius-server.git move "parse scope" to fr_inet_pton6() --- diff --git a/src/lib/util/inet.c b/src/lib/util/inet.c index 8291b7d005d..2a3632c16eb 100644 --- a/src/lib/util/inet.c +++ b/src/lib/util/inet.c @@ -607,7 +607,8 @@ int fr_inet_pton4(fr_ipaddr_t *out, char const *value, ssize_t inlen, bool resol */ int fr_inet_pton6(fr_ipaddr_t *out, char const *value, ssize_t inlen, bool resolve, bool fallback, bool mask) { - char const *p, *end; + char *p; + char const *end; unsigned int prefix; char *eptr; char buffer[256]; /* As per RFC1035 */ @@ -622,29 +623,33 @@ int fr_inet_pton6(fr_ipaddr_t *out, char const *value, ssize_t inlen, bool resol end = value + inlen; while ((value < end) && isspace((int) *value)) value++; if (value == end) { - fr_strerror_const("Empty IPv4 address string is invalid"); + fr_strerror_const("Empty IPv6 address string is invalid"); return -1; } - inlen = end - value; + inlen = end - value; /* always >0 due to the above check for value==end */ /* - * Copy to intermediary buffer if we were given a length + * Copy to intermediary buffer. */ - if (inlen >= 0) { - if (inlen >= (ssize_t)sizeof(buffer)) { - fr_strerror_printf("Invalid IPv6 address string \"%pV\"", fr_box_strvalue_len(value, inlen)); - return -1; - } - memcpy(buffer, value, inlen); - buffer[inlen] = '\0'; - value = buffer; + if (inlen >= (ssize_t)sizeof(buffer)) { + fr_strerror_printf("Invalid IPv6 address string \"%pV\"", fr_box_strvalue_len(value, inlen)); + return -1; } + memcpy(buffer, value, inlen); + buffer[inlen] = '\0'; + value = buffer; p = strchr(value, '/'); if (!p) { out->prefix = 128; out->af = AF_INET6; + /* + * Allow scopes for non-prefix values. + */ + p = strchr(value, '%'); + if (p) *(p++) = '\0'; + /* * Allow '*' as the wildcard address */ @@ -657,6 +662,30 @@ int fr_inet_pton6(fr_ipaddr_t *out, char const *value, ssize_t inlen, bool resol } } else if (fr_inet_hton(out, AF_INET6, value, fallback) < 0) return -1; + /* + * No scope, or just '%'. That's fine. + */ + if (!p || !*p) return 0; + + /* + * Parse scope. + */ + prefix = strtoul(p, &eptr, 10); + if (prefix > 128) { + fr_strerror_printf("Invalid scope ID \"%s\". Should be between 0-2^32-1", p); + return -1; + } + if (eptr[0] != '\0') { + fr_strerror_printf("Failed to parse scope \"%s\", " + "got garbage after numerical scope value \"%s\"", p, eptr); + return -1; + } + + if (prefix > UINT32_MAX) { + fr_strerror_printf("Invalid scope ID \"%s\"", p); + return -1; + } + return 0; } diff --git a/src/lib/util/value.c b/src/lib/util/value.c index 09cafe4e23d..cdadd43566b 100644 --- a/src/lib/util/value.c +++ b/src/lib/util/value.c @@ -4708,6 +4708,13 @@ parse: size_t name_len = fr_sbuff_adv_past_allowed(&our_in, fr_sbuff_remaining(&our_in), sbuff_char_class_hostname, rules->terminals); if (!name_len) return 0; + /* + * Parse scope, too. + */ + if (fr_sbuff_next_if_char(&our_in, '%')) { + name_len += fr_sbuff_adv_past_allowed(&our_in, fr_sbuff_remaining(&our_in), sbuff_char_class_hostname, sbuff_char_class_uint); + } + if (fr_inet_pton6(&addr, fr_sbuff_current(in), name_len, fr_hostname_lookups, false, true) < 0) return -1; @@ -4722,18 +4729,6 @@ parse: } memcpy(&dst->vb_ip, &addr, sizeof(dst->vb_ip)); - - /* - * Parse scopes, too. - */ - if (fr_sbuff_next_if_char(&our_in, '%')) { - slen = fr_sbuff_out(NULL, &dst->vb_ip.scope_id, &our_in); - if (slen <= 0) { - fr_strerror_printf("Failed parsing scope ID"); - return -1; - } - } - } goto finish;