On 15 Feb 2014, at 15:26, Alan DeKok <aland@deployingradius.com> wrote:
Arran Cudbard-Bell wrote:
Hm, no. Using RFC terms, and assuming were going for optimum efficiency:
if (${foo})
MUST NOT be optimised away, it is a attribute or rcode check with the value of the CONF_PAIR ${foo}
I'm not sure what you mean by "optimized away".
If the result of the condition cannot change during the processing of a request the condition is not evaluated during the processing of a request. if ('foo' == 'foo') { } Will always be true, so there's no need to strcmp foo and foo on every request.
${foo} gets replaced with the value of configuration item 'foo', by the configuration file reader. This happens *before* any analysis is done of the condition.
Yep.
e.g.
foo = 0 if (${foo}) { ...
and
if (0) { ...
are identical.
It sounds like your analysis is mixing up the two passes.
No, I'm aware they're different steps and ${} substitutions are done before everything else, my examples just weren't clear enough.
1) string substitution ${foo} --> value of configuration item "foo"
2) compilation to string xlat, attribute reference, etc.
if ("${foo}")
SHOULD be optimised away, it is an XLAT expansion only containing string literals.
Only if the string inside of the double quotes contains a % character.
Doesn't contain a % surely?
Where ${foo} -> '%{User-Name}'
MUST NOT be optimised away, it is an XLAT expansion containing an attribute reference.
Be careful with the single quotes. %{User-Name} is an xlat saying "the value of the User-Name attribute". '%{User-Name}' is a single-quoted string with contents %{User-Name}. The contents are a *static* string, and aren't dynamically expanded.
Sorry I wasn't being clear with the examples. I meant: ${foo} -> %{User-Name}
Ready to process requests. rad_recv: Access-Request packet from host 127.0.0.1 port 51784, id=52, length=38 User-Password = 'foo' (0) # Executing section authorize from file /usr/local/freeradius-3.0.x/etc/raddb/sites-enabled/default (0) authorize { (0) ? if (!'User-Name') (0) ? if (!'User-Name') -> FALSE
Yes. 'User-Name' is a non-NULL string, so it's always TRUE. !TRUE is FALSE.
Sure there was just no indication to show whether the evaluation was actually being skipped, it looked like it was still being performed, when as you say 'User-Name' is always true.
(0) ? if (!"User-Name") -> FALSE
The same applies here.
Same.
(0) ? if (!User-Name) -> TRUE
Here, User-Name is an attribute reference. The packet you sent didn't include a User-Name. So the check for existence of User-Name is FALSE, and !FALSE is TRUE.
Yep, that's correct, i'm not questioning the results of the evaluations they're all as I would expect. I was just pointing out that it's not clear that the condition isn't actually being evaluated.
(0) ? if (!('User-Name' == 'bar')) -> TRUE
That's correct. The string 'User-Name' is not the same as the string 'bar'. So that evaluates to FALSE. And !FALSE is TRUE.
Yep.
But I may be miss-understanding on how it's meant to operate.
The string substitution for ${var} is very simple, and is *completely* independent of the step which parses conditions. The "parse condition" step just sees text strings. All of the ${foo} magic has gone away.
I'm aware of that. It makes it much easier to comprehend what's going on when you think of ${} expansions as doing something to C preprocessor macros. It's just the output didn't look any different for conditions I expected to be pre-evaluated. If it's all happening transparently behind the scenes then that's fine. Arran Cudbard-Bell <a.cudbardb@freeradius.org> FreeRADIUS Development Team FD31 3077 42EC 7FCD 32FE 5EE2 56CF 27F9 30A8 CAA2