@ -215,6 +215,7 @@ static const struct radius_attr_type radius_attrs[] =
RADIUS_ATTR_INT32 } ,
{ RADIUS_ATTR_EVENT_TIMESTAMP , " Event-Timestamp " ,
RADIUS_ATTR_INT32 } ,
{ RADIUS_ATTR_EGRESS_VLANID , " EGRESS-VLANID " , RADIUS_ATTR_HEXDUMP } ,
{ RADIUS_ATTR_NAS_PORT_TYPE , " NAS-Port-Type " , RADIUS_ATTR_INT32 } ,
{ RADIUS_ATTR_TUNNEL_TYPE , " Tunnel-Type " , RADIUS_ATTR_HEXDUMP } ,
{ RADIUS_ATTR_TUNNEL_MEDIUM_TYPE , " Tunnel-Medium-Type " ,
@ -1411,12 +1412,30 @@ struct radius_tunnel_attrs {
} ;
static int cmp_int ( const void * a , const void * b )
{
int x , y ;
x = * ( ( int * ) a ) ;
y = * ( ( int * ) b ) ;
return ( x - y ) ;
}
/**
* radius_msg_get_vlanid - Parse RADIUS attributes for VLAN tunnel information
* The k tagged vlans found are sorted by vlan_id and stored in the first k
* items of tagged .
*
* @ msg : RADIUS message
* Returns : VLAN ID for the first tunnel configuration or 0 if none is found
* @ untagged : Pointer to store untagged vid
* @ numtagged : Size of tagged
* @ tagged : Pointer to store tagged list
*
* Returns : 0 if neither tagged nor untagged configuration is found , 1 otherwise
*/
int radius_msg_get_vlanid ( struct radius_msg * msg )
int radius_msg_get_vlanid ( struct radius_msg * msg , int * untagged , int numtagged ,
int * tagged )
{
struct radius_tunnel_attrs tunnel [ RADIUS_TUNNEL_TAGS ] , * tun ;
size_t i ;
@ -1424,8 +1443,12 @@ int radius_msg_get_vlanid(struct radius_msg *msg)
const u8 * data ;
char buf [ 10 ] ;
size_t dlen ;
int j , taggedidx = 0 , vlan_id ;
os_memset ( & tunnel , 0 , sizeof ( tunnel ) ) ;
for ( j = 0 ; j < numtagged ; j + + )
tagged [ j ] = 0 ;
* untagged = 0 ;
for ( i = 0 ; i < msg - > attr_used ; i + + ) {
attr = radius_get_attr_hdr ( msg , i ) ;
@ -1462,21 +1485,44 @@ int radius_msg_get_vlanid(struct radius_msg *msg)
break ;
os_memcpy ( buf , data , dlen ) ;
buf [ dlen ] = ' \0 ' ;
vlan_id = atoi ( buf ) ;
if ( vlan_id < = 0 )
break ;
tun - > tag_used + + ;
tun - > vlanid = atoi ( buf ) ;
tun - > vlanid = vlan_id ;
break ;
case RADIUS_ATTR_EGRESS_VLANID : /* RFC 4675 */
if ( attr - > length ! = 6 )
break ;
vlan_id = WPA_GET_BE24 ( data + 1 ) ;
if ( vlan_id < = 0 )
break ;
if ( data [ 0 ] = = 0x32 )
* untagged = vlan_id ;
else if ( data [ 0 ] = = 0x31 & & tagged & &
taggedidx < numtagged )
tagged [ taggedidx + + ] = vlan_id ;
break ;
}
}
/* Use tunnel with the lowest tag for untagged VLAN id */
for ( i = 0 ; i < RADIUS_TUNNEL_TAGS ; i + + ) {
tun = & tunnel [ i ] ;
if ( tun - > tag_used & &
tun - > type = = RADIUS_TUNNEL_TYPE_VLAN & &
tun - > medium_type = = RADIUS_TUNNEL_MEDIUM_TYPE_802 & &
tun - > vlanid > 0 )
return tun - > vlanid ;
tun - > vlanid > 0 ) {
* untagged = tun - > vlanid ;
break ;
}
}
if ( taggedidx )
qsort ( tagged , taggedidx , sizeof ( int ) , cmp_int ) ;
if ( * untagged > 0 | | taggedidx )
return 1 ;
return 0 ;
}