New feature in v3: cast!

Arran Cudbard-Bell a.cudbardb at freeradius.org
Sun May 12 20:40:53 CEST 2013


On 12 May 2013, at 14:02, Brian Candler <B.Candler at pobox.com> wrote:

> On Sun, May 12, 2013 at 08:40:14AM -0400, Alan DeKok wrote:
>>> 1. Why is <ipaddr> necessary before the literal? Surely an unquoted
>>> 127.0.0.1 can't be parsed as anything else.
>> 
>>  See my other example for why it's necessary.
>> 
>>  In *some* cases, you know the data type of an expression.  In those
>> cases, you can easily do type-specific comparisons.  That's what unlang
>> does today:
>> 
>> 	if (Framed-IP-Address == 127.0.0.1) {
>> 
>>  The type is "ipaddr", because of Framed-IP-Address.  The RHS is in
>> fact parsed into a second Framed-IP-Address attribute, and the two are
>> compared.
> 
> So if I understand you rightly, you're saying that the unlang expressions
> 
>   Framed-IP-Address == 127.0.0.1
> 
> and
> 
>   Framed-IP-Address == "127.0.0.1"
> 
> are treated identically - it's the type of the LHS which makes a difference,
> and no distinction is made between an IP literal and a string literal. Is
> that correct?
> 
> Is there a fundamental reason why literal values can't have types?
> 
> The canonical example would be the difference between 1 and "1". Say:
> 
>    if (Acct-Session-Time < 100)
> 
> But presumably
> 
>    if (Acct-Session-Time < "100")
> 
> is handled the same today (i.e. the "100" is converted to an integer because
> of the LHS type).

Right.

> 
>>  However... you can't currently do a type-safe comparison like:
>> 
>> 	if (127.0.0.1 < 127.0.0.2) {
>> 
>>  The interpretor does *string* comparisons.  Which is wrong for IP
>> addresses.
> 
> ... which again implies this is parsed exactly the same as
> 
>    if ("127.0.0.1" < "127.0.0.2")

Yes.

> 
> But there must be something else going on, because on the LHS at least,
> Framed-IP-Address is not parsed the same as "Framed-IP-Address"

It's a hangover for backwards compatibility and arguably wrong.

I strongly suggested that we disallow it for the sake of clarity but Alan
was worried it'd break existing implementations.

The proper syntax for such a comparison is:

if (&Framed-IP-Address > 192.168.0.0/24) {

}

I originally argued that string literals must all be wrapped in single quotes,
but this would have meant boolean values and enumerated values would also have
been required to be wrapped.

i.e.

update request {
	Service-Type := 'Framed-User'
}

update control {
	Fall-Through := 'no'
}

> 
>>> 2. What does the & in front of Framed-IP-Address do?
>> 
>> $ man unlang  :)
>> 
>>  It's a reference.
>> 
>> 	if (&User-Name == &Filter-Id) {
>> 
>>  Does type-safe comparisons on the *values* of the two attributes.
> 
> That's pretty different to most languages though, were A == B compares the
> values of A and B, and & gives you a reference to the variable; you want to
> compare the values, not the references.

Not so much. I believe === in most languages would get you a strict comparison
between references. That could be implemented here very easily but I can't see
many places where it'd be useful.

Think of &<attribute> being more like $<variable> in PHP.

> 
> Having said that, I seem to remember that C++ does magic dereferencing,
> converting references to values where required.  But the main purpose of
> taking a reference is to allow a variable to be assigned to at a distance.

The main point here is to clearly mark attributes as distinct from literals.

I believe it's also supported in unlang now.

update reply {
	Reply-Message := "User-Name was &User-Name, Framed-IP-Address was &Framed-IP-Address"
}

And %{<attribute>} is deprecated.

>> The
>> v2 unlang code would require you to do:
>> 
>> 	if (User-Name == "%{Filter-Id}") {
> 
> Ah yes, because of things like Acct-Status-Type == Start, where the RHS has
> to be considered as an enumerated value rather than another attribute.

Exactly.

Though i'm guessing

Acct-Status-Type == 'Start' or Acct-Status-Type == "Start" would probably work just as well.

I think it's sort of dumb to treat bare words essentially the same as literals. I'd have
rather used them as attribute references everywhere.

But apparently not requiring enumerated values, integer values or IP addresses be wrapped
in quotes trumps the convenience of barewords refer to attributes.

At least attribute references are consistent now, whether it's in conditional statements,
xlat strings, update blocks, switch statements (I hope), you can always reference attributes
in the same way. Any added consistency is a good thing :)

Arran Cudbard-Bell <a.cudbardb at freeradius.org>
FreeRADIUS Development Team



More information about the Freeradius-Devel mailing list