1## @defgroup captive_portal Captive Portal
2## @brief Funktionen für den Umgang mit der Captive-Portal-Software für offene WLAN-Knoten
3# Beginn der Doku-Gruppe
7# shellcheck disable=SC2034
10## @var Quelldatei für Standardwerte des Hotspot-Pakets
11ON_CAPTIVE_PORTAL_DEFAULTS_FILE=/usr/share/opennet/captive-portal.defaults
14## @fn configure_free_network()
15## @brief Erzeuge das free-Netzwerk-Interface, falls es noch nicht existiert.
17 local uci_prefix=
"network.$NETWORK_FREE"
18 # es wurde bereits einmalig konfiguriert
19 if [ -z
"$(uci_get "$uci_prefix
")" ]; then
20 uci set
"${uci_prefix}=interface"
21 uci set
"${uci_prefix}.device=none"
22 uci set
"${uci_prefix}.proto=static"
23 uci set
"${uci_prefix}.ipaddr=$(get_on_captive_portal_default free_ipaddress)"
24 uci set
"${uci_prefix}.netmask=$(get_on_captive_portal_default free_netmask)"
25 uci set
"${uci_prefix}.auto=1"
29 uci_prefix=
$(find_first_uci_section
"dhcp" "dhcp" "interface=$NETWORK_FREE")
30 # beenden, falls vorhanden
31 if [ -z
"$uci_prefix" ]; then
32 # DHCP-Einstellungen fuer dieses Interface festlegen
33 uci_prefix=
"dhcp.$(uci add "dhcp
" "dhcp
")"
34 uci set
"${uci_prefix}.interface=$NETWORK_FREE"
35 uci set
"${uci_prefix}.start=10"
36 uci set
"${uci_prefix}.limit=240"
37 uci set
"${uci_prefix}.leasetime=30m"
43## @fn get_on_captive_portal_default()
44## @param key Name des Schlüssels
45## @brief Liefere einen der default-Werte der aktuellen Firmware zurück (Paket on-captive-portal).
46## @details Die default-Werte werden nicht von der Konfigurationsverwaltung uci verwaltet.
47## Somit sind nach jedem Upgrade imer die neuesten Standard-Werte verfügbar.
54## @fn captive_portal_has_devices()
55## @brief Prüfe, ob dem Captive Portal mindestens ein physisches Netzwerk-Gerät zugeordnet ist.
56## @details Sobald ein Netzwerk-Gerät konfiguriert ist, gilt der Captive-Portal-Dienst als aktiv.
57## Es werden sowohl nicht-wifi-, als auch wifi-Interfaces geprueft.
59 [ -n
"$(get_subdevices_of_interface "$NETWORK_FREE
")" ] &&
return 0
60 [ -n
"$(find_all_uci_sections wireless wifi-iface "network=$NETWORK_FREE
")" ] &&
return 0
61 trap
"" EXIT &&
return 1
65## @fn captive_portal_repair_empty_network_bridge()
66## @brief Reduziere Konstruktionen wie beispielsweise "bridge(None, wlan0)" zu "wlan0".
67## @details Brücken mit "none"-Elementen verwirren das nodogsplash-Start-Skript.
69 local uci_prefix=
"network.${NETWORK_FREE}"
70 local sub_device_count
71 if [
"$(uci_get "${uci_prefix}.type
")" =
"bridge" ] && [
"$(uci_get "${uci_prefix}.device
")" =
"none" ]; then
72 # verdaechtig: Bruecke mit "none"-Device
74 if [
"$sub_device_count" -eq
"1" ]; then
75 # wifi-Device is konfiguriert - Bruecke und "none" kann entfernt werden
79 # nichts ist konfiguriert - erstmal nur die Bruecke entfernen
91 disable_captive_portal
96change_captive_portal_wireless_disabled_state() {
99 find_all_uci_sections wireless wifi-iface
"network=$NETWORK_FREE" |
while read -r uci_prefix;
do
100 uci set
"${uci_prefix}.disabled=$state"
102 apply_changes wireless
106disable_captive_portal() {
107 trap
"error_trap disable_captive_portal" EXIT
108 msg_info "on-captive-portal: wifi-Interfaces abschalten"
109 # free-Interface ist aktiv - es gibt jedoch keinen Tunnel
110 change_captive_portal_wireless_disabled_state
"1"
114## @fn sync_captive_portal_state_with_mig_connections()
115## @brief Synchronisiere den Zustand (up/down) des free-Interface mit dem des VPN-Tunnel-Interface.
116## @details Diese Funktion wird nach Statusänderungen des VPN-Interface, sowie innerhalb eines
117## regelmäßigen cronjobs ausgeführt.
119 trap
"error_trap sync_captive_portal_state_with_mig_connections" EXIT
120 # eventuelle defekte/verwirrende Netzwerk-Konfiguration korrigieren
122 # Abbruch, falls keine Netzwerk-Interfaces zugeordnet wurden
129 # Pruefe ob mindestens eine IPv4-Adresse konfiguriert ist.
130 # (aus unbekannten Gruenden kann es vorkommen, dass die IPv4-Adresse spontan wegfaellt)
132 is_ipv4 "$address" && device_active=1 &&
break
136 if [ -n
"$device_active" ] && [ -z
"$mig_active" ]; then
137 disable_captive_portal
138 elif [ -n
"$mig_active" ]; then
139 [ -z
"$device_active" ] && ifup
"$NETWORK_FREE"
140 change_captive_portal_wireless_disabled_state
"0"
145## @fn is_captive_portal_running()
146## @brief Prüfe ob das Netzwerk-Interface des Captive-Portal aktiv ist.
149 trap
"" EXIT &&
return 1
153## @fn get_captive_portal_client_count()
154## @brief Ermittle die Anzahl der verbundenen Clients. Leere Ausgabe, falls keine aktiven
155## Interfaces vorhanden sind.
164 if assoclist=
$(iwinfo
"$device" assoclist 2>/dev/
null); then
165 this_count=
$(echo
"$assoclist" | awk
'{ if (($1 == "TX:") && ($(NF-1) >= 100)) count++; } END { print count; }')
167 # determine the number of valid arp cache items for this interface
168 this_count=
$(ip neighbor list dev
"$device" | grep -c
'REACHABLE$' ||
true)
170 count=
$((count + this_count))
173 # Liefere keine Ausgabe (leer), falls wir gar nichts zum Zaehlen gefunden haben.
174 # Dadurch kann das munin-Plugin (und andere Aufrufer) erkennen, dass das Portal nicht
176 [ -z
"$count" ] &&
return 0
181## @fn get_captive_portal_clients()
182## @brief Zeilenweise aller aktuellen Clients inklusive ihrer relevanten Kenngrößen.
183## @details In jeder Zeile wird ein Client beschrieben, wobei die folgenden Detailinformationen durch Tabulatoren getrennt sind:
186## * Zeitpunkt des Verbindungsaufbaus (seit epoch)
187## * Zeitpunkt der letzten Aktivität (seit epoch)
188## * Download-Verkehrsvolumen (kByte)
189## * Upload-Verkehrsvolumen (kByte)
190## Der Einfachheit halber nehmen wir an, dass alle DHCP-Clients auch Captive-Portal-Clients sind.
192 trap
'error_trap get_captive_portal_clients "'"$*"'"' EXIT
197 # Die "iwinfo assoclist" ist wahrscheinlich der einzige brauchbare Weg, um
198 # Verkehrsstatistiken zu beliebigen Peers zu erhalten. Wir müssen es also gar nicht erst
199 # mit anderen (nicht-wifi) Interfaces versuchen.
202 iwinfo wlan0 assoclist 2>/dev/
null ||
true;
done)
203 # erzwinge eine leere Zeile am Ende fuer die finale Ausgabe des letzten Clients
204 # shellcheck disable=SC2034
205 while read -r timestamp mac_address ip_address hostname misc;
do
206 # eine assoclist-Zeile sieht etwa folgendermassen aus:
207 # TX: 6.5 MBit/s, MCS 0, 20MHz 217 Pkts.
208 packets_rxtx=
$(echo
"$assoclist" | awk
'
209 BEGIN { my_mac = tolower("'"$mac_address"'"); }
211 if ($1 ~ /^(..:){5}..$/) current_mac = tolower($1);
212 if (($1 == "RX:") && (my_mac == current_mac)) my_rx=$(NF-1);
213 if (($1 == "TX:") && (my_mac == current_mac)) my_tx=$(NF-1);
215 END { OFS="\t"; print(my_rx, my_tx); }')
216 printf
'%s\t%s\t%s\t%s\n' "$ip_address" "$mac_address" "$timestamp" "$packets_rxtx"
217 done </var/dhcp.leases
220# Ende der Doku-Gruppe
set eu case $1 in on captive portal on function update_captive_portal_status
get_captive_portal_clients()
Zeilenweise aller aktuellen Clients inklusive ihrer relevanten Kenngrößen.
sync_captive_portal_state_with_mig_connections()
Synchronisiere den Zustand (up/down) des free-Interface mit dem des VPN-Tunnel-Interface.
captive_portal_has_devices()
Prüfe, ob dem Captive Portal mindestens ein physisches Netzwerk-Gerät zugeordnet ist.
configure_free_network()
Erzeuge das free-Netzwerk-Interface, falls es noch nicht existiert.
get_captive_portal_client_count()
Ermittle die Anzahl der verbundenen Clients. Leere Ausgabe, falls keine aktiven Interfaces vorhanden ...
captive_portal_repair_empty_network_bridge()
Reduziere Konstruktionen wie beispielsweise "bridge(None, wlan0)" zu "wlan0".
get_on_captive_portal_default(key)
Liefere einen der default-Werte der aktuellen Firmware zurück (Paket on-captive-portal).
is_captive_portal_running()
Prüfe ob das Netzwerk-Interface des Captive-Portal aktiv ist.
_get_file_dict_value(key)
Auslesen eines Werts aus einem Schlüssel/Wert-Eingabestrom.
msg_info(message)
Informationen und Fehlermeldungen ins syslog schreiben.
is_on_module_installed_and_enabled(module)
Pruefe ob ein Opennet-Modul sowohl installiert, als auch aktiviert ist.
get_subdevices_of_interface()
Ermittle die physischen Netzwerk-Geräte (bis auf wifi), die zu einem logischen Netzwerk-Interface geh...
get_current_addresses_of_network()
Liefere die IP-Adressen eines logischen Interface inkl. Praefix-Laenge (z.B. 172.16....
is_interface_up(interface)
Prüfe ob ein logisches Netzwerk-Interface aktiv ist.
get_active_mig_connections()
Liefere die aktiven VPN-Verbindungen (mit Mesh-Internet-Gateways) zurück.
is_ipv4(target)
Prüfe ob der übergebene Text eine IPv4-Adresse ist.
uci_delete(uci_path)
Lösche ein UCI-Element.
set eu grep root::etc shadow exit if command v chpasswd dev null