]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
move "parse scope" to fr_inet_pton6()
authorAlan T. DeKok <aland@freeradius.org>
Tue, 18 Jan 2022 15:47:37 +0000 (10:47 -0500)
committerAlan T. DeKok <aland@freeradius.org>
Tue, 18 Jan 2022 15:47:37 +0000 (10:47 -0500)
src/lib/util/inet.c
src/lib/util/value.c

index 8291b7d005d82a66872520aad1df04a7204d016e..2a3632c16eb965c9a52bfa9092e12ed54d42ce83 100644 (file)
@@ -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;
        }
 
index 09cafe4e23d0992c81b4b626607bc7d3c2e937d4..cdadd43566b9218f191a48ba6950e9c337158926 100644 (file)
@@ -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;