A server stack is the collection of software that forms the operational infrastructure on a given machine. In a computing context, a stack is an ordered pile. A server stack is one type of solution stack — an ordered selection of software that makes it possible to complete a particular task. Like in this post about hostapd: mapping MAC address to VLAN ID (static mapping via accept_mac_file) was one problem in server stack that need for a solution. Below are some tips in manage your linux server when you find problem about linux, vlan, mac-address, access-point, hostapd.
I want hostapd to assign each station a given VLAN based on MAC address. BTW, my network is quite small. Using RADIUS would be an overkill.
According to the hostapd manual:
Optionally, the local MAC ACL list (accept_mac_file) can be used to
set static client MAC address to VLAN ID mapping.
Let’s assume I only have 1 station (with MAC DE:AD:BE:EF:CA:FE). I’ve created a VLAN using:
sudo ip link add link wlan0 name vlan.100 type vlan id 100
sudo ip addr add 192.168.100.1/24 brd 192.168.100.255 dev vlan.100
sudo ip link set dev vlan.100 up
On hostapd.conf I’m using:
# Interface to use
interface=wlan0
# Driver
driver=nl80211
# Name of the network
ssid=YaddaYadda
# Use the 2.4GHz band: g = IEEE 802.11g (2.4 GHz)
hw_mode=g
# Use channel 6
channel=6
# Enable 802.11n
ieee80211n=1
# Enable 40MHz channels with 20ns guard interval
ht_capab=[HT40][SHORT-GI-20][DSSS_CCK-40]
# Accept only known MAC addresses
macaddr_acl=1
accept_mac_file=/etc/hostapd/accept
# Use WPA authentication
auth_algs=1
# Send empty SSID in beacons and ignore probe request frames that do not specify full SSID
ignore_broadcast_ssid=1
# Use WPA2
wpa=2
# Use a pre-shared key
wpa_key_mgmt=WPA-PSK
# Enable the wireless multimedia extensions
wmm_enabled=1
# The network hashed passphrase
wpa_psk=786451648446NotReallyTheHashedPassphrase849989654651651651654564
# Use AES, instead of TKIP
rsn_pairwise=CCMP
# Isolate Clients
ap_isolate=1
# HOSTAPD event logger configuration
logger_syslog=-1
logger_syslog_level=2
logger_stdout=-1
logger_stdout_level=2
# Country code
country_code=NO
On file /etc/hostapd/accept I have included the following:
DE:AD:BE:EF:CA:FE vlan.100
hostapd starts without any issues. However, after connecting my station with MAC DE:AD:BE:EF:CA:FE, I’m still getting all the traffic on wlan0 and not on vlan.100…
hostapd does not say much about how the file accept_mac_file should look like to map MAC <-> VLAN ID. I’ve tried comma, with and without spaces, but no luck…
Has anyone been able to get this MAC <-> VLAN mapping to work?
Looking at the hostapd
source code, I find that there is a hostapd_config_read_maclist()
function in config_file.c
that parses the files referenced by the accept_mac_file
and deny_mac_file
configuration values:
static int hostapd_config_read_maclist(const char *fname,
struct mac_acl_entry **acl, int *num)
{
FILE *f;
char buf[128], *pos;
int line = 0;
u8 addr[ETH_ALEN];
int vlan_id;
f = fopen(fname, "r");
if (!f) {
wpa_printf(MSG_ERROR, "MAC list file '%s' not found.", fname);
return -1;
}
while (fgets(buf, sizeof(buf), f)) {
int rem = 0;
line++;
if (buf[0] == '#')
continue;
pos = buf;
while (*pos != ' ') {
if (*pos == 'n') {
*pos = ' ';
break;
}
pos++;
}
if (buf[0] == ' ')
continue;
pos = buf;
if (buf[0] == '-') {
rem = 1;
pos++;
}
if (hwaddr_aton(pos, addr)) {
wpa_printf(MSG_ERROR, "Invalid MAC address '%s' at "
"line %d in '%s'", pos, line, fname);
fclose(f);
return -1;
}
if (rem) {
hostapd_remove_acl_mac(acl, num, addr);
continue;
}
vlan_id = 0;
pos = buf;
while (*pos != ' ' && *pos != ' ' && *pos != 't')
pos++;
while (*pos == ' ' || *pos == 't')
pos++;
if (*pos != ' ')
vlan_id = atoi(pos);
if (hostapd_add_acl_maclist(acl, num, vlan_id, addr) < 0) {
fclose(f);
return -1;
}
}
fclose(f);
if (*acl)
qsort(*acl, *num, sizeof(**acl), hostapd_acl_comp);
return 0;
}
I haven’t (yet) tested this to confirm, but based on the code above, it looks like the rules for *_mac_file
files are as follows:
- Lines beginning with
#
are ignored. - Empty lines are ignored.
- A MAC address is specified by six octets in hexadecimal, each separated by
:
.
- A MAC address can optionally be prefixed with
-
to remove all occurrences of it from the list thus far. - Otherwise, a MAC address can optionally be followed by some combination of space and tab characters followed by an integer specifying the VLAN. If the VLAN is
0
, not specified, or not an integer this is treated as no VLAN.
Based on these rules, I believe the way to map the MAC address DE:AD:BE:EF:CA:FE
to the VLAN with name vlan.100
and ID 100
is with this line:
DE:AD:BE:EF:CA:FE 100
That is, only the VLAN ID matters to hostapd
, not the VLAN name.