]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Added %{rand:...} to generate uniformly distributed random numbers
authorAlan T. DeKok <aland@freeradius.org>
Fri, 2 Sep 2011 21:38:00 +0000 (17:38 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Sat, 3 Sep 2011 00:48:13 +0000 (20:48 -0400)
src/modules/rlm_expr/rlm_expr.c

index 445004bbf9bfef073a904e6a8ac389906b7f9101..80e1f08aa49d8d36acee7343b4a698f3213dd128 100644 (file)
@@ -254,6 +254,40 @@ static size_t expr_xlat(void *instance, REQUEST *request, char *fmt,
        return strlen(out);
 }
 
+static size_t rand_xlat(void *instance, REQUEST *request, char *fmt,
+                       char *out, size_t outlen,
+                       RADIUS_ESCAPE_STRING func)
+{
+       int             rcode;
+       int64_t         result;
+       rlm_expr_t      *inst = instance;
+       char            buffer[256];
+
+       inst = inst;            /* -Wunused */
+
+       /*
+        * Do an xlat on the provided string (nice recursive operation).
+        */
+       if (!radius_xlat(buffer, sizeof(buffer), fmt, request, func)) {
+               radlog(L_ERR, "rlm_expr: xlat failed.");
+               return 0;
+       }
+
+       result = atoi(buffer);
+
+       /*
+        *      Too small or too big.
+        */
+       if (result <= 0) return 0;
+       if (result >= (1 << 30)) result = (1 << 30);
+
+       result *= fr_rand();    /* 0..2^32-1 */
+       result >>= 32;
+
+       snprintf(out, outlen, "%ld", (long int) result);
+       return strlen(out);
+}
+
 /*
  *     Do any per-module initialization that is separate to each
  *     configured instance of the module.  e.g. set up connections
@@ -285,6 +319,9 @@ static int expr_instantiate(CONF_SECTION *conf, void **instance)
                inst->xlat_name = strdup(xlat_name);
                xlat_register(xlat_name, expr_xlat, inst);
        }
+
+       xlat_register("rand", rand_xlat, inst);
+
        /*
         * Initialize various paircompare functions
         */