Convert an integer to a MAC address in unlang / expr

classic Classic list List threaded Threaded
6 messages Options
| Threaded
Open this post in threaded view
|

Convert an integer to a MAC address in unlang / expr

James Wood
Hello,

FR 3.0.19

Quick one - I have some Aruba APs that are sending the BSSID in the
Called-Station-Id attribute instead of the base radio MAC. I need to get
back to the base radio MAC, so Aerohive has provided a mask we can apply to
find out the base radio MAC from this BSSID.

I am doing:

if (&Called-Station-Id =~
/^([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})([^0-9a-f](.+))?$/i)
 {
   update control {
       &Tmp-String-1 := "%{expr: 0x%{1}%{2}%{3}%{4}%{5}%{6} &
0xFFFFFFFFFFC0}"
   }
}

This works and the debug output shows &Tmp-String-1:

EXPAND %{expr: 0x%{1}%{2}%{3}%{4}%{5}%{6} & 0xFFFFFFFFFFC0}

--> 149928134221440

149928134221440 is correct so I need to base convert this integer back to a
real MAC in a format like  88-5B-DD-2E-9E-80 or  885BDD2E9E80 instead of
149928134221440.

Any thoughts?

Thanks,

James
-
List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html
| Threaded
Open this post in threaded view
|

Re: [EXT] Convert an integer to a MAC address in unlang / expr

Brian Julin


James Wood <[hidden email]>wrote:

>Quick one - I have some Aruba APs that are sending the BSSID in the
>Called-Station-Id attribute instead of the base radio MAC. I need to get
>back to the base radio MAC, so Aerohive has provided a mask we can apply to
>find out the base radio MAC from this BSSID.

>I am doing:

>if (&Called-Station-Id =~
>/^([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})([^0-9a-f](.+))?$/i)
> {
>   update control {
>      &Tmp-String-1 := "%{expr: 0x%{1}%{2}%{3}%{4}%{5}%{6} &
>0xFFFFFFFFFFC0}"
>   }
>}


First off, your interstitials between the octets should probably be looking for the '-' or ':' characters, not another hex digit.

%{hex:Attribute-Name} might work but I'm not sure it handles strings or whether %{hex:%expr{blah}} might work.  You'll have to chop off a leading "0x" afterwards.

You're actually chewing some data you don't need to.  The first 5 octets can just be left in string form, and the last octet will always end in 0 with that mask, so you only need to do math on the second to last digit (the first digit of the last octet).  Worst case once you've extracted that digit and masked it against 0xc you'll have 4 possible values and you could use an if statement to convert 12 back to "c" (the rest of the possible values are the same in hex and decimal).

Note that different Aruba AP models have different masks, though.



-
List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html
| Threaded
Open this post in threaded view
|

Re: Convert an integer to a MAC address in unlang / expr

Alan DeKok-2
In reply to this post by James Wood
On Aug 25, 2020, at 11:50 PM, James Wood <[hidden email]> wrote:
>
> Quick one - I have some Aruba APs that are sending the BSSID in the
> Called-Station-Id attribute instead of the base radio MAC. I need to get
> back to the base radio MAC, so Aerohive has provided a mask we can apply to
> find out the base radio MAC from this BSSID.

  Could you also provide the debug output?  That will let us know if the regex is correct at least.

> I am doing:
>
> if (&Called-Station-Id =~
> /^([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})([^0-9a-f](.+))?$/i)
> {
>   update control {
>       &Tmp-String-1 := "%{expr: 0x%{1}%{2}%{3}%{4}%{5}%{6} &
> 0xFFFFFFFFFFC0}"
>   }
> }
>
> This works and the debug output shows &Tmp-String-1:
>
> EXPAND %{expr: 0x%{1}%{2}%{3}%{4}%{5}%{6} & 0xFFFFFFFFFFC0}
>
> --> 149928134221440
>
> 149928134221440 is correct so I need to base convert this integer back to a
> real MAC in a format like  88-5B-DD-2E-9E-80 or  885BDD2E9E80 instead of
> 149928134221440.

  Without changing too much, you can do:

if (&Called-Station-Id =~
/^([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})[^0-9a-f]?([0-9a-f]{2})([^0-9a-f](.+))?$/i)
{
  update control {
      &Tmp-String-1 := "%{1}-%{2}-%{3}-%{4}-%{5}-%{expr:0x%{6} & 0xc0}"
  }
}

    Which should be a lot simpler.  The final value might still be printed as decimal, tho.  I don't think the %{hex:...} expansion will do what you want.

  Alan DeKok.


-
List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html
| Threaded
Open this post in threaded view
|

RE: [EXT] Convert an integer to a MAC address in unlang / expr

James Wood
In reply to this post by James Wood
Thanks Brian and Alan for your advice.

If I just perform the mask transform on the last octet this works but of
course it returns the result as an int, so I can't find any built in
function to get that back to hex.

This is what I've ended up with; please let me know if you feel there is a
better/cleaner way without needing the IF statement

update control {
    &Tmp-String-1 := "%{1}-%{2}-%{3}-%{4}-%{5}"
    &Tmp-String-2 := "%{expr: 0x%{6} & 0xC0}"
}
if (&control:Tmp-String-2 && &control:Tmp-String-2 != "") {
    if (&control:Tmp-String-2 == "00") {
        update control {
                &Tmp-String-2 := "00"
        }
    }
    if (&control:Tmp-String-2 == "64") {
        update control {
                &Tmp-String-2 := "40"
        }
    }
    if (&control:Tmp-String-2 == "128") {
        update control {
                &Tmp-String-2 := "80"
        }
    }
    if (&control:Tmp-String-2 == "192") {
        update control {
                &Tmp-String-2 := "C0"
        }
    }

    update request {
        &Called-Station-Id :=
"%{control:Tmp-String-1}-%{control:Tmp-String-2}"
    }
}

Thanks,

James
-
List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html
| Threaded
Open this post in threaded view
|

Re: [EXT] Convert an integer to a MAC address in unlang / expr

Alan DeKok-2
On Aug 27, 2020, at 6:44 AM, James Wood <[hidden email]> wrote:
>
> If I just perform the mask transform on the last octet this works but of
> course it returns the result as an int, so I can't find any built in
> function to get that back to hex.

  There's %{hex:...} but it only works on attributes, not raw numbers.

> This is what I've ended up with; please let me know if you feel there is a
> better/cleaner way without needing the IF statement

  After some thinking I don't think there is.  I'll see if I can add some features to make this easier.

  Alan DeKok.


-
List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html
| Threaded
Open this post in threaded view
|

Re: [EXT] Convert an integer to a MAC address in unlang / expr

Brian Julin
In reply to this post by James Wood

James Wood <[hidden email]>

> Thanks Brian and Alan for your advice.
>
> If I just perform the mask transform on the last octet this works but of
> course it returns the result as an int, so I can't find any built in
> function to get that back to hex.

> This is what I've ended up with; please let me know if you feel there is a
> better/cleaner way without needing the IF statement

Take only the first digit into %{6}.  Then mask with 0xC.  Then divide by 16.

0/16 is 0, 64/16 is 4, 128/16 is 8 and 192/16 is 12.

So then just one if statement makes 12 into "C" and you can just put
that back in with a hard coded 0 after it... no need to convert 0 to "0"
or 4 to "4" or 8 to "8", they should stringify on their own.


-
List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html