]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
add operations and upcast on combo-ips and prefixes
authorAlan T. DeKok <aland@freeradius.org>
Fri, 8 Dec 2023 19:01:16 +0000 (14:01 -0500)
committerAlan T. DeKok <aland@freeradius.org>
Fri, 8 Dec 2023 19:01:34 +0000 (14:01 -0500)
src/lib/util/calc.c
src/tests/unit/calc.txt

index d5ad61012c779e3480418b074b3dea4ade030994..aa30f9066e94cf23c547a476c73d8881c811980a 100644 (file)
@@ -138,6 +138,48 @@ static const fr_type_t upcast_op[FR_TYPE_MAX + 1][FR_TYPE_MAX + 1] = {
                [FR_TYPE_FLOAT64] = FR_TYPE_IPV6_ADDR,
        },
 
+       [FR_TYPE_COMBO_IP_ADDR] = {
+               [FR_TYPE_IPV6_PREFIX] = FR_TYPE_COMBO_IP_PREFIX,
+
+               [FR_TYPE_BOOL] =   FR_TYPE_COMBO_IP_ADDR,
+
+               [FR_TYPE_UINT8] =   FR_TYPE_COMBO_IP_ADDR,
+               [FR_TYPE_UINT16] =  FR_TYPE_COMBO_IP_ADDR,
+               [FR_TYPE_UINT32] =  FR_TYPE_COMBO_IP_ADDR,
+               [FR_TYPE_UINT64] =  FR_TYPE_COMBO_IP_ADDR,
+
+               [FR_TYPE_SIZE] =    FR_TYPE_COMBO_IP_ADDR,
+
+               [FR_TYPE_INT8] =    FR_TYPE_COMBO_IP_ADDR,
+               [FR_TYPE_INT16] =   FR_TYPE_COMBO_IP_ADDR,
+               [FR_TYPE_INT32] =   FR_TYPE_COMBO_IP_ADDR,
+               [FR_TYPE_INT64] =   FR_TYPE_COMBO_IP_ADDR,
+
+               [FR_TYPE_FLOAT32] = FR_TYPE_COMBO_IP_ADDR,
+               [FR_TYPE_FLOAT64] = FR_TYPE_COMBO_IP_ADDR,
+       },
+
+       [FR_TYPE_COMBO_IP_PREFIX] = {
+               [FR_TYPE_IPV6_PREFIX] = FR_TYPE_COMBO_IP_PREFIX,
+
+               [FR_TYPE_BOOL] =   FR_TYPE_COMBO_IP_ADDR,
+
+               [FR_TYPE_UINT8] =   FR_TYPE_COMBO_IP_ADDR,
+               [FR_TYPE_UINT16] =  FR_TYPE_COMBO_IP_ADDR,
+               [FR_TYPE_UINT32] =  FR_TYPE_COMBO_IP_ADDR,
+               [FR_TYPE_UINT64] =  FR_TYPE_COMBO_IP_ADDR,
+
+               [FR_TYPE_SIZE] =    FR_TYPE_COMBO_IP_ADDR,
+
+               [FR_TYPE_INT8] =    FR_TYPE_COMBO_IP_ADDR,
+               [FR_TYPE_INT16] =   FR_TYPE_COMBO_IP_ADDR,
+               [FR_TYPE_INT32] =   FR_TYPE_COMBO_IP_ADDR,
+               [FR_TYPE_INT64] =   FR_TYPE_COMBO_IP_ADDR,
+
+               [FR_TYPE_FLOAT32] = FR_TYPE_COMBO_IP_ADDR,
+               [FR_TYPE_FLOAT64] = FR_TYPE_COMBO_IP_ADDR,
+       },
+
        /*
         *      Bools and to pretty much any numerical type result in
         *      the other integer.
@@ -1177,7 +1219,7 @@ static int calc_ipv4_addr(UNUSED TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_
        fr_value_box_t one, two;
        fr_value_box_t *a, *b;
 
-       fr_assert(dst->type == FR_TYPE_IPV4_ADDR);
+       fr_assert((dst->type == FR_TYPE_IPV4_ADDR) || (dst->type == FR_TYPE_COMBO_IP_ADDR));
 
        if (cast_ipv4_addr(&one, in1) < 0) return -1;
        a = &one;
@@ -1226,7 +1268,7 @@ static int calc_ipv4_prefix(UNUSED TALLOC_CTX *ctx, fr_value_box_t *dst, fr_valu
        int prefix;
        fr_value_box_t one, two, tmp;
 
-       fr_assert(dst->type == FR_TYPE_IPV4_PREFIX);
+       fr_assert((dst->type == FR_TYPE_IPV4_PREFIX) || (dst->type == FR_TYPE_COMBO_IP_PREFIX));
 
        switch (op) {
        case T_AND:
@@ -1376,7 +1418,7 @@ static int calc_ipv6_addr(UNUSED TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_
        int i;
        uint64_t mask;
 
-       fr_assert(dst->type == FR_TYPE_IPV6_ADDR);
+       fr_assert((dst->type == FR_TYPE_IPV6_ADDR) || (dst->type == FR_TYPE_COMBO_IP_ADDR));
 
        if (cast_ipv6_addr(&one, in1) < 0) return -1;
        a = &one;
@@ -1462,7 +1504,7 @@ static int calc_ipv6_prefix(UNUSED TALLOC_CTX *ctx, fr_value_box_t *dst, fr_valu
        uint8_t const *pa, *pb;
        uint8_t *pdst;
 
-       fr_assert(dst->type == FR_TYPE_IPV6_PREFIX);
+       fr_assert((dst->type == FR_TYPE_IPV6_PREFIX) || (dst->type == FR_TYPE_COMBO_IP_PREFIX));
 
        if (a->type == FR_TYPE_OCTETS) {
                if (a->vb_length != (128 / 8)) {
@@ -1514,6 +1556,30 @@ static int calc_ipv6_prefix(UNUSED TALLOC_CTX *ctx, fr_value_box_t *dst, fr_valu
        return 0;
 }
 
+#define is_ipv6(_x) (((_x)->type == FR_TYPE_IPV6_ADDR) || ((_x)->type == FR_TYPE_IPV6_PREFIX) || ((((_x)->type == FR_TYPE_COMBO_IP_ADDR) || ((_x)->type == FR_TYPE_COMBO_IP_PREFIX)) && ((_x)->vb_ip.af == AF_INET6)))
+
+static int calc_combo_ip_addr(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_t const *in1, fr_token_t op, fr_value_box_t const *in2)
+{
+       /*
+        *      IPv6 is better than IPv4!
+        */
+       if (is_ipv6(in1) || is_ipv6(in2)) {
+               return calc_ipv6_addr(ctx, dst, in1, op, in2);
+       }
+
+       return calc_ipv4_addr(ctx, dst, in1, op, in2);
+}
+
+static int calc_combo_ip_prefix(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_t const *in1, fr_token_t op, fr_value_box_t const *in2)
+{
+       if (is_ipv6(in1) || is_ipv6(in2)) {
+               return calc_ipv6_prefix(ctx, dst, in1, op, in2);
+       }
+
+       return calc_ipv4_prefix(ctx, dst, in1, op, in2);
+}
+
+
 static int calc_float32(UNUSED TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_t const *in1, fr_token_t op, fr_value_box_t const *in2)
 {
        fr_value_box_t one, two;
@@ -1775,6 +1841,9 @@ static int calc_int64(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_t const
 
 typedef int (*fr_binary_op_t)(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_t const *a, fr_token_t op, fr_value_box_t const *b);
 
+/** Map output type to its associated function
+ *
+ */
 static const fr_binary_op_t calc_type[FR_TYPE_MAX + 1] = {
        [FR_TYPE_BOOL]          = calc_bool,
 
@@ -1783,9 +1852,13 @@ static const fr_binary_op_t calc_type[FR_TYPE_MAX + 1] = {
 
        [FR_TYPE_IPV4_ADDR]     = calc_ipv4_addr,
        [FR_TYPE_IPV4_PREFIX]   = calc_ipv4_prefix,
+
        [FR_TYPE_IPV6_ADDR]     = calc_ipv6_addr,
        [FR_TYPE_IPV6_PREFIX]   = calc_ipv6_prefix,
 
+       [FR_TYPE_COMBO_IP_ADDR] = calc_combo_ip_addr,
+       [FR_TYPE_COMBO_IP_PREFIX] = calc_combo_ip_prefix,
+
        [FR_TYPE_UINT8]         = calc_uint64,
        [FR_TYPE_UINT16]        = calc_uint64,
        [FR_TYPE_UINT32]        = calc_uint64,
index b6b4f580c2cf52a076502b59bd05a55c1d84a12c..4306e1dea13bd5426a471825d2115f954c956d89 100644 (file)
@@ -173,6 +173,12 @@ match Cannot compare IPv4 with IPv6 address
 calc combo-prefix 127/8 + uint8 1 -> ipaddr
 match 127.0.0.1
 
+calc combo-prefix 127/8 + uint8 1 -> combo-ip
+match 127.0.0.1
+
+calc ipv4addr 192.168.2.1 & uint32 0xffff0000 -> combo-prefix
+match 192.168.0.0/16
+
 ######################################################################
 #
 #  Float
@@ -203,4 +209,4 @@ calc string "2" += string "test"
 match 2test
 
 count
-match 92
+match 96