Add tests for %{integer:} and fix up some odd cases
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Fri, 24 Jan 2014 22:59:03 +0000 (22:59 +0000)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Fri, 24 Jan 2014 23:02:02 +0000 (23:02 +0000)
Allow printing of the ASCII representation of most data types

share/dictionary.freeradius.internal
src/lib/valuepair.c
src/main/xlat.c
src/tests/keywords/integer [new file with mode: 0644]

index 5cfc1e6..3ee56bf 100644 (file)
@@ -430,6 +430,17 @@ ATTRIBUTE  Tmp-Date-6                              1846    date
 ATTRIBUTE      Tmp-Date-7                              1847    date
 ATTRIBUTE      Tmp-Date-8                              1848    date
 ATTRIBUTE      Tmp-Date-9                              1849    date
+
+ATTRIBUTE      Tmp-Integer64-0                         1871    integer64
+ATTRIBUTE      Tmp-Integer64-1                         1872    integer64
+ATTRIBUTE      Tmp-Integer64-2                         1873    integer64
+ATTRIBUTE      Tmp-Integer64-3                         1874    integer64
+ATTRIBUTE      Tmp-Integer64-4                         1875    integer64
+ATTRIBUTE      Tmp-Integer64-5                         1876    integer64
+ATTRIBUTE      Tmp-Integer64-6                         1877    integer64
+ATTRIBUTE      Tmp-Integer64-7                         1878    integer64
+ATTRIBUTE      Tmp-Integer64-8                         1879    integer64
+ATTRIBUTE      Tmp-Integer64-9                         1880    integer64
 #
 #  These attributes shouldn't be used anywhere.  They are defined here
 #  only for casting of values in conditional expressions.
