From fd705204f7eb19c787a07a96680ff62859e5fbb6 Mon Sep 17 00:00:00 2001 From: "Chang.H.S" Date: Tue, 10 Apr 2012 19:36:44 +0900 Subject: [PATCH 1/1] LinuxAP : add new plugin --- configure.ac | 2 + lib/python/Plugins/SystemPlugins/Makefile.am | 2 +- .../SystemPlugins/WirelessAccessPoint/Makefile.am | 10 + .../SystemPlugins/WirelessAccessPoint/__init__.py | 0 .../WirelessAccessPoint/_wirelessap.so | Bin 0 -> 131503 bytes .../WirelessAccessPoint/hostapd.conf.orig | 1016 ++++++++++++++++++++ .../WirelessAccessPoint/meta/Makefile.am | 3 + .../meta/plugin_wirelessaccesspoint.xml | 17 + .../SystemPlugins/WirelessAccessPoint/plugin.py | 589 ++++++++++++ .../WirelessAccessPoint/wirelessap.py | 87 ++ 10 files changed, 1725 insertions(+), 1 deletion(-) create mode 100755 lib/python/Plugins/SystemPlugins/WirelessAccessPoint/Makefile.am create mode 100755 lib/python/Plugins/SystemPlugins/WirelessAccessPoint/__init__.py create mode 100755 lib/python/Plugins/SystemPlugins/WirelessAccessPoint/_wirelessap.so create mode 100644 lib/python/Plugins/SystemPlugins/WirelessAccessPoint/hostapd.conf.orig create mode 100755 lib/python/Plugins/SystemPlugins/WirelessAccessPoint/meta/Makefile.am create mode 100755 lib/python/Plugins/SystemPlugins/WirelessAccessPoint/meta/plugin_wirelessaccesspoint.xml create mode 100755 lib/python/Plugins/SystemPlugins/WirelessAccessPoint/plugin.py create mode 100644 lib/python/Plugins/SystemPlugins/WirelessAccessPoint/wirelessap.py diff --git a/configure.ac b/configure.ac index f11245a..4fd69df 100644 --- a/configure.ac +++ b/configure.ac @@ -254,6 +254,8 @@ lib/python/Plugins/SystemPlugins/CrashReport/meta/Makefile lib/python/Plugins/SystemPlugins/3GModemManager/Makefile lib/python/Plugins/SystemPlugins/3GModemManager/meta/Makefile lib/python/Plugins/SystemPlugins/3GModemManager/script/Makefile +lib/python/Plugins/SystemPlugins/WirelessAccessPoint/Makefile +lib/python/Plugins/SystemPlugins/WirelessAccessPoint/meta/Makefile lib/python/Tools/Makefile lib/service/Makefile lib/components/Makefile diff --git a/lib/python/Plugins/SystemPlugins/Makefile.am b/lib/python/Plugins/SystemPlugins/Makefile.am index 059673c..7e31a15 100755 --- a/lib/python/Plugins/SystemPlugins/Makefile.am +++ b/lib/python/Plugins/SystemPlugins/Makefile.am @@ -6,7 +6,7 @@ SUBDIRS = SoftwareManager FrontprocessorUpgrade PositionerSetup Satfinder \ CrashlogAutoSubmit CleanupWizard VideoEnhancement WirelessLan NetworkWizard \ TempFanControl FactoryTest Fancontrol FPGAUpgrade WirelessLanSetup ManualFancontrol \ Blindscan RemoteControlCode UI3DSetup UIPositionSetup HDMICEC LEDBrightnessSetup \ - FirmwareUpgrade CrashReport 3GModemManager + FirmwareUpgrade CrashReport 3GModemManager WirelessAccessPoint install_PYTHON = \ __init__.py diff --git a/lib/python/Plugins/SystemPlugins/WirelessAccessPoint/Makefile.am b/lib/python/Plugins/SystemPlugins/WirelessAccessPoint/Makefile.am new file mode 100755 index 0000000..4790bfd --- /dev/null +++ b/lib/python/Plugins/SystemPlugins/WirelessAccessPoint/Makefile.am @@ -0,0 +1,10 @@ +installdir = $(pkglibdir)/python/Plugins/SystemPlugins/WirelessAccessPoint + +SUBDIRS = meta + +install_PYTHON = \ + __init__.py \ + plugin.py \ + hostapd.conf.orig \ + _wirelessap.so \ + wirelessap.py diff --git a/lib/python/Plugins/SystemPlugins/WirelessAccessPoint/__init__.py b/lib/python/Plugins/SystemPlugins/WirelessAccessPoint/__init__.py new file mode 100755 index 0000000..e69de29 diff --git a/lib/python/Plugins/SystemPlugins/WirelessAccessPoint/_wirelessap.so b/lib/python/Plugins/SystemPlugins/WirelessAccessPoint/_wirelessap.so new file mode 100755 index 0000000000000000000000000000000000000000..8e0c085097ae5a0ac5cdf8b196fd6a421a328f55 GIT binary patch literal 131503 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 literal 0 HcmV?d00001 diff --git a/lib/python/Plugins/SystemPlugins/WirelessAccessPoint/hostapd.conf.orig b/lib/python/Plugins/SystemPlugins/WirelessAccessPoint/hostapd.conf.orig new file mode 100644 index 0000000..807f263 --- /dev/null +++ b/lib/python/Plugins/SystemPlugins/WirelessAccessPoint/hostapd.conf.orig @@ -0,0 +1,1016 @@ +##### hostapd configuration file ############################################## +# Empty lines and lines starting with # are ignored + +# AP netdevice name (without 'ap' postfix, i.e., wlan0 uses wlan0ap for +# management frames); ath0 for madwifi +interface=wlan0 + +# In case of madwifi, atheros, and nl80211 driver interfaces, an additional +# configuration parameter, bridge, may be used to notify hostapd if the +# interface is included in a bridge. This parameter is not used with Host AP +# driver. If the bridge parameter is not set, the drivers will automatically +# figure out the bridge interface (assuming sysfs is enabled and mounted to +# /sys) and this parameter may not be needed. +# +# For nl80211, this parameter can be used to request the AP interface to be +# added to the bridge automatically (brctl may refuse to do this before hostapd +# has been started to change the interface mode). If needed, the bridge +# interface is also created. +bridge=br0 + +# Driver interface type (hostap/wired/madwifi/test/none/nl80211/bsd); +# default: hostap). nl80211 is used with all Linux mac80211 drivers. +# Use driver=none if building hostapd as a standalone RADIUS server that does +# not control any wireless/wired driver. +driver=nl80211 + +# hostapd event logger configuration +# +# Two output method: syslog and stdout (only usable if not forking to +# background). +# +# Module bitfield (ORed bitfield of modules that will be logged; -1 = all +# modules): +# bit 0 (1) = IEEE 802.11 +# bit 1 (2) = IEEE 802.1X +# bit 2 (4) = RADIUS +# bit 3 (8) = WPA +# bit 4 (16) = driver interface +# bit 5 (32) = IAPP +# bit 6 (64) = MLME +# +# Levels (minimum value for logged events): +# 0 = verbose debugging +# 1 = debugging +# 2 = informational messages +# 3 = notification +# 4 = warning +# +logger_syslog=-1 +logger_syslog_level=2 +logger_stdout=-1 +logger_stdout_level=2 + +# Dump file for state information (on SIGUSR1) +dump_file=/tmp/hostapd.dump + +# Interface for separate control program. If this is specified, hostapd +# will create this directory and a UNIX domain socket for listening to requests +# from external programs (CLI/GUI, etc.) for status information and +# configuration. The socket file will be named based on the interface name, so +# multiple hostapd processes/interfaces can be run at the same time if more +# than one interface is used. +# /var/run/hostapd is the recommended directory for sockets and by default, +# hostapd_cli will use it when trying to connect with hostapd. +ctrl_interface=/var/run/hostapd + +# Access control for the control interface can be configured by setting the +# directory to allow only members of a group to use sockets. This way, it is +# possible to run hostapd as root (since it needs to change network +# configuration and open raw sockets) and still allow GUI/CLI components to be +# run as non-root users. However, since the control interface can be used to +# change the network configuration, this access needs to be protected in many +# cases. By default, hostapd is configured to use gid 0 (root). If you +# want to allow non-root users to use the contron interface, add a new group +# and change this value to match with that group. Add users that should have +# control interface access to this group. +# +# This variable can be a group name or gid. +#ctrl_interface_group=wheel +ctrl_interface_group=0 + + +##### IEEE 802.11 related configuration ####################################### + +# SSID to be used in IEEE 802.11 management frames +ssid=vuplus_ap + +# Country code (ISO/IEC 3166-1). Used to set regulatory domain. +# Set as needed to indicate country in which device is operating. +# This can limit available channels and transmit power. +#country_code=US + +# Enable IEEE 802.11d. This advertises the country_code and the set of allowed +# channels and transmit power levels based on the regulatory limits. The +# country_code setting must be configured with the correct country for +# IEEE 802.11d functions. +# (default: 0 = disabled) +#ieee80211d=1 + +# Operation mode (a = IEEE 802.11a, b = IEEE 802.11b, g = IEEE 802.11g, +# Default: IEEE 802.11b +hw_mode=g + +# Channel number (IEEE 802.11) +# (default: 0, i.e., not set) +# Please note that some drivers (e.g., madwifi) do not use this value from +# hostapd and the channel will need to be configuration separately with +# iwconfig. +channel=1 + +# Beacon interval in kus (1.024 ms) (default: 100; range 15..65535) +beacon_int=100 + +# DTIM (delivery trafic information message) period (range 1..255): +# number of beacons between DTIMs (1 = every beacon includes DTIM element) +# (default: 2) +dtim_period=2 + +# Maximum number of stations allowed in station table. New stations will be +# rejected after the station table is full. IEEE 802.11 has a limit of 2007 +# different association IDs, so this number should not be larger than that. +# (default: 2007) +max_num_sta=255 + +# RTS/CTS threshold; 2347 = disabled (default); range 0..2347 +# If this field is not included in hostapd.conf, hostapd will not control +# RTS threshold and 'iwconfig wlan# rts ' can be used to set it. +rts_threshold=2347 + +# Fragmentation threshold; 2346 = disabled (default); range 256..2346 +# If this field is not included in hostapd.conf, hostapd will not control +# fragmentation threshold and 'iwconfig wlan# frag ' can be used to set +# it. +fragm_threshold=2346 + +# Rate configuration +# Default is to enable all rates supported by the hardware. This configuration +# item allows this list be filtered so that only the listed rates will be left +# in the list. If the list is empty, all rates are used. This list can have +# entries that are not in the list of rates the hardware supports (such entries +# are ignored). The entries in this list are in 100 kbps, i.e., 11 Mbps = 110. +# If this item is present, at least one rate have to be matching with the rates +# hardware supports. +# default: use the most common supported rate setting for the selected +# hw_mode (i.e., this line can be removed from configuration file in most +# cases) +#supported_rates=10 20 55 110 60 90 120 180 240 360 480 540 + +# Basic rate set configuration +# List of rates (in 100 kbps) that are included in the basic rate set. +# If this item is not included, usually reasonable default set is used. +#basic_rates=10 20 +#basic_rates=10 20 55 110 +#basic_rates=60 120 240 + +# Short Preamble +# This parameter can be used to enable optional use of short preamble for +# frames sent at 2 Mbps, 5.5 Mbps, and 11 Mbps to improve network performance. +# This applies only to IEEE 802.11b-compatible networks and this should only be +# enabled if the local hardware supports use of short preamble. If any of the +# associated STAs do not support short preamble, use of short preamble will be +# disabled (and enabled when such STAs disassociate) dynamically. +# 0 = do not allow use of short preamble (default) +# 1 = allow use of short preamble +#preamble=1 + +# Station MAC address -based authentication +# Please note that this kind of access control requires a driver that uses +# hostapd to take care of management frame processing and as such, this can be +# used with driver=hostap or driver=nl80211, but not with driver=madwifi. +# 0 = accept unless in deny list +# 1 = deny unless in accept list +# 2 = use external RADIUS server (accept/deny lists are searched first) +macaddr_acl=0 + +# Accept/deny lists are read from separate files (containing list of +# MAC addresses, one per line). Use absolute path name to make sure that the +# files can be read on SIGHUP configuration reloads. +#accept_mac_file=/etc/hostapd.accept +#deny_mac_file=/etc/hostapd.deny + +# IEEE 802.11 specifies two authentication algorithms. hostapd can be +# configured to allow both of these or only one. Open system authentication +# should be used with IEEE 802.1X. +# Bit fields of allowed authentication algorithms: +# bit 0 = Open System Authentication +# bit 1 = Shared Key Authentication (requires WEP) +auth_algs=3 + +# Send empty SSID in beacons and ignore probe request frames that do not +# specify full SSID, i.e., require stations to know SSID. +# default: disabled (0) +# 1 = send empty (length=0) SSID in beacon and ignore probe request for +# broadcast SSID +# 2 = clear SSID (ASCII 0), but keep the original length (this may be required +# with some clients that do not support empty SSID) and ignore probe +# requests for broadcast SSID +ignore_broadcast_ssid=0 + +# TX queue parameters (EDCF / bursting) +# default for all these fields: not set, use hardware defaults +# tx_queue__ +# queues: data0, data1, data2, data3, after_beacon, beacon +# (data0 is the highest priority queue) +# parameters: +# aifs: AIFS (default 2) +# cwmin: cwMin (1, 3, 7, 15, 31, 63, 127, 255, 511, 1023) +# cwmax: cwMax (1, 3, 7, 15, 31, 63, 127, 255, 511, 1023); cwMax >= cwMin +# burst: maximum length (in milliseconds with precision of up to 0.1 ms) for +# bursting +# +# Default WMM parameters (IEEE 802.11 draft; 11-03-0504-03-000e): +# These parameters are used by the access point when transmitting frames +# to the clients. +# +# Low priority / AC_BK = background +#tx_queue_data3_aifs=7 +#tx_queue_data3_cwmin=15 +#tx_queue_data3_cwmax=1023 +#tx_queue_data3_burst=0 +# Note: for IEEE 802.11b mode: cWmin=31 cWmax=1023 burst=0 +# +# Normal priority / AC_BE = best effort +#tx_queue_data2_aifs=3 +#tx_queue_data2_cwmin=15 +#tx_queue_data2_cwmax=63 +#tx_queue_data2_burst=0 +# Note: for IEEE 802.11b mode: cWmin=31 cWmax=127 burst=0 +# +# High priority / AC_VI = video +#tx_queue_data1_aifs=1 +#tx_queue_data1_cwmin=7 +#tx_queue_data1_cwmax=15 +#tx_queue_data1_burst=3.0 +# Note: for IEEE 802.11b mode: cWmin=15 cWmax=31 burst=6.0 +# +# Highest priority / AC_VO = voice +#tx_queue_data0_aifs=1 +#tx_queue_data0_cwmin=3 +#tx_queue_data0_cwmax=7 +#tx_queue_data0_burst=1.5 +# Note: for IEEE 802.11b mode: cWmin=7 cWmax=15 burst=3.3 +# +# Special queues; normally not user configurable +# +#tx_queue_after_beacon_aifs=2 +#tx_queue_after_beacon_cwmin=15 +#tx_queue_after_beacon_cwmax=1023 +#tx_queue_after_beacon_burst=0 +# +#tx_queue_beacon_aifs=2 +#tx_queue_beacon_cwmin=3 +#tx_queue_beacon_cwmax=7 +#tx_queue_beacon_burst=1.5 + +# 802.1D Tag (= UP) to AC mappings +# WMM specifies following mapping of data frames to different ACs. This mapping +# can be configured using Linux QoS/tc and sch_pktpri.o module. +# 802.1D Tag 802.1D Designation Access Category WMM Designation +# 1 BK AC_BK Background +# 2 - AC_BK Background +# 0 BE AC_BE Best Effort +# 3 EE AC_BE Best Effort +# 4 CL AC_VI Video +# 5 VI AC_VI Video +# 6 VO AC_VO Voice +# 7 NC AC_VO Voice +# Data frames with no priority information: AC_BE +# Management frames: AC_VO +# PS-Poll frames: AC_BE + +# Default WMM parameters (IEEE 802.11 draft; 11-03-0504-03-000e): +# for 802.11a or 802.11g networks +# These parameters are sent to WMM clients when they associate. +# The parameters will be used by WMM clients for frames transmitted to the +# access point. +# +# note - txop_limit is in units of 32microseconds +# note - acm is admission control mandatory flag. 0 = admission control not +# required, 1 = mandatory +# note - here cwMin and cmMax are in exponent form. the actual cw value used +# will be (2^n)-1 where n is the value given here +# +wmm_enabled=1 +# +# WMM-PS Unscheduled Automatic Power Save Delivery [U-APSD] +# Enable this flag if U-APSD supported outside hostapd (eg., Firmware/driver) +#uapsd_advertisement_enabled=1 +# +# Low priority / AC_BK = background +wmm_ac_bk_cwmin=4 +wmm_ac_bk_cwmax=10 +wmm_ac_bk_aifs=7 +wmm_ac_bk_txop_limit=0 +wmm_ac_bk_acm=0 +# Note: for IEEE 802.11b mode: cWmin=5 cWmax=10 +# +# Normal priority / AC_BE = best effort +wmm_ac_be_aifs=3 +wmm_ac_be_cwmin=4 +wmm_ac_be_cwmax=10 +wmm_ac_be_txop_limit=0 +wmm_ac_be_acm=0 +# Note: for IEEE 802.11b mode: cWmin=5 cWmax=7 +# +# High priority / AC_VI = video +wmm_ac_vi_aifs=2 +wmm_ac_vi_cwmin=3 +wmm_ac_vi_cwmax=4 +wmm_ac_vi_txop_limit=94 +wmm_ac_vi_acm=0 +# Note: for IEEE 802.11b mode: cWmin=4 cWmax=5 txop_limit=188 +# +# Highest priority / AC_VO = voice +wmm_ac_vo_aifs=2 +wmm_ac_vo_cwmin=2 +wmm_ac_vo_cwmax=3 +wmm_ac_vo_txop_limit=47 +wmm_ac_vo_acm=0 +# Note: for IEEE 802.11b mode: cWmin=3 cWmax=4 burst=102 + +# Static WEP key configuration +# +# The key number to use when transmitting. +# It must be between 0 and 3, and the corresponding key must be set. +# default: not set +#wep_default_key=0 +# The WEP keys to use. +# A key may be a quoted string or unquoted hexadecimal digits. +# The key length should be 5, 13, or 16 characters, or 10, 26, or 32 +# digits, depending on whether 40-bit (64-bit), 104-bit (128-bit), or +# 128-bit (152-bit) WEP is used. +# Only the default key must be supplied; the others are optional. +# default: not set +#wep_key0=123456789a +#wep_key1="vwxyz" +#wep_key2=0102030405060708090a0b0c0d +#wep_key3=".2.4.6.8.0.23" + +# Station inactivity limit +# +# If a station does not send anything in ap_max_inactivity seconds, an +# empty data frame is sent to it in order to verify whether it is +# still in range. If this frame is not ACKed, the station will be +# disassociated and then deauthenticated. This feature is used to +# clear station table of old entries when the STAs move out of the +# range. +# +# The station can associate again with the AP if it is still in range; +# this inactivity poll is just used as a nicer way of verifying +# inactivity; i.e., client will not report broken connection because +# disassociation frame is not sent immediately without first polling +# the STA with a data frame. +# default: 300 (i.e., 5 minutes) +#ap_max_inactivity=300 + +# Maximum allowed Listen Interval (how many Beacon periods STAs are allowed to +# remain asleep). Default: 65535 (no limit apart from field size) +#max_listen_interval=100 + +# WDS (4-address frame) mode with per-station virtual interfaces +# (only supported with driver=nl80211) +# This mode allows associated stations to use 4-address frames to allow layer 2 +# bridging to be used. +#wds_sta=1 + +##### IEEE 802.11n related configuration ###################################### + +# ieee80211n: Whether IEEE 802.11n (HT) is enabled +# 0 = disabled (default) +# 1 = enabled +# Note: You will also need to enable WMM for full HT functionality. +#ieee80211n=1 + +# ht_capab: HT capabilities (list of flags) +# LDPC coding capability: [LDPC] = supported +# Supported channel width set: [HT40-] = both 20 MHz and 40 MHz with secondary +# channel below the primary channel; [HT40+] = both 20 MHz and 40 MHz +# with secondary channel below the primary channel +# (20 MHz only if neither is set) +# Note: There are limits on which channels can be used with HT40- and +# HT40+. Following table shows the channels that may be available for +# HT40- and HT40+ use per IEEE 802.11n Annex J: +# freq HT40- HT40+ +# 2.4 GHz 5-13 1-7 (1-9 in Europe/Japan) +# 5 GHz 40,48,56,64 36,44,52,60 +# (depending on the location, not all of these channels may be available +# for use) +# Please note that 40 MHz channels may switch their primary and secondary +# channels if needed or creation of 40 MHz channel maybe rejected based +# on overlapping BSSes. These changes are done automatically when hostapd +# is setting up the 40 MHz channel. +# Spatial Multiplexing (SM) Power Save: [SMPS-STATIC] or [SMPS-DYNAMIC] +# (SMPS disabled if neither is set) +# HT-greenfield: [GF] (disabled if not set) +# Short GI for 20 MHz: [SHORT-GI-20] (disabled if not set) +# Short GI for 40 MHz: [SHORT-GI-40] (disabled if not set) +# Tx STBC: [TX-STBC] (disabled if not set) +# Rx STBC: [RX-STBC1] (one spatial stream), [RX-STBC12] (one or two spatial +# streams), or [RX-STBC123] (one, two, or three spatial streams); Rx STBC +# disabled if none of these set +# HT-delayed Block Ack: [DELAYED-BA] (disabled if not set) +# Maximum A-MSDU length: [MAX-AMSDU-7935] for 7935 octets (3839 octets if not +# set) +# DSSS/CCK Mode in 40 MHz: [DSSS_CCK-40] = allowed (not allowed if not set) +# PSMP support: [PSMP] (disabled if not set) +# L-SIG TXOP protection support: [LSIG-TXOP-PROT] (disabled if not set) +#ht_capab=[HT40-][SHORT-GI-20][SHORT-GI-40] + +##### IEEE 802.1X-2004 related configuration ################################## + +# Require IEEE 802.1X authorization +#ieee8021x=1 + +# IEEE 802.1X/EAPOL version +# hostapd is implemented based on IEEE Std 802.1X-2004 which defines EAPOL +# version 2. However, there are many client implementations that do not handle +# the new version number correctly (they seem to drop the frames completely). +# In order to make hostapd interoperate with these clients, the version number +# can be set to the older version (1) with this configuration value. +#eapol_version=2 + +# Optional displayable message sent with EAP Request-Identity. The first \0 +# in this string will be converted to ASCII-0 (nul). This can be used to +# separate network info (comma separated list of attribute=value pairs); see, +# e.g., RFC 4284. +#eap_message=hello +#eap_message=hello\0networkid=netw,nasid=foo,portid=0,NAIRealms=example.com + +# WEP rekeying (disabled if key lengths are not set or are set to 0) +# Key lengths for default/broadcast and individual/unicast keys: +# 5 = 40-bit WEP (also known as 64-bit WEP with 40 secret bits) +# 13 = 104-bit WEP (also known as 128-bit WEP with 104 secret bits) +#wep_key_len_broadcast=5 +#wep_key_len_unicast=5 +# Rekeying period in seconds. 0 = do not rekey (i.e., set keys only once) +#wep_rekey_period=300 + +# EAPOL-Key index workaround (set bit7) for WinXP Supplicant (needed only if +# only broadcast keys are used) +eapol_key_index_workaround=0 + +# EAP reauthentication period in seconds (default: 3600 seconds; 0 = disable +# reauthentication). +#eap_reauth_period=3600 + +# Use PAE group address (01:80:c2:00:00:03) instead of individual target +# address when sending EAPOL frames with driver=wired. This is the most common +# mechanism used in wired authentication, but it also requires that the port +# is only used by one station. +#use_pae_group_addr=1 + +##### Integrated EAP server ################################################### + +# Optionally, hostapd can be configured to use an integrated EAP server +# to process EAP authentication locally without need for an external RADIUS +# server. This functionality can be used both as a local authentication server +# for IEEE 802.1X/EAPOL and as a RADIUS server for other devices. + +# Use integrated EAP server instead of external RADIUS authentication +# server. This is also needed if hostapd is configured to act as a RADIUS +# authentication server. +eap_server=0 + +# Path for EAP server user database +#eap_user_file=/etc/hostapd.eap_user + +# CA certificate (PEM or DER file) for EAP-TLS/PEAP/TTLS +#ca_cert=/etc/hostapd.ca.pem + +# Server certificate (PEM or DER file) for EAP-TLS/PEAP/TTLS +#server_cert=/etc/hostapd.server.pem + +# Private key matching with the server certificate for EAP-TLS/PEAP/TTLS +# This may point to the same file as server_cert if both certificate and key +# are included in a single file. PKCS#12 (PFX) file (.p12/.pfx) can also be +# used by commenting out server_cert and specifying the PFX file as the +# private_key. +#private_key=/etc/hostapd.server.prv + +# Passphrase for private key +#private_key_passwd=secret passphrase + +# Enable CRL verification. +# Note: hostapd does not yet support CRL downloading based on CDP. Thus, a +# valid CRL signed by the CA is required to be included in the ca_cert file. +# This can be done by using PEM format for CA certificate and CRL and +# concatenating these into one file. Whenever CRL changes, hostapd needs to be +# restarted to take the new CRL into use. +# 0 = do not verify CRLs (default) +# 1 = check the CRL of the user certificate +# 2 = check all CRLs in the certificate path +#check_crl=1 + +# dh_file: File path to DH/DSA parameters file (in PEM format) +# This is an optional configuration file for setting parameters for an +# ephemeral DH key exchange. In most cases, the default RSA authentication does +# not use this configuration. However, it is possible setup RSA to use +# ephemeral DH key exchange. In addition, ciphers with DSA keys always use +# ephemeral DH keys. This can be used to achieve forward secrecy. If the file +# is in DSA parameters format, it will be automatically converted into DH +# params. This parameter is required if anonymous EAP-FAST is used. +# You can generate DH parameters file with OpenSSL, e.g., +# "openssl dhparam -out /etc/hostapd.dh.pem 1024" +#dh_file=/etc/hostapd.dh.pem + +# Configuration data for EAP-SIM database/authentication gateway interface. +# This is a text string in implementation specific format. The example +# implementation in eap_sim_db.c uses this as the UNIX domain socket name for +# the HLR/AuC gateway (e.g., hlr_auc_gw). In this case, the path uses "unix:" +# prefix. +#eap_sim_db=unix:/tmp/hlr_auc_gw.sock + +# Encryption key for EAP-FAST PAC-Opaque values. This key must be a secret, +# random value. It is configured as a 16-octet value in hex format. It can be +# generated, e.g., with the following command: +# od -tx1 -v -N16 /dev/random | colrm 1 8 | tr -d ' ' +#pac_opaque_encr_key=000102030405060708090a0b0c0d0e0f + +# EAP-FAST authority identity (A-ID) +# A-ID indicates the identity of the authority that issues PACs. The A-ID +# should be unique across all issuing servers. In theory, this is a variable +# length field, but due to some existing implementations requiring A-ID to be +# 16 octets in length, it is strongly recommended to use that length for the +# field to provid interoperability with deployed peer implementations. This +# field is configured in hex format. +#eap_fast_a_id=101112131415161718191a1b1c1d1e1f + +# EAP-FAST authority identifier information (A-ID-Info) +# This is a user-friendly name for the A-ID. For example, the enterprise name +# and server name in a human-readable format. This field is encoded as UTF-8. +#eap_fast_a_id_info=test server + +# Enable/disable different EAP-FAST provisioning modes: +#0 = provisioning disabled +#1 = only anonymous provisioning allowed +#2 = only authenticated provisioning allowed +#3 = both provisioning modes allowed (default) +#eap_fast_prov=3 + +# EAP-FAST PAC-Key lifetime in seconds (hard limit) +#pac_key_lifetime=604800 + +# EAP-FAST PAC-Key refresh time in seconds (soft limit on remaining hard +# limit). The server will generate a new PAC-Key when this number of seconds +# (or fewer) of the lifetime remains. +#pac_key_refresh_time=86400 + +# EAP-SIM and EAP-AKA protected success/failure indication using AT_RESULT_IND +# (default: 0 = disabled). +#eap_sim_aka_result_ind=1 + +# Trusted Network Connect (TNC) +# If enabled, TNC validation will be required before the peer is allowed to +# connect. Note: This is only used with EAP-TTLS and EAP-FAST. If any other +# EAP method is enabled, the peer will be allowed to connect without TNC. +#tnc=1 + + +##### IEEE 802.11f - Inter-Access Point Protocol (IAPP) ####################### + +# Interface to be used for IAPP broadcast packets +#iapp_interface=eth0 + + +##### RADIUS client configuration ############################################# +# for IEEE 802.1X with external Authentication Server, IEEE 802.11 +# authentication with external ACL for MAC addresses, and accounting + +# The own IP address of the access point (used as NAS-IP-Address) +own_ip_addr=127.0.0.1 + +# Optional NAS-Identifier string for RADIUS messages. When used, this should be +# a unique to the NAS within the scope of the RADIUS server. For example, a +# fully qualified domain name can be used here. +# When using IEEE 802.11r, nas_identifier must be set and must be between 1 and +# 48 octets long. +#nas_identifier=ap.example.com + +# RADIUS authentication server +#auth_server_addr=127.0.0.1 +#auth_server_port=1812 +#auth_server_shared_secret=secret + +# RADIUS accounting server +#acct_server_addr=127.0.0.1 +#acct_server_port=1813 +#acct_server_shared_secret=secret + +# Secondary RADIUS servers; to be used if primary one does not reply to +# RADIUS packets. These are optional and there can be more than one secondary +# server listed. +#auth_server_addr=127.0.0.2 +#auth_server_port=1812 +#auth_server_shared_secret=secret2 +# +#acct_server_addr=127.0.0.2 +#acct_server_port=1813 +#acct_server_shared_secret=secret2 + +# Retry interval for trying to return to the primary RADIUS server (in +# seconds). RADIUS client code will automatically try to use the next server +# when the current server is not replying to requests. If this interval is set, +# primary server will be retried after configured amount of time even if the +# currently used secondary server is still working. +#radius_retry_primary_interval=600 + + +# Interim accounting update interval +# If this is set (larger than 0) and acct_server is configured, hostapd will +# send interim accounting updates every N seconds. Note: if set, this overrides +# possible Acct-Interim-Interval attribute in Access-Accept message. Thus, this +# value should not be configured in hostapd.conf, if RADIUS server is used to +# control the interim interval. +# This value should not be less 600 (10 minutes) and must not be less than +# 60 (1 minute). +#radius_acct_interim_interval=600 + +# Dynamic VLAN mode; allow RADIUS authentication server to decide which VLAN +# is used for the stations. This information is parsed from following RADIUS +# attributes based on RFC 3580 and RFC 2868: Tunnel-Type (value 13 = VLAN), +# Tunnel-Medium-Type (value 6 = IEEE 802), Tunnel-Private-Group-ID (value +# VLANID as a string). vlan_file option below must be configured if dynamic +# VLANs are used. Optionally, the local MAC ACL list (accept_mac_file) can be +# used to set static client MAC address to VLAN ID mapping. +# 0 = disabled (default) +# 1 = option; use default interface if RADIUS server does not include VLAN ID +# 2 = required; reject authentication if RADIUS server does not include VLAN ID +#dynamic_vlan=0 + +# VLAN interface list for dynamic VLAN mode is read from a separate text file. +# This list is used to map VLAN ID from the RADIUS server to a network +# interface. Each station is bound to one interface in the same way as with +# multiple BSSIDs or SSIDs. Each line in this text file is defining a new +# interface and the line must include VLAN ID and interface name separated by +# white space (space or tab). +#vlan_file=/etc/hostapd.vlan + +# Interface where 802.1q tagged packets should appear when a RADIUS server is +# used to determine which VLAN a station is on. hostapd creates a bridge for +# each VLAN. Then hostapd adds a VLAN interface (associated with the interface +# indicated by 'vlan_tagged_interface') and the appropriate wireless interface +# to the bridge. +#vlan_tagged_interface=eth0 + + +##### RADIUS authentication server configuration ############################## + +# hostapd can be used as a RADIUS authentication server for other hosts. This +# requires that the integrated EAP server is also enabled and both +# authentication services are sharing the same configuration. + +# File name of the RADIUS clients configuration for the RADIUS server. If this +# commented out, RADIUS server is disabled. +#radius_server_clients=/etc/hostapd.radius_clients + +# The UDP port number for the RADIUS authentication server +#radius_server_auth_port=1812 + +# Use IPv6 with RADIUS server (IPv4 will also be supported using IPv6 API) +#radius_server_ipv6=1 + + +##### WPA/IEEE 802.11i configuration ########################################## + +# Enable WPA. Setting this variable configures the AP to require WPA (either +# WPA-PSK or WPA-RADIUS/EAP based on other configuration). For WPA-PSK, either +# wpa_psk or wpa_passphrase must be set and wpa_key_mgmt must include WPA-PSK. +# For WPA-RADIUS/EAP, ieee8021x must be set (but without dynamic WEP keys), +# RADIUS authentication server must be configured, and WPA-EAP must be included +# in wpa_key_mgmt. +# This field is a bit field that can be used to enable WPA (IEEE 802.11i/D3.0) +# and/or WPA2 (full IEEE 802.11i/RSN): +# bit0 = WPA +# bit1 = IEEE 802.11i/RSN (WPA2) (dot11RSNAEnabled) +#wpa=1 + +# WPA pre-shared keys for WPA-PSK. This can be either entered as a 256-bit +# secret in hex format (64 hex digits), wpa_psk, or as an ASCII passphrase +# (8..63 characters) that will be converted to PSK. This conversion uses SSID +# so the PSK changes when ASCII passphrase is used and the SSID is changed. +# wpa_psk (dot11RSNAConfigPSKValue) +# wpa_passphrase (dot11RSNAConfigPSKPassPhrase) +#wpa_psk=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef +#wpa_passphrase=secret passphrase + +# Optionally, WPA PSKs can be read from a separate text file (containing list +# of (PSK,MAC address) pairs. This allows more than one PSK to be configured. +# Use absolute path name to make sure that the files can be read on SIGHUP +# configuration reloads. +#wpa_psk_file=/etc/hostapd.wpa_psk + +# Set of accepted key management algorithms (WPA-PSK, WPA-EAP, or both). The +# entries are separated with a space. WPA-PSK-SHA256 and WPA-EAP-SHA256 can be +# added to enable SHA256-based stronger algorithms. +# (dot11RSNAConfigAuthenticationSuitesTable) +#wpa_key_mgmt=WPA-PSK WPA-EAP + +# Set of accepted cipher suites (encryption algorithms) for pairwise keys +# (unicast packets). This is a space separated list of algorithms: +# CCMP = AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0] +# TKIP = Temporal Key Integrity Protocol [IEEE 802.11i/D7.0] +# Group cipher suite (encryption algorithm for broadcast and multicast frames) +# is automatically selected based on this configuration. If only CCMP is +# allowed as the pairwise cipher, group cipher will also be CCMP. Otherwise, +# TKIP will be used as the group cipher. +# (dot11RSNAConfigPairwiseCiphersTable) +# Pairwise cipher for WPA (v1) (default: TKIP) +#wpa_pairwise=TKIP CCMP +# Pairwise cipher for RSN/WPA2 (default: use wpa_pairwise value) +#rsn_pairwise=CCMP + +# Time interval for rekeying GTK (broadcast/multicast encryption keys) in +# seconds. (dot11RSNAConfigGroupRekeyTime) +#wpa_group_rekey=600 + +# Rekey GTK when any STA that possesses the current GTK is leaving the BSS. +# (dot11RSNAConfigGroupRekeyStrict) +#wpa_strict_rekey=1 + +# Time interval for rekeying GMK (master key used internally to generate GTKs +# (in seconds). +#wpa_gmk_rekey=86400 + +# Maximum lifetime for PTK in seconds. This can be used to enforce rekeying of +# PTK to mitigate some attacks against TKIP deficiencies. +#wpa_ptk_rekey=600 + +# Enable IEEE 802.11i/RSN/WPA2 pre-authentication. This is used to speed up +# roaming be pre-authenticating IEEE 802.1X/EAP part of the full RSN +# authentication and key handshake before actually associating with a new AP. +# (dot11RSNAPreauthenticationEnabled) +#rsn_preauth=1 +# +# Space separated list of interfaces from which pre-authentication frames are +# accepted (e.g., 'eth0' or 'eth0 wlan0wds0'. This list should include all +# interface that are used for connections to other APs. This could include +# wired interfaces and WDS links. The normal wireless data interface towards +# associated stations (e.g., wlan0) should not be added, since +# pre-authentication is only used with APs other than the currently associated +# one. +#rsn_preauth_interfaces=eth0 + +# peerkey: Whether PeerKey negotiation for direct links (IEEE 802.11e) is +# allowed. This is only used with RSN/WPA2. +# 0 = disabled (default) +# 1 = enabled +#peerkey=1 + +# ieee80211w: Whether management frame protection (MFP) is enabled +# 0 = disabled (default) +# 1 = optional +# 2 = required +#ieee80211w=0 + +# Association SA Query maximum timeout (in TU = 1.024 ms; for MFP) +# (maximum time to wait for a SA Query response) +# dot11AssociationSAQueryMaximumTimeout, 1...4294967295 +#assoc_sa_query_max_timeout=1000 + +# Association SA Query retry timeout (in TU = 1.024 ms; for MFP) +# (time between two subsequent SA Query requests) +# dot11AssociationSAQueryRetryTimeout, 1...4294967295 +#assoc_sa_query_retry_timeout=201 + + +# okc: Opportunistic Key Caching (aka Proactive Key Caching) +# Allow PMK cache to be shared opportunistically among configured interfaces +# and BSSes (i.e., all configurations within a single hostapd process). +# 0 = disabled (default) +# 1 = enabled +#okc=1 + + +##### IEEE 802.11r configuration ############################################## + +# Mobility Domain identifier (dot11FTMobilityDomainID, MDID) +# MDID is used to indicate a group of APs (within an ESS, i.e., sharing the +# same SSID) between which a STA can use Fast BSS Transition. +# 2-octet identifier as a hex string. +#mobility_domain=a1b2 + +# PMK-R0 Key Holder identifier (dot11FTR0KeyHolderID) +# 1 to 48 octet identifier. +# This is configured with nas_identifier (see RADIUS client section above). + +# Default lifetime of the PMK-RO in minutes; range 1..65535 +# (dot11FTR0KeyLifetime) +#r0_key_lifetime=10000 + +# PMK-R1 Key Holder identifier (dot11FTR1KeyHolderID) +# 6-octet identifier as a hex string. +#r1_key_holder=000102030405 + +# Reassociation deadline in time units (TUs / 1.024 ms; range 1000..65535) +# (dot11FTReassociationDeadline) +#reassociation_deadline=1000 + +# List of R0KHs in the same Mobility Domain +# format: <128-bit key as hex string> +# This list is used to map R0KH-ID (NAS Identifier) to a destination MAC +# address when requesting PMK-R1 key from the R0KH that the STA used during the +# Initial Mobility Domain Association. +#r0kh=02:01:02:03:04:05 r0kh-1.example.com 000102030405060708090a0b0c0d0e0f +#r0kh=02:01:02:03:04:06 r0kh-2.example.com 00112233445566778899aabbccddeeff +# And so on.. One line per R0KH. + +# List of R1KHs in the same Mobility Domain +# format: <128-bit key as hex string> +# This list is used to map R1KH-ID to a destination MAC address when sending +# PMK-R1 key from the R0KH. This is also the list of authorized R1KHs in the MD +# that can request PMK-R1 keys. +#r1kh=02:01:02:03:04:05 02:11:22:33:44:55 000102030405060708090a0b0c0d0e0f +#r1kh=02:01:02:03:04:06 02:11:22:33:44:66 00112233445566778899aabbccddeeff +# And so on.. One line per R1KH. + +# Whether PMK-R1 push is enabled at R0KH +# 0 = do not push PMK-R1 to all configured R1KHs (default) +# 1 = push PMK-R1 to all configured R1KHs whenever a new PMK-R0 is derived +#pmk_r1_push=1 + +##### Neighbor table ########################################################## +# Maximum number of entries kept in AP table (either for neigbor table or for +# detecting Overlapping Legacy BSS Condition). The oldest entry will be +# removed when adding a new entry that would make the list grow over this +# limit. Note! WFA certification for IEEE 802.11g requires that OLBC is +# enabled, so this field should not be set to 0 when using IEEE 802.11g. +# default: 255 +#ap_table_max_size=255 + +# Number of seconds of no frames received after which entries may be deleted +# from the AP table. Since passive scanning is not usually performed frequently +# this should not be set to very small value. In addition, there is no +# guarantee that every scan cycle will receive beacon frames from the +# neighboring APs. +# default: 60 +#ap_table_expiration_time=3600 + + +##### Wi-Fi Protected Setup (WPS) ############################################# + +# WPS state +# 0 = WPS disabled (default) +# 1 = WPS enabled, not configured +# 2 = WPS enabled, configured +#wps_state=2 + +# AP can be configured into a locked state where new WPS Registrar are not +# accepted, but previously authorized Registrars (including the internal one) +# can continue to add new Enrollees. +#ap_setup_locked=1 + +# Universally Unique IDentifier (UUID; see RFC 4122) of the device +# This value is used as the UUID for the internal WPS Registrar. If the AP +# is also using UPnP, this value should be set to the device's UPnP UUID. +# If not configured, UUID will be generated based on the local MAC address. +#uuid=12345678-9abc-def0-1234-56789abcdef0 + +# Note: If wpa_psk_file is set, WPS is used to generate random, per-device PSKs +# that will be appended to the wpa_psk_file. If wpa_psk_file is not set, the +# default PSK (wpa_psk/wpa_passphrase) will be delivered to Enrollees. Use of +# per-device PSKs is recommended as the more secure option (i.e., make sure to +# set wpa_psk_file when using WPS with WPA-PSK). + +# When an Enrollee requests access to the network with PIN method, the Enrollee +# PIN will need to be entered for the Registrar. PIN request notifications are +# sent to hostapd ctrl_iface monitor. In addition, they can be written to a +# text file that could be used, e.g., to populate the AP administration UI with +# pending PIN requests. If the following variable is set, the PIN requests will +# be written to the configured file. +#wps_pin_requests=/var/run/hostapd_wps_pin_requests + +# Device Name +# User-friendly description of device; up to 32 octets encoded in UTF-8 +#device_name=Wireless AP + +# Manufacturer +# The manufacturer of the device (up to 64 ASCII characters) +#manufacturer=Company + +# Model Name +# Model of the device (up to 32 ASCII characters) +#model_name=WAP + +# Model Number +# Additional device description (up to 32 ASCII characters) +#model_number=123 + +# Serial Number +# Serial number of the device (up to 32 characters) +#serial_number=12345 + +# Primary Device Type +# Used format: -- +# categ = Category as an integer value +# OUI = OUI and type octet as a 4-octet hex-encoded value; 0050F204 for +# default WPS OUI +# subcateg = OUI-specific Sub Category as an integer value +# Examples: +# 1-0050F204-1 (Computer / PC) +# 1-0050F204-2 (Computer / Server) +# 5-0050F204-1 (Storage / NAS) +# 6-0050F204-1 (Network Infrastructure / AP) +#device_type=6-0050F204-1 + +# OS Version +# 4-octet operating system version number (hex string) +#os_version=01020300 + +# Config Methods +# List of the supported configuration methods +# Available methods: usba ethernet label display ext_nfc_token int_nfc_token +# nfc_interface push_button keypad +#config_methods=label display push_button keypad + +# Static access point PIN for initial configuration and adding Registrars +# If not set, hostapd will not allow external WPS Registrars to control the +# access point. The AP PIN can also be set at runtime with hostapd_cli +# wps_ap_pin command. Use of temporary (enabled by user action) and random +# AP PIN is much more secure than configuring a static AP PIN here. As such, +# use of the ap_pin parameter is not recommended if the AP device has means for +# displaying a random PIN. +#ap_pin=12345670 + +# Skip building of automatic WPS credential +# This can be used to allow the automatically generated Credential attribute to +# be replaced with pre-configured Credential(s). +#skip_cred_build=1 + +# Additional Credential attribute(s) +# This option can be used to add pre-configured Credential attributes into M8 +# message when acting as a Registrar. If skip_cred_build=1, this data will also +# be able to override the Credential attribute that would have otherwise been +# automatically generated based on network configuration. This configuration +# option points to an external file that much contain the WPS Credential +# attribute(s) as binary data. +#extra_cred=hostapd.cred + +# Credential processing +# 0 = process received credentials internally (default) +# 1 = do not process received credentials; just pass them over ctrl_iface to +# external program(s) +# 2 = process received credentials internally and pass them over ctrl_iface +# to external program(s) +# Note: With wps_cred_processing=1, skip_cred_build should be set to 1 and +# extra_cred be used to provide the Credential data for Enrollees. +# +# wps_cred_processing=1 will disabled automatic updates of hostapd.conf file +# both for Credential processing and for marking AP Setup Locked based on +# validation failures of AP PIN. An external program is responsible on updating +# the configuration appropriately in this case. +#wps_cred_processing=0 + +# AP Settings Attributes for M7 +# By default, hostapd generates the AP Settings Attributes for M7 based on the +# current configuration. It is possible to override this by providing a file +# with pre-configured attributes. This is similar to extra_cred file format, +# but the AP Settings attributes are not encapsulated in a Credential +# attribute. +#ap_settings=hostapd.ap_settings + +# WPS UPnP interface +# If set, support for external Registrars is enabled. +#upnp_iface=br0 + +# Friendly Name (required for UPnP) +# Short description for end use. Should be less than 64 characters. +#friendly_name=WPS Access Point + +# Manufacturer URL (optional for UPnP) +#manufacturer_url=http://www.example.com/ + +# Model Description (recommended for UPnP) +# Long description for end user. Should be less than 128 characters. +#model_description=Wireless Access Point + +# Model URL (optional for UPnP) +#model_url=http://www.example.com/model/ + +# Universal Product Code (optional for UPnP) +# 12-digit, all-numeric code that identifies the consumer package. +#upc=123456789012 + +##### Multiple BSSID support ################################################## +# +# Above configuration is using the default interface (wlan#, or multi-SSID VLAN +# interfaces). Other BSSIDs can be added by using separator 'bss' with +# default interface name to be allocated for the data packets of the new BSS. +# +# hostapd will generate BSSID mask based on the BSSIDs that are +# configured. hostapd will verify that dev_addr & MASK == dev_addr. If this is +# not the case, the MAC address of the radio must be changed before starting +# hostapd (ifconfig wlan0 hw ether ). If a BSSID is configured for +# every secondary BSS, this limitation is not applied at hostapd and other +# masks may be used if the driver supports them (e.g., swap the locally +# administered bit) +# +# BSSIDs are assigned in order to each BSS, unless an explicit BSSID is +# specified using the 'bssid' parameter. +# If an explicit BSSID is specified, it must be chosen such that it: +# - results in a valid MASK that covers it and the dev_addr +# - is not the same as the MAC address of the radio +# - is not the same as any other explicitly specified BSSID +# +# Please note that hostapd uses some of the values configured for the first BSS +# as the defaults for the following BSSes. However, it is recommended that all +# BSSes include explicit configuration of all relevant configuration items. +# +#bss=wlan0_0 +#ssid=test2 +# most of the above items can be used here (apart from radio interface specific +# items, like channel) + +#bss=wlan0_1 +#bssid=00:13:10:95:fe:0b +# ... diff --git a/lib/python/Plugins/SystemPlugins/WirelessAccessPoint/meta/Makefile.am b/lib/python/Plugins/SystemPlugins/WirelessAccessPoint/meta/Makefile.am new file mode 100755 index 0000000..6369e8c --- /dev/null +++ b/lib/python/Plugins/SystemPlugins/WirelessAccessPoint/meta/Makefile.am @@ -0,0 +1,3 @@ +installdir = $(datadir)/meta + +dist_install_DATA = plugin_wirelessaccesspoint.xml diff --git a/lib/python/Plugins/SystemPlugins/WirelessAccessPoint/meta/plugin_wirelessaccesspoint.xml b/lib/python/Plugins/SystemPlugins/WirelessAccessPoint/meta/plugin_wirelessaccesspoint.xml new file mode 100755 index 0000000..cf53317 --- /dev/null +++ b/lib/python/Plugins/SystemPlugins/WirelessAccessPoint/meta/plugin_wirelessaccesspoint.xml @@ -0,0 +1,17 @@ + + + + + + + hschang + Wireless Access Point + enigma2-plugin-systemplugins-wirelessaccesspoint + Using a Wireless module as AP. + Using a Wireless module as AP.\n(The Module should support master mode) + + + + + + diff --git a/lib/python/Plugins/SystemPlugins/WirelessAccessPoint/plugin.py b/lib/python/Plugins/SystemPlugins/WirelessAccessPoint/plugin.py new file mode 100755 index 0000000..9635780 --- /dev/null +++ b/lib/python/Plugins/SystemPlugins/WirelessAccessPoint/plugin.py @@ -0,0 +1,589 @@ +from Screens.Screen import Screen +from Components.ConfigList import ConfigListScreen, ConfigList +from Components.config import config, ConfigSubsection, getConfigListEntry, ConfigSelection, ConfigIP, ConfigInteger +from Components.config import ConfigText, ConfigYesNo, NoSave, ConfigPassword, ConfigNothing, ConfigSequence +from Components.ActionMap import ActionMap +from Screens.MessageBox import MessageBox +from Components.Sources.StaticText import StaticText +from Plugins.Plugin import PluginDescriptor +from Tools.Directories import fileExists +from math import pow as math_pow +from Components.Network import iNetwork +from Components.PluginComponent import plugins +from Components.Console import Console +from os import path as os_path, system as os_system, listdir +from Tools.Directories import resolveFilename, SCOPE_PLUGINS +from enigma import eTimer +import wirelessap + +debug_msg_on = False +def printDebugMsg(msg): + global debug_msg_on + if debug_msg_on: + print "[Wireless Access Point] ", msg + +class fixedValue: + def __init__(self, value = ""): + self.value = value + +apModeConfig = ConfigSubsection() +apModeConfig.useap = ConfigYesNo(default = False) +apModeConfig.setupmode = ConfigSelection(default = "simple", choices = [ ("simple", "Simple"), ("advanced", "Advanced") ] ) +#apModeConfig.wirelessdevice = fixedValue(value = "") +apModeConfig.branch = fixedValue(value = "br0") +apModeConfig.driver = fixedValue(value = "nl80211") +apModeConfig.wirelessmode = ConfigSelection(default = "g", choices = [ ("b", "802.11b"), ("a", "802.11a"), ("g", "802.11g") ] ) +apModeConfig.channel = ConfigInteger(default = 1, limits = (1,13) ) +apModeConfig.ssid = ConfigText(default = "Input SSID", visible_width = 50, fixed_size = False) +apModeConfig.beacon = ConfigInteger(default = 100, limits = (15,65535)) +apModeConfig.rts_threshold = ConfigInteger(default = 2347, limits = (0,2347) ) +apModeConfig.fragm_threshold = ConfigInteger(default = 2346, limits = (256,2346) ) +apModeConfig.preamble = ConfigSelection(default = "0", choices = [ ("0", "Long"), ("1", "Short") ] ) +apModeConfig.ignore_broadcast_ssid = ConfigSelection(default = "0", choices = [ ("0", _("disabled")), ("1", _("enabled")) ]) + +apModeConfig.encrypt = ConfigYesNo(default = False) +apModeConfig.method = ConfigSelection(default = "0", choices = [ + ("0", _("WEP")), ("1", _("WPA")), ("2", _("WPA2")),("3", _("WPA/WPA2"))]) +apModeConfig.wep = ConfigYesNo(default = False) +#apModeConfig.wep_default_key = ConfigSelection(default = "0", choices = [ ("0", "0"), ("1", "1"), ("2", "2"), ("3", "3") ] ) +apModeConfig.wep_default_key = fixedValue(value = "0") +apModeConfig.wepType = ConfigSelection(default = "64", choices = [ + ("64", _("Enable 64 bit (Input 10 hex keys)")), ("128", _("Enable 128 bit (Input 26 hex keys)"))]) +apModeConfig.wep_key0 = ConfigPassword(default = "", visible_width = 50, fixed_size = False) +apModeConfig.wpa = ConfigSelection(default = "0", choices = [ + ("0", _("not set")), ("1", _("WPA")), ("2", _("WPA2")),("3", _("WPA/WPA2"))]) +apModeConfig.wpa_passphrase = ConfigPassword(default = "", visible_width = 50, fixed_size = False) +apModeConfig.wpagrouprekey = ConfigInteger(default = 600, limits = (0,3600)) +apModeConfig.wpa_key_mgmt = fixedValue(value = "WPA-PSK") +apModeConfig.wpa_pairwise = fixedValue(value = "TKIP CCMP") +apModeConfig.rsn_pairwise = fixedValue(value = "CCMP") + +apModeConfig.usedhcp = ConfigYesNo(default=True) +apModeConfig.address = ConfigIP(default = [0,0,0,0]) +apModeConfig.netmask = ConfigIP(default = [255,0,0,0]) +apModeConfig.gateway = ConfigIP(default = [0,0,0,0]) + +class WirelessAccessPoint(Screen,ConfigListScreen): + skin = """ + + + + + + + + + + + + + + + + + + + + """ + + def __init__(self,session): + Screen.__init__(self,session) + self.session = session + self["shortcuts"] = ActionMap(["ShortcutActions", "SetupActions" ], + { + "ok": self.doConfigMsg, + "cancel": self.keyCancel, + "red": self.keyCancel, + "green": self.doConfigMsg, + }, -2) + self.list = [] + ConfigListScreen.__init__(self, self.list,session = self.session) + self["key_red"] = StaticText(_("Cancel")) + self["key_green"] = StaticText(_("Ok")) + self["key_yellow"] = StaticText(_(" ")) + self["key_blue"] = StaticText(_(" ")) + self["current_settings"] = StaticText(_("Current settings (interface : br0)")) + self["IPAddress_text"] = StaticText(_("IP Address")) + self["Netmask_text"] = StaticText(_("Netmask")) + self["Gateway_text"] = StaticText(_("Gateway")) + self["IPAddress"] = StaticText(_("N/A")) + self["Netmask"] = StaticText(_("N/A")) + self["Gateway"] = StaticText(_("N/A")) + self.wirelessAP = wirelessap.wirelessAP() + self.checkRunHostapd() + self.checkWirelessDevices() + self.makeConfigList() + self.loadInterfacesConfig() + self.loadHostapConfig() + self.setupCurrentEncryption() + self.createConfigEntry() + self.createConfig() + self.onClose.append(self.__onClose) + self.onLayoutFinish.append(self.checkwlanDeviceList) + self.onLayoutFinish.append(self.currentNetworkSettings) + self.checkwlanDeviceListTimer = eTimer() + self.checkwlanDeviceListTimer.callback.append(self.WirelessDeviceNotDetectedMsg) + + def checkwlanDeviceList(self): + if len(self.wlanDeviceList) == 0: + self.checkwlanDeviceListTimer.start(100,True) + + def WirelessDeviceNotDetectedMsg(self): + self.session.openWithCallback(self.close ,MessageBox, _("Wireless Lan Device is not detected."), MessageBox.TYPE_ERROR) + + def currentNetworkSettings(self): + self["IPAddress"].setText(self.formatAddr(iNetwork.getAdapterAttribute("br0", "ip"))) + self["Netmask"].setText(self.formatAddr(iNetwork.getAdapterAttribute("br0", "netmask"))) + self["Gateway"].setText(self.formatAddr(iNetwork.getAdapterAttribute("br0", "gateway"))) + + def formatAddr(self, address = [0,0,0,0]): + if address is None: + return "N/A" + return "%d:%d:%d:%d"%(address[0],address[1],address[2],address[3]) + + def checkRunHostapd(self): + global apModeConfig + if fileExists("/var/run/hostapd", 0): + apModeConfig.useap.value = True + + def makeConfigList(self): + global apModeConfig + self.hostapdConfigList = {} + self.hostapdConfigList["interface"] = apModeConfig.wirelessdevice + self.hostapdConfigList["bridge"] = apModeConfig.branch # "br0" + self.hostapdConfigList["driver"] = apModeConfig.driver # "nl80211" + self.hostapdConfigList["hw_mode"] = apModeConfig.wirelessmode + self.hostapdConfigList["channel"] = apModeConfig.channel + self.hostapdConfigList["ssid"] = apModeConfig.ssid + self.hostapdConfigList["beacon_int"] = apModeConfig.beacon + self.hostapdConfigList["rts_threshold"] = apModeConfig.rts_threshold + self.hostapdConfigList["fragm_threshold"] = apModeConfig.fragm_threshold + self.hostapdConfigList["preamble"] = apModeConfig.preamble +# self.hostapdConfigList["macaddr_acl"] = "" # fix to add Access Control List Editer +# self.hostapdConfigList["accept_mac_file"] = "" # fix to add Access Control List Editer +# self.hostapdConfigList["deny_mac_file"] = "" # fix to add Access Control List Editer + self.hostapdConfigList["ignore_broadcast_ssid"] = apModeConfig.ignore_broadcast_ssid +# self.hostapdConfigList["wmm_enabled"] = "" +# self.hostapdConfigList["ieee80211n"] = "" +# self.hostapdConfigList["ht_capab"] = "" + self.hostapdConfigList["wep_default_key"] = apModeConfig.wep_default_key + self.hostapdConfigList["wep_key0"] = apModeConfig.wep_key0 + self.hostapdConfigList["wpa"] = apModeConfig.wpa + self.hostapdConfigList["wpa_passphrase"] = apModeConfig.wpa_passphrase + self.hostapdConfigList["wpa_key_mgmt"] = apModeConfig.wpa_key_mgmt # "WPA-PSK" + self.hostapdConfigList["wpa_pairwise"] = apModeConfig.wpa_pairwise # "TKIP CCMP" + self.hostapdConfigList["rsn_pairwise"] = apModeConfig.rsn_pairwise # "CCMP" + self.hostapdConfigList["wpa_group_rekey"] = apModeConfig.wpagrouprekey + + def loadInterfacesConfig(self): + global apModeConfig + try: + fp = file('/etc/network/interfaces', 'r') + datas = fp.readlines() + fp.close() + except: + printDebugMsg("interfaces - file open failed") + # check br0 configuration + current_iface = "" + ifaceConf = {} + try: + for line in datas: + split = line.strip().split(' ') + if (split[0] == "iface"): + current_iface = split[1] + if (current_iface == "br0") and (len(split) == 4 and split[3] == "dhcp"): + apModeConfig.usedhcp.value = True + else: + apModeConfig.usedhcp.value = False + if (current_iface == "br0" or current_iface == "eth0"): + if (split[0] == "address"): + apModeConfig.address.value = map(int, split[1].split('.')) + if (split[0] == "netmask"): + apModeConfig.netmask.value = map(int, split[1].split('.')) + if (split[0] == "gateway"): + apModeConfig.gateway.value = map(int, split[1].split('.')) + except: + printDebugMsg("configuration parsing error! - /etc/network/interfaces") + + def loadHostapConfig(self): + hostapdConf = { } + ret = self.wirelessAP.loadHostapConfig(hostapdConf) + if ret != 0: + printDebugMsg("configuration opening failed!!") + return + for (key,value) in hostapdConf.items(): + if key == "config.wep": + apModeConfig.wep.value = int(value) + elif key in ["channel", "beacon_int", "rts_threshold", "fragm_threshold", "wpa_group_rekey"]: + self.hostapdConfigList[key].value = int(value) + elif key in self.hostapdConfigList.keys(): + self.hostapdConfigList[key].value = value + if key == "channel" and value not in range(14): + self.hostapdConfigList[key].value = 1 + +# for key in self.hostapdConfigList.keys(): +# printDebugMsg("[cofigList] key : %s, value : %s"%(key, str(self.hostapdConfigList[key].value)) ) + + def setupCurrentEncryption(self): + if apModeConfig.wpa.value is not "0" and apModeConfig.wpa_passphrase.value: # (1,WPA), (2,WPA2), (3,WPA/WPA2) + apModeConfig.encrypt.value = True + apModeConfig.method.value = apModeConfig.wpa.value + elif apModeConfig.wep.value and apModeConfig.wep_key0.value: + apModeConfig.encrypt.value = True + apModeConfig.method.value = "0" + if len(apModeConfig.wep_key0.value) > 10: + apModeConfig.wepType.value = "128" + else: + apModeConfig.encrypt.value = False + + def createConfigEntry(self): + global apModeConfig +#hostap settings + self.useApEntry = getConfigListEntry(_("Use AP Mode"), apModeConfig.useap) + self.setupModeEntry = getConfigListEntry(_("Setup Mode"), apModeConfig.setupmode) + self.wirelessDeviceEntry = getConfigListEntry(_("AP Device"), apModeConfig.wirelessdevice) + self.wirelessModeEntry = getConfigListEntry(_("AP Mode"), apModeConfig.wirelessmode) + self.channelEntry = getConfigListEntry(_("Channel (1~13)"), apModeConfig.channel) + self.ssidEntry = getConfigListEntry(_("SSID (0~32 Characters)"), apModeConfig.ssid) + self.beaconEntry = getConfigListEntry(_("Beacon (15~65535)"), apModeConfig.beacon) + self.rtsThresholdEntry = getConfigListEntry(_("RTS Threshold (0~2347)"), apModeConfig.rts_threshold) + self.fragmThresholdEntry = getConfigListEntry(_("FRAGM Threshold (256~2346)"), apModeConfig.fragm_threshold) + self.prambleEntry = getConfigListEntry(_("Preamble"), apModeConfig.preamble) + self.ignoreBroadcastSsid = getConfigListEntry(_("Ignore Broadcast SSID"), apModeConfig.ignore_broadcast_ssid) +# hostap encryption + self.encryptEntry = getConfigListEntry(_("Encrypt"), apModeConfig.encrypt) + self.methodEntry = getConfigListEntry(_("Method"), apModeConfig.method) + self.wepKeyTypeEntry = getConfigListEntry(_("KeyType"), apModeConfig.wepType) + self.wepKey0Entry = getConfigListEntry(_("WEP Key (HEX)"), apModeConfig.wep_key0) + self.wpaKeyEntry = getConfigListEntry(_("KEY (8~63 Characters)"), apModeConfig.wpa_passphrase) + self.groupRekeyEntry = getConfigListEntry(_("Group Rekey Interval"), apModeConfig.wpagrouprekey) +# interface settings + self.usedhcpEntry = getConfigListEntry(_("Use DHCP"), apModeConfig.usedhcp) + self.ipEntry = getConfigListEntry(_("IP Address"), apModeConfig.address) + self.netmaskEntry = getConfigListEntry(_("NetMask"), apModeConfig.netmask) + self.gatewayEntry = getConfigListEntry(_("Gateway"), apModeConfig.gateway) + + def createConfig(self): + global apModeConfig + self.configList = [] + self.configList.append( self.useApEntry ) + if apModeConfig.useap.value is True: + self.configList.append( self.setupModeEntry ) + self.configList.append( self.wirelessDeviceEntry ) + self.configList.append( self.wirelessModeEntry ) + self.configList.append( self.channelEntry ) + self.configList.append( self.ssidEntry ) + if apModeConfig.setupmode.value is "advanced": + self.configList.append( self.beaconEntry ) + self.configList.append( self.rtsThresholdEntry ) + self.configList.append( self.fragmThresholdEntry ) + self.configList.append( self.prambleEntry ) + self.configList.append( self.ignoreBroadcastSsid ) + self.configList.append( self.encryptEntry ) + if apModeConfig.encrypt.value is True: + self.configList.append( self.methodEntry ) + if apModeConfig.method.value is "0": # wep + self.configList.append( self.wepKeyTypeEntry ) + self.configList.append( self.wepKey0Entry ) + else: + self.configList.append( self.wpaKeyEntry ) + if apModeConfig.setupmode.value is "advanced": + self.configList.append( self.groupRekeyEntry ) +## set network interfaces + self.configList.append( self.usedhcpEntry ) + if apModeConfig.usedhcp.value is False: + self.configList.append( self.ipEntry ) + self.configList.append( self.netmaskEntry ) + self.configList.append( self.gatewayEntry ) + self["config"].list = self.configList + self["config"].l.setList(self.configList) + + def keyLeft(self): + ConfigListScreen.keyLeft(self) + self.newConfig() + + def keyRight(self): + ConfigListScreen.keyRight(self) + self.newConfig() + + def newConfig(self): + if self["config"].getCurrent() in [ self.encryptEntry, self.methodEntry, self.useApEntry, self.usedhcpEntry, self.setupModeEntry]: + self.createConfig() + + def doConfigMsg(self): + try: + self.session.openWithCallback(self.doConfig, MessageBox, (_("Are you sure you want to setup your AP?\n\n") ) ) + except: + printDebugMsg("doConfig failed") + + def doConfig(self, ret = False): + global apModeConfig + if ret is not True: + return + if apModeConfig.useap.value is True and apModeConfig.encrypt.value is True: + if not self.checkEncrypKey(): + return + if not self.checkConfig(): + return + self.configStartMsg = self.session.openWithCallback(self.ConfigFinishedMsg, MessageBox, _("Please wait for AP Configuration....\n") , type = MessageBox.TYPE_INFO, enable_input = False) + if apModeConfig.useap.value is True: + self.networkRestart( nextFunc = self.makeConf ) + else: + self.networkRestart( nextFunc = self.removeConf ) + + def checkEncrypKey(self): + if apModeConfig.method.value == "0": + if self.checkWep(apModeConfig.wep_key0.value) is False: + self.session.open(MessageBox, _("Invalid WEP key\n\n"), type = MessageBox.TYPE_ERROR, timeout = 10 ) + else: + return True + else: + if not len(apModeConfig.wpa_passphrase.value) in range(8,65): + self.session.open(MessageBox, _("Invalid WPA key\n\n"), type = MessageBox.TYPE_ERROR, timeout = 10) + else: + return True + return False + + def checkWep(self, key): + length = len(key) + if length == 0: + return False + elif apModeConfig.wepType.value == "64" and length == 10: + return True + elif apModeConfig.wepType.value == "128" and length == 26: + return True + else: + return False + + def checkConfig(self): + # ssid Check + if len(apModeConfig.ssid.value) == 0 or len(apModeConfig.ssid.value) > 32: + self.session.open(MessageBox, _("Invalid SSID\n"), type = MessageBox.TYPE_ERROR, timeout = 10) + return False; + elif apModeConfig.channel.value not in range(1,14): + self.session.open(MessageBox, _("Invalid channel\n"), type = MessageBox.TYPE_ERROR, timeout = 10) + return False; + elif apModeConfig.beacon.value < 15 or apModeConfig.beacon.value > 65535: + self.session.open(MessageBox, _("Invalid beacon\n"), type = MessageBox.TYPE_ERROR, timeout = 10) + return False; + elif apModeConfig.rts_threshold.value < 0 or apModeConfig.rts_threshold.value > 2347: + self.session.open(MessageBox, _("Invalid RTS Threshold\n"), type = MessageBox.TYPE_ERROR, timeout = 10) + return False; + elif apModeConfig.fragm_threshold.value < 256 or apModeConfig.fragm_threshold.value > 2346: + self.session.open(MessageBox, _("Invalid Fragm Threshold\n"), type = MessageBox.TYPE_ERROR, timeout = 10) + return False; + elif apModeConfig.wpagrouprekey.value < 0 or apModeConfig.wpagrouprekey.value > 3600: + self.session.open(MessageBox, _("Invalid wpagrouprekey\n"), type = MessageBox.TYPE_ERROR, timeout = 10) + return False; + return True; + + def networkRestart(self, nextFunc = None ): + self.networkRestart_stop( nextFunc = nextFunc ) + + def networkRestart_stop(self, nextFunc = None ): + printDebugMsg("networkRestart_stop") + self.msgPlugins(False) + self.commands = [] # stop current network + self.networkRestartConsole = Console() + self.commands.append("/etc/init.d/avahi-daemon stop") + for iface in iNetwork.getAdapterList(): + if iface != 'eth0' or not iNetwork.onRemoteRootFS(): + self.commands.append("ifdown " + iface) + self.commands.append("ip addr flush dev " + iface) + self.commands.append("/etc/init.d/hostapd stop") + self.commands.append("/etc/init.d/networking stop") + self.commands.append("killall -9 udhcpc") + self.commands.append("rm /var/run/udhcpc*") + self.networkRestartConsole.eBatch(self.commands, nextFunc, debug = True) + + def makeConf(self,extra_args): + printDebugMsg("makeConf") + self.writeNetworkInterfaces() + result = self.writeHostapdConfig() + if result == -1: + self.configStartMsg.close(False) + return + self.setIpForward(1) + self.networkRestart_start() + + def removeConf(self,extra_args): + printDebugMsg("removeConf") + if fileExists("/etc/hostapd.conf", 0): + os_system("mv /etc/hostapd.conf /etc/hostapd.conf.linuxap.back") + fp = file("/etc/network/interfaces", 'w') + fp.write("# automatically generated by AP Setup Plugin\n# do NOT change manually!\n\n") + fp.write("auto lo\n") + fp.write("iface lo inet loopback\n\n") + # eth0 setup + fp.write("auto eth0\n") + if apModeConfig.usedhcp.value is True: + fp.write("iface eth0 inet dhcp\n") + else: + fp.write("iface eth0 inet static\n") + fp.write(" address %d.%d.%d.%d\n" % tuple(apModeConfig.address.value) ) + fp.write(" netmask %d.%d.%d.%d\n" % tuple(apModeConfig.netmask.value) ) + fp.write(" gateway %d.%d.%d.%d\n" % tuple(apModeConfig.gateway.value) ) + fp.close() + self.setIpForward(0) + self.networkRestart_start() + + def networkRestart_start(self): + printDebugMsg("networkRestart_start") + self.restartConsole = Console() + self.commands = [] + self.commands.append("/etc/init.d/networking start") + self.commands.append("/etc/init.d/avahi-daemon start") + self.commands.append("/etc/init.d/hostapd start") + self.restartConsole.eBatch(self.commands, self.networkRestartFinished, debug=True) + + def networkRestartFinished(self, data): + printDebugMsg("networkRestartFinished") + iNetwork.removeAdapterAttribute('br0',"ip") + iNetwork.removeAdapterAttribute('br0',"netmask") + iNetwork.removeAdapterAttribute('br0',"gateway") + iNetwork.getInterfaces(self.getInterfacesDataAvail) + + def getInterfacesDataAvail(self, data): + if data is True and self.configStartMsg is not None: + self.configStartMsg.close(True) + + def ConfigFinishedMsg(self, ret): + if ret is True: + self.session.openWithCallback(self.ConfigFinishedMsgCallback ,MessageBox, _("Configuration your AP is finished"), type = MessageBox.TYPE_INFO, timeout = 5, default = False) + else: + self.session.openWithCallback(self.close ,MessageBox, _("Invalid model or Image."), MessageBox.TYPE_ERROR) + + def ConfigFinishedMsgCallback(self,data): + self.close() + + def msgPlugins(self,reason = False): + for p in plugins.getPlugins(PluginDescriptor.WHERE_NETWORKCONFIG_READ): + p(reason=reason) + + def writeNetworkInterfaces(self): + global apModeConfig + fp = file("/etc/network/interfaces", 'w') + fp.write("# automatically generated by AP Setup Plugin\n# do NOT change manually!\n\n") + fp.write("auto lo\n") + fp.write("iface lo inet loopback\n\n") + # eth0 setup + fp.write("auto eth0\n") + fp.write("iface eth0 inet manual\n") + fp.write(" up ip link set $IFACE up\n") + fp.write(" down ip link set $IFACE down\n\n") + # Wireless device setup + fp.write("auto %s\n" % apModeConfig.wirelessdevice.value) + fp.write("iface %s inet manual\n" % apModeConfig.wirelessdevice.value) + fp.write(" up ip link set $IFACE up\n") + fp.write(" down ip link set $IFACE down\n") + # branch setup + fp.write("auto br0\n") + if apModeConfig.usedhcp.value is True: + fp.write("iface br0 inet dhcp\n") + else: + fp.write("iface br0 inet static\n") + fp.write(" address %d.%d.%d.%d\n" % tuple(apModeConfig.address.value) ) + fp.write(" netmask %d.%d.%d.%d\n" % tuple(apModeConfig.netmask.value) ) + fp.write(" gateway %d.%d.%d.%d\n" % tuple(apModeConfig.gateway.value) ) + fp.write(" pre-up brctl addbr br0\n") + fp.write(" pre-up brctl addif br0 eth0\n") +# fp.write(" pre-up brctl addif br0 wlan0\n") // runned by hostpad + fp.write(" post-down brctl delif br0 eth0\n") +# fp.write(" post-down brctl delif br0 wlan0\n") // runned by hostpad + fp.write(" post-down brctl delbr br0\n\n") + fp.write("\n") + fp.close() + + def writeHostapdConfig(self): #c++ + global apModeConfig + configDict = {} + for key in self.hostapdConfigList.keys(): + configDict[key] = str(self.hostapdConfigList[key].value) + configDict["config.encrypt"] = str(int(apModeConfig.encrypt.value)) + configDict["config.method"] = apModeConfig.method.value + ret = self.wirelessAP.writeHostapdConfig(configDict) + if(ret != 0): + return -1 + return 0 + + def setIpForward(self, setValue = 0): + ipForwardFilePath = "/proc/sys/net/ipv4/ip_forward" + if not fileExists(ipForwardFilePath): + return -1 + printDebugMsg("set %s to %d" % (ipForwardFilePath, setValue)) + f = open(ipForwardFilePath, "w") + f.write("%d" % setValue) + f.close() + sysctlPath = "/etc/sysctl.conf" + sysctlLines = [] + if fileExists(sysctlPath): + fp = file(sysctlPath, "r") + sysctlLines = fp.readlines() + fp.close() + sysctlList = {} + for line in sysctlLines: + line = line.strip() + (key,value) = line.split("=") + key=key.strip() + value=value.strip() + sysctlList[key] = value + sysctlList["net.ipv4.ip_forward"] = str(setValue) + fp = file(sysctlPath, "w") + for (key,value) in sysctlList.items(): + fp.write("%s=%s\n"%(key,value)) + fp.close() + return 0 + + def checkWirelessDevices(self): + global apModeConfig + self.wlanDeviceList = [] + wlanIfaces =[] + for x in iNetwork.getInstalledAdapters(): + if x.startswith('eth') or x.startswith('br') or x.startswith('mon'): + continue + wlanIfaces.append(x) + description=self.getAdapterDescription(x) + if description == "Unknown network adapter": + self.wlanDeviceList.append((x, x)) + else: + self.wlanDeviceList.append(( x, description + " (%s)"%x )) + apModeConfig.wirelessdevice = ConfigSelection( choices = self.wlanDeviceList ) + + def getAdapterDescription(self, iface): + classdir = "/sys/class/net/" + iface + "/device/" + driverdir = "/sys/class/net/" + iface + "/device/driver/" + if os_path.exists(classdir): + files = listdir(classdir) + if 'driver' in files: + if os_path.realpath(driverdir).endswith('rtw_usb_drv'): + return _("Realtek")+ " " + _("WLAN adapter.") + elif os_path.realpath(driverdir).endswith('ath_pci'): + return _("Atheros")+ " " + _("WLAN adapter.") + elif os_path.realpath(driverdir).endswith('zd1211b'): + return _("Zydas")+ " " + _("WLAN adapter.") + elif os_path.realpath(driverdir).endswith('rt73'): + return _("Ralink")+ " " + _("WLAN adapter.") + elif os_path.realpath(driverdir).endswith('rt73usb'): + return _("Ralink")+ " " + _("WLAN adapter.") + else: + return str(os_path.basename(os_path.realpath(driverdir))) + " " + _("WLAN adapter") + else: + return _("Unknown network adapter") + else: + return _("Unknown network adapter") + + def __onClose(self): + for x in self["config"].list: + x[1].cancel() + apModeConfig.wpa.value = "0" + apModeConfig.wep.value = False + + def keyCancel(self): + self.close() + +def main(session, **kwargs): + session.open(WirelessAccessPoint) + +def Plugins(**kwargs): + return [PluginDescriptor(name=_("Wireless Access Point"), description="Using a Wireless module as access point.", where = PluginDescriptor.WHERE_PLUGINMENU, needsRestart = True, fnc=main)] + diff --git a/lib/python/Plugins/SystemPlugins/WirelessAccessPoint/wirelessap.py b/lib/python/Plugins/SystemPlugins/WirelessAccessPoint/wirelessap.py new file mode 100644 index 0000000..56e85cb --- /dev/null +++ b/lib/python/Plugins/SystemPlugins/WirelessAccessPoint/wirelessap.py @@ -0,0 +1,87 @@ +# This file was automatically generated by SWIG (http://www.swig.org). +# Version 1.3.39 +# +# Do not make changes to this file unless you know what you are doing--modify +# the SWIG interface file instead. +# This file is compatible with both classic and new-style classes. + +from sys import version_info +if version_info >= (2,6,0): + def swig_import_helper(): + from os.path import dirname + import imp + fp = None + try: + fp, pathname, description = imp.find_module('_wirelessap', [dirname(__file__)]) + except ImportError: + import _wirelessap + return _wirelessap + if fp is not None: + try: + _mod = imp.load_module('_wirelessap', fp, pathname, description) + finally: + fp.close() + return _mod + _wirelessap = swig_import_helper() + del swig_import_helper +else: + import _wirelessap +del version_info +try: + _swig_property = property +except NameError: + pass # Python < 2.2 doesn't have 'property'. +def _swig_setattr_nondynamic(self,class_type,name,value,static=1): + if (name == "thisown"): return self.this.own(value) + if (name == "this"): + if type(value).__name__ == 'SwigPyObject': + self.__dict__[name] = value + return + method = class_type.__swig_setmethods__.get(name,None) + if method: return method(self,value) + if (not static) or hasattr(self,name): + self.__dict__[name] = value + else: + raise AttributeError("You cannot add attributes to %s" % self) + +def _swig_setattr(self,class_type,name,value): + return _swig_setattr_nondynamic(self,class_type,name,value,0) + +def _swig_getattr(self,class_type,name): + if (name == "thisown"): return self.this.own() + method = class_type.__swig_getmethods__.get(name,None) + if method: return method(self) + raise AttributeError(name) + +def _swig_repr(self): + try: strthis = "proxy of " + self.this.__repr__() + except: strthis = "" + return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,) + +try: + _object = object + _newclass = 1 +except AttributeError: + class _object : pass + _newclass = 0 + + +class wirelessAP(_object): + __swig_setmethods__ = {} + __setattr__ = lambda self, name, value: _swig_setattr(self, wirelessAP, name, value) + __swig_getmethods__ = {} + __getattr__ = lambda self, name: _swig_getattr(self, wirelessAP, name) + __repr__ = _swig_repr + def __init__(self): + this = _wirelessap.new_wirelessAP() + try: self.this.append(this) + except: self.this = this + __swig_destroy__ = _wirelessap.delete_wirelessAP + __del__ = lambda self : None; + def loadHostapConfig(self, *args): return _wirelessap.wirelessAP_loadHostapConfig(self, *args) + def writeHostapdConfig(self, *args): return _wirelessap.wirelessAP_writeHostapdConfig(self, *args) +wirelessAP_swigregister = _wirelessap.wirelessAP_swigregister +wirelessAP_swigregister(wirelessAP) + + + -- 2.7.4