From 45b1fc5c7f9c7cba421293c3d93735916cc65d72 Mon Sep 17 00:00:00 2001 From: Michael Tremer Date: Fri, 16 Apr 2021 11:53:30 +0200 Subject: [PATCH] hostapd: Find device by MAC address With wireless device as members in bridges, we cannot predict the name very well. So we will use the MAC address and find the correct device name when we launch hostapd. Signed-off-by: Michael Tremer --- config/cfgroot/network-functions.pl | 46 ++++++++++++++++++++++++++++- html/cgi-bin/wlanap.cgi | 38 ++++++++++++++---------- src/initscripts/packages/hostapd | 23 ++++++++++++++- src/paks/hostapd/install.sh | 11 +++++++ 4 files changed, 100 insertions(+), 18 deletions(-) diff --git a/config/cfgroot/network-functions.pl b/config/cfgroot/network-functions.pl index 9908ee8abd..2f704dfbfe 100644 --- a/config/cfgroot/network-functions.pl +++ b/config/cfgroot/network-functions.pl @@ -332,6 +332,28 @@ sub setup_upstream_proxy() { } } +sub list_wireless_interfaces() { + my %interfaces = (); + + opendir(INTERFACES, "/sys/class/net"); + + my $intf; + while ($intf = readdir(INTERFACES)) { + # Is this a wireless interface? + opendir(PHY80211, "/sys/class/net/$intf/phy80211") or next; + closedir(PHY80211); + + # Read the MAC address + my $address = &get_nic_property($intf, "address"); + + $interfaces{$address} = "$address ($intf)"; + } + + closedir(INTERFACES); + + return %interfaces; +} + my %wireless_status = (); sub _get_wireless_status($) { @@ -416,7 +438,7 @@ sub get_nic_property { my $property = shift; my $result; - open(FILE, "/sys/class/net/$nicname/$property") or die("Could not read property"); + open(FILE, "/sys/class/net/$nicname/$property") or die("Could not read property $property for $nicname"); $result = ; close(FILE); @@ -465,6 +487,28 @@ sub get_mac_by_name($) { return $mac; } +sub get_intf_by_address($) { + my $address = shift; + + opendir(INTERFACES, "/sys/class/net"); + + while (my $intf = readdir(INTERFACES)) { + next if ($intf eq "." or $intf eq ".."); + + my $intf_address = &get_nic_property($intf, "address"); + + # Skip interfaces without addresses + next if ($intf_address eq ""); + + # Return a match + return $intf if ($intf_address eq $address); + } + + closedir(INTERFACES); + + return undef; +} + # ## Function to get a list of all available network zones. # diff --git a/html/cgi-bin/wlanap.cgi b/html/cgi-bin/wlanap.cgi index 01dcaeea28..85fe42d965 100644 --- a/html/cgi-bin/wlanap.cgi +++ b/html/cgi-bin/wlanap.cgi @@ -81,6 +81,9 @@ $wlanapsettings{'IEEE80211W'} = 'off'; &General::readhash("/var/ipfire/wlanap/settings", \%wlanapsettings); &Header::getcgihash(\%wlanapsettings); +# Find the selected interface +my $INTF = &Network::get_intf_by_address($wlanapsettings{'INTERFACE'}); + my @macs = $wlanapsettings{'MACS'}; delete $wlanapsettings{'__CGI__'}; @@ -193,8 +196,11 @@ my $wlan_card_status = 'dummy'; my $wlan_ap_status = ''; my $message = ""; -$selected{'INTERFACE'}{'green0'} = ''; -$selected{'INTERFACE'}{'blue0'} = ''; +my %INTERFACES = &Network::list_wireless_interfaces(); + +foreach my $intf (keys %INTERFACES) { + $selected{'INTERFACE'}{$intf} = ''; +} $selected{'ENC'}{$wlanapsettings{'INTERFACE'}} = "selected='selected'"; if ( ($wlanapsettings{'INTERFACE'} eq '') ){ @@ -206,11 +212,12 @@ $message



@@ -222,18 +229,18 @@ END &Header::closepage(); exit; }else{ - my $cmd_out = `/usr/sbin/iwconfig $wlanapsettings{'INTERFACE'} 2>/dev/null`; + my $cmd_out = `/usr/sbin/iwconfig $INTF 2>/dev/null`; if ( $cmd_out eq '' ){ $message = "$Lang::tr{'wlanap no interface'}"; $wlan_card_status = ''; }else{ - $cmd_out = `/sbin/ifconfig | /bin/grep $wlanapsettings{'INTERFACE'}`; + $cmd_out = `/sbin/ifconfig $INTF`; if ( $cmd_out eq '' ){ $wlan_card_status = 'down'; }else{ $wlan_card_status = 'up'; - $cmd_out = `/usr/sbin/iwconfig $wlanapsettings{'INTERFACE'} | /bin/grep "Mode:Master"`; + $cmd_out = `/usr/sbin/iwconfig $INTF | /bin/grep "Mode:Master"`; if ( $cmd_out ne '' ){ $wlan_ap_status = 'up'; } @@ -270,16 +277,16 @@ $selected{'TXPOWER'}{$wlanapsettings{'TXPOWER'}} = "selected='selected'"; $selected{'HW_MODE'}{$wlanapsettings{'HW_MODE'}} = "selected='selected'"; $selected{'MACMODE'}{$wlanapsettings{'MACMODE'}} = "selected='selected'"; -my $monwlaninterface = $wlanapsettings{'INTERFACE'}; -if ( -d '/sys/class/net/mon.'.$wlanapsettings{'INTERFACE'} ) { - $monwlaninterface = 'mon.'.$wlanapsettings{'INTERFACE'}; +my $monwlaninterface = $INTF; +if ( -d '/sys/class/net/mon.' . $INTF) { + $monwlaninterface = 'mon.' . $INTF; } my @channellist_cmd; my @channellist = (0); if ( $wlanapsettings{'DRIVER'} eq 'NL80211' ){ -my $wiphy = `iw dev $wlanapsettings{'INTERFACE'} info | grep wiphy | cut -d" " -f2`; +my $wiphy = `iw dev $INTF info | grep wiphy | cut -d" " -f2`; chomp $wiphy; @channellist_cmd = `iw phy phy$wiphy info | grep " MHz \\\[" | grep -v "(disabled)" | grep -v "no IBSS" | grep -v "no IR" | grep -v "passive scanning" 2>/dev/null`; @@ -318,7 +325,7 @@ my @countrylist = @temp; my @txpower_cmd = `iwlist $monwlaninterface txpower 2>/dev/null`; if ( $wlanapsettings{'DRIVER'} eq 'NL80211' ){ - # There is a bug with NL80211 only all devices can displayed + # There is a bug with NL80211 only all devices can displaye @txpower_cmd = `iwlist txpower 2>/dev/null | sed -e "s|unknown transmit-power information.||g"`; } # get available power @@ -488,7 +495,7 @@ print < END ; -if ( $wlanapsettings{'INTERFACE'} =~ /green0/ ){ +if ( $INTF =~ /green0/ ){ print < @@ -523,7 +530,7 @@ END ; my @status; if ( $wlanapsettings{'DRIVER'} eq 'NL80211' ){ - @status = `iw dev $wlanapsettings{'INTERFACE'} info && iw dev $wlanapsettings{'INTERFACE'} station dump && echo ""`; + @status = `iw dev $INTF info && iw dev $INTF station dump && echo ""`; } print < @@ -588,7 +595,6 @@ sub WriteConfig_hostapd{ driver=$wlanapsettings{'DRIVER_HOSTAPD'} ######################### basic hostapd configuration ########################## # -interface=$wlanapsettings{'INTERFACE'} country_code=$wlanapsettings{'COUNTRY'} ieee80211d=1 ieee80211h=1 diff --git a/src/initscripts/packages/hostapd b/src/initscripts/packages/hostapd index 7aee84e520..c559b26f0d 100644 --- a/src/initscripts/packages/hostapd +++ b/src/initscripts/packages/hostapd @@ -2,6 +2,20 @@ . /etc/sysconfig/rc . ${rc_functions} +find_interface() { + local address="${1}" + + local path + for path in /sys/class/net/*; do + if [ -s "${path}/address" ] && [ "$(<${path}/address)" = "${address}" ]; then + basename "${path}" + return 0 + fi + done + + return 1; +} + CHANNEL="6" COUNTRY="00" TXPOWER="auto" @@ -12,8 +26,15 @@ eval $(/usr/local/bin/readhash /var/ipfire/wlanap/settings) case "${1}" in start) + interface="$(find_interface "${INTERFACE}")" + if [ -z "${interface}" ]; then + boot_mesg "Could not find interface with address ${INTERFACE} for wireless access point" + echo_failure + exit 1 + fi + boot_mesg "Starting hostapd... " - loadproc /usr/bin/hostapd -B /etc/hostapd.conf + loadproc /usr/bin/hostapd -B /etc/hostapd.conf -i "${interface}" ;; stop) diff --git a/src/paks/hostapd/install.sh b/src/paks/hostapd/install.sh index bd2441e55a..2dae5364ee 100644 --- a/src/paks/hostapd/install.sh +++ b/src/paks/hostapd/install.sh @@ -24,6 +24,17 @@ . /opt/pakfire/lib/functions.sh extract_files restore_backup ${NAME} + +# Convert INTERFACE setting to MAC address +( + eval $(/usr/local/bin/readhash /var/ipfire/wlanap/settings) + + if [ -n "${INTERFACE}" -a -d "/sys/class/net/${INTERFACE}" ]; then + sed -i /var/ipfire/wlanap/settings \ + -e "s/^INTERFACE=.*/INTERFACE=$(