index bbc1334..961d5cf 100644 (file)
@@ -1336,6 +1336,9 @@ bool pairparsevalue(VALUE_PAIR *vp, char const *value)
 
                        /*
                         *      Convert things which are obviously integers to IP addresses
+                        *
+                        *      We assume the number is the bigendian representation of the
+                        *      IP address.
                         */
                        if (fr_integer_check(value)) {
                                vp->vp_ipaddr = htonl(atol(value));
@@ -1613,6 +1616,19 @@ bool pairparsevalue(VALUE_PAIR *vp, char const *value)
                {
                        char const *c1, *c2;
 
+                       /*
+                        *      Convert things which are obviously integers to Ethernet addresses
+                        *
+                        *      We assume the number is the bigendian representation of the
+                        *      ethernet address.
+                        */
+                       if (fr_integer_check(value)) {
+                               uint64_t integer = htonll(atoll(value));
+
+                               memcpy(&vp->vp_ether, &integer, sizeof(vp->vp_ether));
+                               break;
+                       }
+
                        length = 0;
                        cp = value;
                        while (*cp) {
index 5a8c0fb..71ba042 100644 (file)
@@ -173,7 +173,8 @@ static ssize_t xlat_integer(UNUSED void *instance, REQUEST *request,
 {
        VALUE_PAIR      *vp;
 
-       uint64_t        integer;
+       uint64_t        int64 = 0;      /* Needs to be initialised to zero */
+       uint32_t        int32 = 0;      /* Needs to be initialised to zero */
 
        while (isspace((int) *fmt)) fmt++;
 
@@ -188,22 +189,38 @@ static ssize_t xlat_integer(UNUSED void *instance, REQUEST *request,
                if (vp->length > 8) {
                        break;
                }
-               memcpy(&integer, &(vp->vp_octets), vp->length);
-               return snprintf(out, outlen, "%" PRIu64, ntohll(integer));
+
+               if (vp->length > 4) {
+                       memcpy(&int64, vp->vp_octets, vp->length);
+                       return snprintf(out, outlen, "%" PRIu64, htonll(int64));
+               }
+
+               memcpy(&int32, vp->vp_octets, vp->length);
+               return snprintf(out, outlen, "%i", htonl(int32));
 
        case PW_TYPE_INTEGER64:
                return snprintf(out, outlen, "%" PRIu64, vp->vp_integer64);
 
-       case PW_TYPE_INTEGER:
+       /*
+        *      IP addresses are treated specially, as parsing functions assume the value
+        *      is bigendian and will convert it for us.
+        */
        case PW_TYPE_IPADDR:
+               return snprintf(out, outlen, "%u", htonl(vp->vp_ipaddr));
+
+       case PW_TYPE_INTEGER:
        case PW_TYPE_DATE:
        case PW_TYPE_BYTE:
        case PW_TYPE_SHORT:
                return snprintf(out, outlen, "%u", vp->vp_integer);
 
+       /*
+        *      Ethernet is weird... It's network related, so we assume to it should be
+        *      bigendian.
+        */
        case PW_TYPE_ETHERNET:
-               memcpy(&integer, &(vp->vp_ether), vp->length);
-               return snprintf(out, outlen, "%" PRIu64, ntohll(integer));
+               memcpy(&int64, &vp->vp_ether, vp->length);
+               return snprintf(out, outlen, "%" PRIu64, htonll(int64));
 
        case PW_TYPE_SIGNED:
                return snprintf(out, outlen, "%i", vp->vp_signed);
@@ -212,8 +229,8 @@ static ssize_t xlat_integer(UNUSED void *instance, REQUEST *request,
                break;
        }
 
-       REDEBUG("Type \"%s\" cannot be converted to integer",
-               fr_int2str(dict_attr_types, vp->da->type, PW_TYPE_INVALID));
+       REDEBUG("Type '%s' of length %zu cannot be converted to integer",
+               fr_int2str(dict_attr_types, vp->da->type, PW_TYPE_INVALID), vp->length);
        *out = '\0';
 
        return -1;
@@ -239,6 +256,9 @@ static ssize_t xlat_hex(UNUSED void *instance, REQUEST *request,
        }
 
        ret = rad_vp2data(&p, vp);
+       if (ret < 0) {
+               return ret;
+       }
        len = (size_t) ret;
 
        /*
@@ -399,8 +419,10 @@ static ssize_t xlat_foreach(void *instance, REQUEST *request,
 static ssize_t xlat_string(UNUSED void *instance, REQUEST *request,
                           char const *fmt, char *out, size_t outlen)
 {
-       int len;
+       size_t len;
+       ssize_t ret;
        VALUE_PAIR *vp;
+       uint8_t const *p;
 
        while (isspace((int) *fmt)) fmt++;
        if (*fmt == '&') fmt++;
@@ -413,10 +435,24 @@ static ssize_t xlat_string(UNUSED void *instance, REQUEST *request,
 
        if ((radius_get_vp(&vp, request, fmt) < 0) || !vp) goto nothing;
 
-       if (vp->da->type != PW_TYPE_OCTETS) goto nothing;
+       ret = rad_vp2data(&p, vp);
+       if (ret < 0) {
+               return ret;
+       }
+
+       switch (vp->da->type) {
+               case PW_TYPE_OCTETS:
+                       len = fr_print_string((char const *) p, vp->length, out, outlen);
+                       break;
 
-       len = fr_print_string(vp->vp_strvalue, vp->length, out, outlen);
-       out[len] = '\0';
+               case PW_TYPE_STRING:
+                       len = strlcpy(out, vp->vp_strvalue, outlen);
+                       break;
+
+               default:
+                       len = fr_print_string((char const *) p, ret, out, outlen);
+                       break;
+       }
 
        return len;
 }
diff --git a/src/tests/keywords/integer b/src/tests/keywords/integer
new file mode 100644 (file)
index 0000000..f9ca64a
--- /dev/null
@@ -0,0 +1,197 @@
+#
+# PRE: update
+#
+update reply {
+       Filter-Id := "filter"
+}
+
+update request {
+       Tmp-String-0        := '9870'
+       Tmp-String-1        := '98709870'
+       Tmp-String-2        := '987098709870'
+       Tmp-Octets-0        := 0x39383731
+       Tmp-Octets-1        := 0x3938373139383731
+       Tmp-Octets-2        := 0x393837313938373139383731
+       Tmp-IP-Address-0    := 57.56.55.50
+       Tmp-Date-0          := 959985459
+       Tmp-Integer-0       := 959985460
+       Tmp-Cast-Abinary    := 'ip out forward srcip 57.56.55.53/32 udp dstport = 1812'
+       Tmp-Cast-IfId       := '0000:0000:3938:3737'
+       Tmp-Cast-IPv6Addr   := '::3938:3738'
+       Tmp-Cast-IPv6Prefix := '::3938:3739/128'
+       Tmp-Cast-Byte       := 58
+       Tmp-Cast-Short      := 14139
+       Tmp-Cast-Ethernet   := 00:00:39:38:37:3c
+       Tmp-Cast-Integer64  := 1152921505566832445
+       Tmp-Cast-IPv4Prefix := 57.56.55.62/32
+}
+
+update request {
+       Tmp-String-2        := "%{integer:Tmp-IP-Address-0}"
+       Tmp-String-3        := "%{integer:Tmp-Date-0}"
+       Tmp-String-4        := "%{integer:Tmp-Integer-0}"
+       Tmp-String-5        := "%{integer:Tmp-Cast-Abinary}"
+       Tmp-String-6        := "%{integer:Tmp-Cast-Ifid}"
+       Tmp-String-7        := "%{integer:Tmp-Cast-IPv6Addr}"
+       Tmp-String-8        := "%{integer:Tmp-Cast-IPv6Prefix}"
+}
+
+# String - network order representation of a 4 char string
+update request {
+       Tmp-Integer-0 := "%{integer:Tmp-String-0}"
+}
+if ((Tmp-String-0 != "%{string:Tmp-Integer-0}") || (Tmp-Integer-0 != 959985456)) {
+       update reply {
+               Filter-Id += 'fail'
+       }
+}
+
+# String - network order representation of a 8 char string
+update request {
+       Tmp-Integer64-0 := "%{integer:Tmp-String-1}"
+}
+if ((Tmp-String-1 != "%{string:Tmp-Integer64-0}") || (Tmp-Integer64-0 != 4123106139115632432)) {
+       update reply {
+               Filter-Id += 'fail'
+       }
+}
+
+# String - Can't convert 12 byte string to integer (our biggest native size is a 64bit unsigned int)
+if ("%{integer:Tmp-String-2}" != '') {
+       update reply {
+               Filter-Id += 'fail'
+       }
+}
+
+# Octets - network order representation of a 4 byte octet string
+update request {
+       Tmp-Integer-0 := "%{integer:Tmp-Octets-0}"
+}
+if ((Tmp-Octets-0 != "0x%{hex:Tmp-Integer-0}") || (Tmp-Integer-0 != 959985457)) {
+       update reply {
+               Filter-Id += 'fail'
+       }
+}
+
+# Octets - network order representation of a 8 byte octet string
+update request {
+       Tmp-Integer64-0 := "%{integer:Tmp-Octets-1}"
+}
+if ((Tmp-Octets-1 != "0x%{hex:Tmp-Integer64-0}") || (Tmp-Integer64-0 != 4123106143410599729)) {
+       update reply {
+               Filter-Id += 'fail'
+       }
+}
+
+# String - Can't convert 12 byte octet string to integer (our biggest native size is a 64bit unsigned int)
+if ("%{integer:Tmp-Octets-2}" != '') {
+       update reply {
+               Filter-Id += 'fail'
+       }
+}
+
+# IP Address
+if (Tmp-String-2 != '959985458') {
+       update reply {
+               Filter-Id += 'fail'
+       }
+}
+
+if (<ipaddr>Tmp-String-2 != &Tmp-IP-Address-0) {
+       update reply {
+               Filter-Id += 'fail'
+       }
+}
+
+# Date
+if (Tmp-String-3 != '959985459') {
+       update reply {
+               Filter-Id += 'fail'
+       }
+}
+
+# Integer
+if (Tmp-String-4 != '959985460') {
+       update reply {
+               Filter-Id += 'fail'
+       }
+}
+
+# Abinary - Can't convert ascend binary to an integer
+if (Tmp-String-5 != '') {
+       update reply {
+               Filter-Id += 'fail'
+       }
+}
+
+# ifid - Can't convert interface ID to an integer
+if (Tmp-String-6 != '') {
+       update reply {
+               Filter-Id += 'fail'
+       }
+}
+
+# ipv6addr - Can't convert IPv6 to integer
+if (Tmp-String-7 != '') {
+       update reply {
+               Filter-ID += 'fail'
+       }
+}
+
+# ipv6addrprefix
+if (Tmp-String-8 != '') {
+       update reply {
+               Filter-ID += 'fail'
+       }
+}
+update request {
+       Tmp-String-0        := "%{integer:Tmp-Cast-Byte}"
+       Tmp-String-1        := "%{integer:Tmp-Cast-Short}"
+       Tmp-String-2        := "%{integer:Tmp-Cast-Ethernet}"
+       Tmp-String-3        := "%{integer:Tmp-Cast-Integer64}"
+       Tmp-String-4        := "%{integer:Tmp-Cast-IPv4Prefix}"
+}
+
+# byte
+if (Tmp-String-0 != '58') {
+       update reply {
+               Filter-ID += 'fail'
+       }
+}
+
+# short
+if (Tmp-String-1 != '14139') {
+       update reply {
+               Filter-ID += 'fail'
+       }
+}
+
+# ethernet
+if (Tmp-String-2 != '62913607630848') {
+       update reply {
+               Filter-Id += 'fail'
+       }
+}
+if (<ether>Tmp-String-2 != &Tmp-Cast-Ethernet) {
+       update reply {
+               Filter-Id += 'fail'
+       }
+}
+
+# integer64
+if (Tmp-String-3 != '1152921505566832445') {
+       update reply {
+               Filter-Id += 'fail'
+       }
+}
+
+# ipv4prefix
+if (Tmp-String-4 != '') {
+       update reply {
+               Filter-Id += 'fail'
+       }
+}
+
+
+
+