Opennet Firmware
olsr.sh
gehe zur Dokumentation dieser Datei
1## @defgroup olsr OLSR
2## @brief Konfiguration und Abfrage des OLSR-Diensts. Einlesen von Diensten announciert via olsrd-nameservice.
3# Beginn der Doku-Gruppe
4## @{
5
6# shellcheck disable=SC2034
7OLSR_NAMESERVICE_SERVICE_TRIGGER=/usr/sbin/on_nameservice_trigger
8SERVICES_FILE=/var/run/services_olsr
9# shellcheck disable=SC2034
10OLSR_HTTP_PORT=8080
11OLSR_UPDATE_LOCK_FILE=/var/run/on-update-olsr-interfaces.lock
13
14# uebertrage die Netzwerke, die derzeit der Zone "opennet" zugeordnet sind, in die olsr-Konfiguration
15# Anschliessend wird olsr und die firewall neugestartet.
16# Dieses Skript sollte via hotplug bei Aenderungen der Netzwerkkonfiguration ausgefuehrt werden.
17# Fuer jedes Interface wird eine separate UCI-Sektion angelegt.
18update_olsr_interfaces() {
19 trap 'error_trap update_olsr_interfaces "$*"' EXIT
20 local uci_prefix
21 local interfaces
22 local current
23
24 interfaces_log="$(get_zone_log_interfaces "$ZONE_MESH")"
25 interfaces_phy="$(get_zone_raw_devices "$ZONE_MESH")"
26
27 # Das uci Interface zu olsrd benötigt folgenden Input:
28 # - log. Interfaces, welches mind ein phys. Interface enthalten
29 # - phys. Interfaces, welche keinem log. Interface zugeordnet sind
30 interfaces_olsr="$interfaces_phy"
31 for interface_log in $interfaces_log; do
32 subinterface="$(get_device_of_interface $interface_log)"
33 # Fuege nur log. Interfaces hinzu, welche phys. Interfaces enthalten
34 if [ -n "$subinterface" ]; then
35 interfaces_olsr=$(echo -e "$interfaces_olsr\n$interface_log")
36 fi
37 done
38
39 for uci_prefix in $(find_all_uci_sections "olsrd" "Interface"); do
40 current=$(uci_get "${uci_prefix}.interface")
41 if echo "$interfaces_olsr" | grep -qFw "$current"; then
42 # OLSR fuer das Interface aktivieren
43 uci set "${uci_prefix}.ignore=0"
44 else
45 # Interfaces entfernen, die nicht mehr in der on-Zone sind
46 uci_delete "$uci_prefix"
47 fi
48 done
49 # alle fehlenden Interfaces neu anlegen
50 for current in $interfaces_olsr; do
51 uci_prefix=$(find_first_uci_section "olsrd" "Interface" "interface=$current")
52 # existiert es bereits? Dann wurde es oben konfiguriert.
53 [ -n "$uci_prefix" ] && continue
54 uci_prefix="olsrd.$(uci add olsrd Interface)"
55 uci set "${uci_prefix}.interface=$current"
56 uci set "${uci_prefix}.ignore=0"
57 done
58 # prevent recursive trigger chaining
59 if acquire_lock "$OLSR_UPDATE_LOCK_FILE" 5 5; then
61 update_opennet_zone_masquerading
62 apply_changes olsrd
63 rm -f "$OLSR_UPDATE_LOCK_FILE"
64 fi
65}
66
67
68# Pruefe das angegebene olsrd-Plugin aktiv ist und aktiviere es, falls dies nicht der Fall sein sollte.
69# Das Ergebnis ist die uci-Sektion (z.B. "olsrd.@LoadPlugin[1]") als String.
70get_and_enable_olsrd_library_uci_prefix() {
71 trap 'error_trap get_and_enable_olsrd_library_uci_prefix "$*"' EXIT
72 local lib_file
73 local uci_prefix=
74 local library="olsrd_$1"
75 local current
76 current=$(for uci_prefix in $(find_all_uci_sections olsrd LoadPlugin); do
77 # die Bibliothek beginnt mit dem Namen - danach folgt die genaue Versionsnummer
78 uci_get "${uci_prefix}.library" | grep -q "^$library"'\.so' && echo "$uci_prefix"
79 true
80 done | tail -1)
81 if [ -n "$current" ]; then
82 uci_prefix=$(echo "$current" | cut -f 1 -d = | sed 's/\.library$//')
83 else
84 lib_file=$(find /usr/lib -type f -name "${library}.*")
85 if [ -z "$lib_file" ]; then
86 msg_error "Failed to find olsrd '$library' plugin. Some Opennet services will fail."
87 trap "" EXIT && return 1
88 fi
89 uci_prefix="olsrd.$(uci add olsrd LoadPlugin)"
90 uci set "${uci_prefix}.library=$(basename "$lib_file")"
91 fi
92 # Plugin aktivieren; Praefix ausgeben
93 if [ -n "$uci_prefix" ]; then
94 # moeglicherweise vorhandenen 'ignore'-Parameter abschalten
95 uci_is_true "$(uci_get "${uci_prefix}.ignore" 0)" && uci set "${uci_prefix}.ignore=0"
96 echo "$uci_prefix"
97 fi
98 return 0
99}
100
101
102# Setze die Einstellung MainIP in der olsr-Konfiguration:
103# Quelle 1: der erste Parameter
104# Quelle 2: on-core.settings.on_id
105# Quelle 3: die vorkonfigurierte Standard-IP
106# Anschliessend ist "apply_changes olsrd" erforderlich.
107olsr_set_main_ip() {
108 trap 'error_trap olsr_set_main_ip "$*"' EXIT
109 # Auslesen der aktuellen, bzw. der Standard-IP
110 local main_ip
111 if [ $# -eq 1 ]; then
112 main_ip="$1"
113 else
114 main_ip=$(get_main_ip)
115 fi
116
117 # die Main-IP ist die erste IP dieses Geraets
118 uci set "olsrd.@olsrd[0].MainIp=$main_ip"
119}
120
121
122# Ermittle welche olsr-Module konfiguriert sind, ohne dass die Library vorhanden ist.
123# Deaktiviere diese Module - fuer ein sauberes boot-Log.
124disable_missing_olsr_modules() {
125 trap 'error_trap disable_missing_olsr_modules "$*"' EXIT
126 local libpath=/usr/lib
127 local libfile
128 local uci_prefix
129 local ignore
130 for uci_prefix in $(find_all_uci_sections "olsrd" "LoadPlugin"); do
131 libfile=$(uci_get "${uci_prefix}.library")
132 ignore=$(uci_get "${uci_prefix}.ignore")
133 [ -n "$ignore" ] && uci_is_true "$ignore" && continue
134 if [ ! -e "$libpath/$libfile" ]; then
135 msg_info "Disabling missing olsr module '$libfile'"
136 uci set "${uci_prefix}.ignore=1"
137 fi
138 done
139 apply_changes olsrd
140}
141
142
143## @fn olsr_sync_routing_tables()
144## @brief Synchronisiere die olsrd-Routingtabellen-Konfiguration mit den iproute-Routingtabellennummern.
145## @details Im Konfliktfall wird die olsrd-Konfiguration an die iproute-Konfiguration angepasst.
147 trap 'error_trap olsr_sync_routing_tables "$*"' EXIT
148 local olsr_name
149 local iproute_name
150 local olsr_id
151 local iproute_id
152 while read -r olsr_name iproute_name; do
153 olsr_id=$(uci_get "olsrd.@olsrd[0].$olsr_name")
154 iproute_id=$(get_routing_table_id "$iproute_name")
155 # beide sind gesetzt und identisch? Alles ok ...
156 [ -n "$olsr_id" ] && [ "$olsr_id" = "$iproute_id" ] && continue
157 # eventuell Tabelle erzeugen, falls sie noch nicht existiert
158 [ -z "$iproute_id" ] && iproute_id=$(add_routing_table "$iproute_name")
159 # olsr passt sich im Zweifel der iproute-Nummer an
160 [ "$olsr_id" = "$iproute_id" ] || uci set "olsrd.@olsrd[0].$olsr_name=$iproute_id"
161 done << EOF
162RtTable $ROUTING_TABLE_MESH
163RtTableDefault $ROUTING_TABLE_MESH_DEFAULT
164EOF
165 apply_changes olsrd
166}
167
168
169# Einlesen eines olsrd-Nameservice-Service.
170# Details zum Eingabe- und Ausgabeformat: siehe "get_olsr_services".
171parse_olsr_service_descriptions() {
172 awk -f /usr/lib/opennet/olsr_parse_service_descriptions.awk
173}
174
175
176# Parse die olsr-Service-Datei
177# Die Service-Datei enthaelt Zeilen streng definierter Form (durchgesetzt vom nameservice-Plugin).
178# Beispielhafte Eintraege:
179# http://192.168.0.15:8080|tcp|ugw upload:3 download:490 ping:108 #192.168.2.15
180# dns://192.168.10.4:53|udp|dns #192.168.10.4
181# Parameter: service-Type (z.B. "gw", "dns", "ntp", "mesh")
182# Ergebnis (tab-separiert):
183# SERVICE SCHEME IP PORT PROTO PATH DETAILS
184# Im Fall von "http://192.168.0.15:8080|tcp|ugw upload:3 download:490 ping:108" entspricht dies:
185# ugw http 192.168.0.15 8080 tcp / upload:3 download:490 ping:108
186# shellcheck disable=SC2120
187get_olsr_services() {
188 trap 'error_trap get_olsr_services "$*"' EXIT
189 local wanted_type="${1:-}"
190 local filter_service
191 [ ! -e "$SERVICES_FILE" ] && msg_debug "no olsr-services file found: $SERVICES_FILE" && return 0
192 sort "$SERVICES_FILE" | uniq | \
193 parse_olsr_service_descriptions | \
194 # filtere die Ergebnisse nach einem Service-Typ, falls selbiger als erster Parameter angegeben wurde
195 awk '{ if (("'"$wanted_type"'" == "") || ("'"$wanted_type"'" == $1)) print $0; }'
196 return 0
197}
198
199
200## @fn update_olsr_services()
201## @brief Verarbeite die aktuelle Dienst-Liste aus dem olsrd-nameservice-Plugin.
202## @details Veraltete Dienste werden entfernt. Eventuelle Änderungen der DNS- und NTP-Serverliste
203## werden angewandt.
205 trap 'error_trap update_olsr_services "$*"' EXIT
206 local scheme
207 local ip
208 local port
209 local path
210 local proto
211 local service
212 local details
213 local olsr_services
214 # aktuell verbreitete Dienste benachrichtigen
215 # shellcheck disable=SC2119
216 olsr_services=$(get_olsr_services)
217 # leere Liste? Keine Verbindung mit der Wolke? Keine Aktualisierung, keine Beraeumung ...
218 [ -z "$olsr_services" ] && return
219 echo "$olsr_services" | notify_services "olsr" >/dev/null
220 # aktualisiere DNS- und NTP-Dienste
221 apply_changes on-core
222}
223
224
225## @fn remove_old_olsr_services()
226## @brief Entferne OLSR-Dienste, deren Einträge veraltet sind.
227## @details Diese Funktion sollte etwa stündlich ausgeführt werden.
229 local service_name
230 local timestamp
231 local min_timestamp
232 min_timestamp=$(($(get_uptime_minutes) - $(get_on_core_default "olsr_service_expire_minutes")))
233 # veraltete Dienste entfernen (nur falls die uptime groesser ist als die Verfallszeit)
234 if [ "$min_timestamp" -gt 0 ]; then
235 get_services | filter_services_by_value "source" "olsr" | pipe_service_attribute "timestamp" "0" \
236 | while read -r service_name timestamp; do
237 # der Service ist zu lange nicht aktualisiert worden
238 if [ -z "$timestamp" ] || [ "$timestamp" -lt "$min_timestamp" ]; then
239 delete_service "$service_name"
240 fi
241 done
242 fi
243 # aktualisiere DNS- und NTP-Dienste
244 apply_changes on-core
245}
246
247
248## @fn request_olsrd_txtinfo()
249## @brief Sende eine Anfrage an das txtinfo-Interface von olsrd
250## @param request Der zu sende Request-Pfad (z.B. "lin" oder "nei")
251## @details Bei Problemen mit dem Verbindungsaufbau erscheint ein Hinweis im syslog.
253 local request="$1"
254 if ! echo "/$request" | timeout 4 nc 127.0.0.1 2006 2>/dev/null; then
255 # keine Fehlermeldung, falls wir uns gerade noch im Boot-Prozess befinden
256 # Dies tritt besonders nach einem Reboot via Web-Interface auf, da dann die Status-Seite
257 # noch während des Hochfahrens abgerufen wird.
258 [ "$(get_uptime_seconds)" -lt 180 ] || msg_error "request_olsrd_txtinfo: olsrd is not responding"
259 fi | if [ "$request" = "con" ] || [ "$request" = "all" ]; then
260 # die Konfiguration und "all" sind ein unklares Format (fuer Menschen)
261 cat
262 else
263 # alle nicht-Daten-Zeilen entfernen:
264 # * loesche alle Zeilen, bis die erste Zeile beginnend mit "Table: " erkannt wird
265 # * loesche die darauffolgende Zeile, sowie alle leeren Zeilen
266 awk 'BEGIN { in_body=0;}
267 { if (/^Table: /) { in_body=1; } else if (in_body == 1) { print; }}' \
268 | sed '1d; /^$/d'
269 fi
270}
271
272# Ende der Doku-Gruppe
273## @}
msg_debug(message)
Debug-Meldungen ins syslog schreiben.
Definition: core.sh:9
msg_error(message)
Die Fehlermeldungen werden in die Standard-Fehlerausgabe und ins syslog geschrieben.
Definition: core.sh:22
msg_info(message)
Informationen und Fehlermeldungen ins syslog schreiben.
Definition: core.sh:15
done
Definition: core.sh:85
remove_old_olsr_services()
Entferne OLSR-Dienste, deren Einträge veraltet sind.
Definition: olsr.sh:16
update_olsr_services()
Verarbeite die aktuelle Dienst-Liste aus dem olsrd-nameservice-Plugin.
Definition: olsr.sh:12
olsr_sync_routing_tables()
Synchronisiere die olsrd-Routingtabellen-Konfiguration mit den iproute-Routingtabellennummern.
Definition: olsr.sh:7
request_olsrd_txtinfo(request)
Sende eine Anfrage an das txtinfo-Interface von olsrd.
Definition: olsr.sh:21
add_routing_table(table_name)
Erstelle einen neuen Routing-Tabellen-Eintrag.
Definition: routing.sh:55
initialize_olsrd_policy_routing()
Policy-Routing-Initialisierung nach dem System-Boot und nach Interface-Hotplug-Ereignissen.
Definition: routing.sh:43
get_routing_table_id(table_name)
Ermittle die Nummer der namentlich gegebenen Routing-Tabelle.
Definition: routing.sh:48
pipe_service_attribute(key, default)
Liefere zu einer Reihe von Diensten ein gewähltes Attribut dieser Dienste zurück.
Definition: services.sh:63
get_services(service_type)
Liefere alle Dienste zurueck, die dem angegebenen Typ zugeordnet sind. Falls kein Typ angegben wird,...
Definition: services.sh:68
notify_services(source)
Siehe "notify_service" - jedoch effizienter im Umgang mit einer großen Anzahl von Diensten.
Definition: services.sh:23
filter_services_by_value(key, value)
Definition: services.sh:74
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
set eu on function print_services services log for dir in etc on services d var on services volatile d
Definition: services:13