Opennet Firmware
on-captive-portal.sh
gehe zur Dokumentation dieser Datei
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
4## @{
5
6
7# shellcheck disable=SC2034
8ZONE_FREE=on_free
9NETWORK_FREE=on_free
10## @var Quelldatei für Standardwerte des Hotspot-Pakets
11ON_CAPTIVE_PORTAL_DEFAULTS_FILE=/usr/share/opennet/captive-portal.defaults
12
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"
26 apply_changes network
27 fi
28 # konfiguriere DHCP
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"
38 apply_changes dhcp
39 fi
40}
41
42
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.
49 local key="$1"
50 _get_file_dict_value "$key" "$ON_CAPTIVE_PORTAL_DEFAULTS_FILE"
51}
52
53
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
62}
63
64
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
73 sub_device_count=$(get_subdevices_of_interface "$NETWORK_FREE" | wc -w)
74 if [ "$sub_device_count" -eq "1" ]; then
75 # wifi-Device is konfiguriert - Bruecke und "none" kann entfernt werden
76 uci_delete "${uci_prefix}.type"
77 uci_delete "${uci_prefix}.device"
78 else
79 # nichts ist konfiguriert - erstmal nur die Bruecke entfernen
80 uci_delete "${uci_prefix}.type"
81 fi
82 apply_changes network
83 fi
84}
85
86
88 if is_on_module_installed_and_enabled "on-captive-portal"; then
90 else
91 disable_captive_portal
92 fi
93}
94
95
96change_captive_portal_wireless_disabled_state() {
97 local state="$1"
98 local uci_prefix
99 find_all_uci_sections wireless wifi-iface "network=$NETWORK_FREE" | while read -r uci_prefix; do
100 uci set "${uci_prefix}.disabled=$state"
101 done
102 apply_changes wireless
103}
104
105
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"
111}
112
113
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
124 local mig_active
125 local address
126 local device_active=
127 mig_active=$(get_active_mig_connections)
128 if is_interface_up "$NETWORK_FREE"; then
129 # Pruefe ob mindestens eine IPv4-Adresse konfiguriert ist.
130 # (aus unbekannten Gruenden kann es vorkommen, dass die IPv4-Adresse spontan wegfaellt)
131 for address in $(get_current_addresses_of_network "$NETWORK_FREE"); do
132 is_ipv4 "$address" && device_active=1 && break
133 true
134 done
135 fi
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"
141 fi
142}
143
144
145## @fn is_captive_portal_running()
146## @brief Prüfe ob das Netzwerk-Interface des Captive-Portal aktiv ist.
148 is_interface_up "$NETWORK_FREE" && return 0
149 trap "" EXIT && return 1
150}
151
152
153## @fn get_captive_portal_client_count()
154## @brief Ermittle die Anzahl der verbundenen Clients. Leere Ausgabe, falls keine aktiven
155## Interfaces vorhanden sind.
157 local count=
158 local this_count
159 local assoclist
160 local device
162 count=0
163 for device in $(get_subdevices_of_interface "$NETWORK_FREE"); do
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; }')
166 else
167 # determine the number of valid arp cache items for this interface
168 this_count=$(ip neighbor list dev "$device" | grep -c 'REACHABLE$' || true)
169 fi
170 count=$((count + this_count))
171 done
172 fi
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
175 # laeuft.
176 [ -z "$count" ] && return 0
177 echo -n "$count"
178}
179
180
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:
184## * IP-Adresse
185## * MAC-Adresse
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
193 local ip_address
194 local mac_address
195 local timestamp
196 local packets_rxtx
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.
200 local assoclist
201 assoclist=$(for device in $(get_subdevices_of_interface "$NETWORK_FREE"); do \
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"'"); }
210 {
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);
214 }
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
218}
219
220# Ende der Doku-Gruppe
221## @}
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.
Definition: core.sh:85
key
Definition: core.sh:85
msg_info(message)
Informationen und Fehlermeldungen ins syslog schreiben.
Definition: core.sh:15
done
Definition: core.sh:85
is_on_module_installed_and_enabled(module)
Pruefe ob ein Opennet-Modul sowohl installiert, als auch aktiviert ist.
Definition: modules.sh:9
get_subdevices_of_interface()
Ermittle die physischen Netzwerk-Geräte (bis auf wifi), die zu einem logischen Netzwerk-Interface geh...
Definition: network.sh:43
get_current_addresses_of_network()
Liefere die IP-Adressen eines logischen Interface inkl. Praefix-Laenge (z.B. 172.16....
Definition: network.sh:19
is_interface_up(interface)
Prüfe ob ein logisches Netzwerk-Interface aktiv ist.
Definition: network.sh:73
get_active_mig_connections()
Liefere die aktiven VPN-Verbindungen (mit Mesh-Internet-Gateways) zurück.
Definition: on-openvpn.sh:34
is_ipv4(target)
Prüfe ob der übergebene Text eine IPv4-Adresse ist.
Definition: routing.sh:8
uci_delete(uci_path)
Lösche ein UCI-Element.
Definition: uci.sh:46
set eu grep root::etc shadow exit if command v chpasswd dev null
Definition: on-password:12