From d0032364eee3e5121a21a2917c2f2c26079d00bc Mon Sep 17 00:00:00 2001 From: Dmytro Bogovych Date: Tue, 19 Sep 2023 10:59:40 +0100 Subject: [PATCH] - first prototype of API enabled agent_gsm --- config/ap/etc/default/hostapd | 23 +++++++ config/ap/etc/dhcpcd.conf | 64 ++++++++++++++++++++ config/ap/etc/dnsmasq.conf | 5 ++ config/ap/etc/hostapd.conf | 8 +++ config/ap/lib/systemd/system/dnsmasq.service | 31 ++++++++++ src/agent_gsm.py | 8 ++- src/agent_point.py | 60 ++++++++++++------ src/utils_cache.py | 2 - 8 files changed, 179 insertions(+), 22 deletions(-) create mode 100644 config/ap/etc/default/hostapd create mode 100644 config/ap/etc/dhcpcd.conf create mode 100644 config/ap/etc/dnsmasq.conf create mode 100644 config/ap/etc/hostapd.conf create mode 100644 config/ap/lib/systemd/system/dnsmasq.service mode change 100644 => 100755 src/agent_point.py diff --git a/config/ap/etc/default/hostapd b/config/ap/etc/default/hostapd new file mode 100644 index 0000000..978f3e0 --- /dev/null +++ b/config/ap/etc/default/hostapd @@ -0,0 +1,23 @@ +# Defaults for hostapd initscript +# +# WARNING: The DAEMON_CONF setting has been deprecated and will be removed +# in future package releases. +# +# See /usr/share/doc/hostapd/README.Debian for information about alternative +# methods of managing hostapd. +# +# Uncomment and set DAEMON_CONF to the absolute path of a hostapd configuration +# file and hostapd will be started during system boot. An example configuration +# file can be found at /usr/share/doc/hostapd/examples/hostapd.conf.gz +# +DAEMON_CONF="/etc/hostapd/hostapd.conf" + +# Additional daemon options to be appended to hostapd command:- +# -d show more debug messages (-dd for even more) +# -K include key data in debug messages +# -t include timestamps in some debug messages +# +# Note that -B (daemon mode) and -P (pidfile) options are automatically +# configured by the init.d script and must not be added to DAEMON_OPTS. +# +#DAEMON_OPTS="" diff --git a/config/ap/etc/dhcpcd.conf b/config/ap/etc/dhcpcd.conf new file mode 100644 index 0000000..8c637d9 --- /dev/null +++ b/config/ap/etc/dhcpcd.conf @@ -0,0 +1,64 @@ +# A sample configuration for dhcpcd. +# See dhcpcd.conf(5) for details. + +# Allow users of this group to interact with dhcpcd via the control socket. +#controlgroup wheel + +# Inform the DHCP server of our hostname for DDNS. +hostname + +# Use the hardware address of the interface for the Client ID. +clientid +# or +# Use the same DUID + IAID as set in DHCPv6 for DHCPv4 ClientID as per RFC4361. +# Some non-RFC compliant DHCP servers do not reply with this set. +# In this case, comment out duid and enable clientid above. +#duid + +# Persist interface configuration when dhcpcd exits. +persistent + +# Rapid commit support. +# Safe to enable by default because it requires the equivalent option set +# on the server to actually work. +option rapid_commit + +# A list of options to request from the DHCP server. +option domain_name_servers, domain_name, domain_search, host_name +option classless_static_routes +# Respect the network MTU. This is applied to DHCP routes. +option interface_mtu + +# Most distributions have NTP support. +#option ntp_servers + +# A ServerID is required by RFC2131. +require dhcp_server_identifier + +# Generate SLAAC address using the Hardware Address of the interface +#slaac hwaddr +# OR generate Stable Private IPv6 Addresses based from the DUID +slaac private + +# Example static IP configuration: +#interface eth0 +#static ip_address=192.168.0.10/24 +#static ip6_address=fd51:42f8:caae:d92e::ff/64 +#static routers=192.168.0.1 +#static domain_name_servers=192.168.0.1 8.8.8.8 fd51:42f8:caae:d92e::1 + +# It is possible to fall back to a static IP if DHCP fails: +# define static profile +#profile static_eth0 +#static ip_address=192.168.1.23/24 +#static routers=192.168.1.1 +#static domain_name_servers=192.168.1.1 + +# fallback to static profile on eth0 +#interface eth0 +#fallback static_eth0 +# +# +interface wlan0 +static ip_address=192.168.45.1/24 +static routers=192.168.45.1 diff --git a/config/ap/etc/dnsmasq.conf b/config/ap/etc/dnsmasq.conf new file mode 100644 index 0000000..850f1e6 --- /dev/null +++ b/config/ap/etc/dnsmasq.conf @@ -0,0 +1,5 @@ +interface=wlan0 # Listening interface +dhcp-range=192.168.45.10,192.168.45.20,255.255.255.0,24h # Pool of IP addresses for wireless clients +domain=wlan # Domain +address=/gw.wlan/192.168.45.1 # Alias for router + diff --git a/config/ap/etc/hostapd.conf b/config/ap/etc/hostapd.conf new file mode 100644 index 0000000..b1982fa --- /dev/null +++ b/config/ap/etc/hostapd.conf @@ -0,0 +1,8 @@ +country_code=GB +interface=wlan0 +ssid=AGENT_GSM +hw_mode=g +channel=7 +macaddr_acl=0 +auth_algs=1 +ignore_broadcast_ssid=0 diff --git a/config/ap/lib/systemd/system/dnsmasq.service b/config/ap/lib/systemd/system/dnsmasq.service new file mode 100644 index 0000000..16f6df9 --- /dev/null +++ b/config/ap/lib/systemd/system/dnsmasq.service @@ -0,0 +1,31 @@ +[Unit] +Description=dnsmasq - A lightweight DHCP and caching DNS server +Requires=network.target +Wants=network-online.target +Before=nss-lookup.target +After=network-online.target + +[Service] +Type=forking +PIDFile=/run/dnsmasq/dnsmasq.pid + +# Test the config file and refuse starting if it is not valid. +ExecStartPre=/usr/sbin/dnsmasq --test + +# We run dnsmasq via the /etc/init.d/dnsmasq script which acts as a +# wrapper picking up extra configuration files and then execs dnsmasq +# itself, when called with the "systemd-exec" function. +ExecStart=/etc/init.d/dnsmasq systemd-exec + +# The systemd-*-resolvconf functions configure (and deconfigure) +# resolvconf to work with the dnsmasq DNS server. They're called like +# this to get correct error handling (ie don't start-resolvconf if the +# dnsmasq daemon fails to start. +ExecStartPost=/etc/init.d/dnsmasq systemd-start-resolvconf +ExecStop=/etc/init.d/dnsmasq systemd-stop-resolvconf + + +ExecReload=/bin/kill -HUP $MAINPID + +[Install] +WantedBy=multi-user.target diff --git a/src/agent_gsm.py b/src/agent_gsm.py index 911d668..e731699 100644 --- a/src/agent_gsm.py +++ b/src/agent_gsm.py @@ -533,9 +533,11 @@ if __name__ == '__main__': utils.log_error(f'Failed to obtain information about {BACKEND.instance}. Exiting.') exit(EXIT_ERROR) - if not BACKEND.online: - # Start own hotspot and API server - agent_point.start() + # if not BACKEND.online: + + # Start own hotspot and API server + agent_point.CACHE = CACHE + agent_point.start() # Cache phone information CACHE.put_phone(BACKEND.phone) diff --git a/src/agent_point.py b/src/agent_point.py old mode 100644 new mode 100755 index efe6996..f0f211d --- a/src/agent_point.py +++ b/src/agent_point.py @@ -1,54 +1,80 @@ #!/usr/bin/python3 -import PyAccessPoint import bottle import multiprocessing -from PyAccessPoint import pyaccesspoint +import time +import os +import utils_cache + class AccessPoint: active: bool = False - ap: pyaccesspoint.AccessPoint = None def __init__(self) -> None: pass def start(self): - if self.ap is not None: - return - - self.ap = pyaccesspoint.AccessPoint(ssid='agent_gsm', password='qwerty') - if not self.ap.start(): - raise RuntimeError(f'Failed to start WiFi access point.') + pass def stop(self): - if self.ap is None: - return - - if not self.ap.stop(): - raise RuntimeError(f'Failed to stop Wifi access point') - self.ap = None + pass ACCESS_POINT = AccessPoint() SERVER_PROCESS = None +RESPONSE_OK = {'status': 'ok'} +CACHE : utils_cache.InfoCache = None @bottle.route('/status') def web_status(): - return "OK" + print(f'Serving /status request...') + return RESPONSE_OK + +@bottle.route('/reboot') +def web_reboot(): + os.system('sudo reboot') + return RESPONSE_OK + +@bottle.route('/stop') +def web_reboot(): + os.system('sudo halt') + return RESPONSE_OK + +@bottle.route('/cache') +def web_list_cache(): + result = [] + if CACHE is None: + return result + + # Iterate cache and return available files list + for f in os.listdir(CACHE.dir): + result.append(f) + + return result + def web_process(): + print(f'Run web process...') bottle.run(host='0.0.0.0', port=8080) def start(): - global SERVER_PROCESS + global ACCESS_POINT, SERVER_PROCESS ACCESS_POINT.start() SERVER_PROCESS = multiprocessing.Process(target=web_process) + SERVER_PROCESS.start() def stop(): + global ACCESS_POINT, SERVER_PROCESS + ACCESS_POINT.stop() SERVER_PROCESS.kill() if __name__ == '__main__': + # Start test stuff start() + # Wait 120 seconds for tests + time.sleep(120.0) + + # Stop test stop() diff --git a/src/utils_cache.py b/src/utils_cache.py index a466838..cf80a56 100644 --- a/src/utils_cache.py +++ b/src/utils_cache.py @@ -19,8 +19,6 @@ class InfoCache: utils.log_error(str(e)) self.dir = None - - def is_active(self) -> bool: return self.dir is not None