1## @defgroup on-service-relay Dienst-Weiterleitungen
2# Beginn der Doku-Gruppe
5## für die Kompatibilität mit Firmware vor v0.5
6## falls mehr als ein GW-Dienst weitergereicht wird, wird dieser Port und die folgenden verwendet
7SERVICE_RELAY_LOCAL_RELAY_PORT_START=5100
10# Pruefung ob ein lokaler Port bereits fuer einen ugw-Dienst weitergeleitet wird
11_is_local_service_relay_port_unused() {
15 [ -n
"$collisions" ] && trap
"" EXIT &&
return 1
16 # keine Kollision entdeckt
21# Liefere den Port zurueck, der einer Dienst-Weiterleitung lokal zugewiesen wurde.
22# Falls noch kein Port definiert ist, dann waehle einen neuen Port.
23# Parameter: config_name
24pick_local_service_relay_port() {
25 trap
'error_trap pick_local_service_relay_port "$*"' EXIT
26 local service_name=
"$1"
29 # falls unbelegt: suche einen unbenutzten lokalen Port
30 if [ -z
"$port" ]; then
31 port=
"$SERVICE_RELAY_LOCAL_RELAY_PORT_START"
32 until _is_local_service_relay_port_unused
"$port";
do
41## @fn update_relay_firewall_rules
42## @brief Erstelle die Liste aller Firewall-Regeln fuer Service-Relay-Weiterleitungen neu.
43## @details Diese Funktion wird als Teil des Firewall-Reload-Prozess und nach Service-Relay-Aenderungen
45update_relay_firewall_rules() {
46 trap
'error_trap update_relay_firewall_rules "$*"' EXIT
52 local table=
"on_usergw_table"
53 local dnat_chain=
"on_service_relay_dnat"
55 main_ip=
$(get_main_ip)
56 # calculate the entries for the new rules
57 # We need to do this in advance - otherwise it could happen, that DNS problems could cause
58 # invalid (i.e. missing) firewall rules. Only if at least one valid rule is calculated,
59 # the rules are updated.
60 new_rules=
$(
for service in
$(
get_services | filter_relay_services);
do
61 is_service_relay_possible
"$service" ||
continue
67 # skip entries in case of broken DNS resolution
68 [ -z
"$target_ip" ] &&
continue
69 echo
"$host $port $protocol $local_port $target_ip"
71 #
do not apply changes,
if there are no valid rules
72 [ -z
"$new_rules" ] &&
return 0
74 # alte Regeln aus Chains löschen (siehe auch /usr/share/nftables.d/ fuer Definition der Chain)
75 nft flush chain inet
"$table" "$dnat_chain"
78 echo
"$new_rules" |
while read -r host port protocol local_port target_ip;
do
80 nft add rule inet
"$table" "$dnat_chain" ip daddr
"$main_ip" "$protocol" dport
"$local_port" counter dnat to
"${target_ip}:${port}"
82 nft add rule inet
"$table" "$dnat_chain" ip6 daddr
"$main_ip" "$protocol" dport
"$local_port" counter dnat to
"${target_ip}:${port}"
85 # Connection-Tracking-Tabelle flushen
86 # Sonst werden Aenderungen fuer bestehende Verbindungen nicht wirksam.
87 echo f >/proc/net/nf_conntrack
91_get_service_relay_olsr_announcement_prefix() {
92 trap
'error_trap _get_service_relay_olsr_announcement_prefix "$*"' EXIT
93 local service_name=
"$1"
100 main_ip=
$(get_main_ip)
103 service_type=
"${service_type#$RELAYABLE_SERVICE_PREFIX}"
106 port=
$(pick_local_service_relay_port
"$service_name")
108 # announce the service
109 echo
"${scheme}://${main_ip}:${port}|${protocol}|${service_type}"
113## @fn get_service_relay_olsr_announcement()
114## @brief Ermittle den oder die OLSR-Nameservice-Announcements, die zu dem Dienst gehoeren.
115get_service_relay_olsr_announcement() {
116 trap
'error_trap get_service_relay_olsr_announcement "$*"' EXIT
117 local service_name=
"$1"
118 local announce_unique
120 announce_unique=
$(_get_service_relay_olsr_announcement_prefix
"$service_name")
121 uci_prefix=
$(get_and_enable_olsrd_library_uci_prefix
"nameservice")
122 uci_get_list "${uci_prefix}.service" | awk
'{ if ($1 == "'"$announce_unique"'") print $0; }'
126## @fn announce_olsr_service_relay()
127## @brief Verkuende das lokale Relay eines öffentlichen Dienstes inkl. Geschwindigkeitsdaten via olsr nameservice.
128## @param service_name Name des zu veröffentlichenden Diensts
129## @attention Anschließend muss die uci-Sektion 'olsrd' committed werden.
130announce_olsr_service_relay() {
131 trap
'error_trap announce_olsr_service_relay "$*"' EXIT
132 local service_name=
"$1"
134 local service_details
135 service_unique=
$(_get_service_relay_olsr_announcement_prefix
"$service_name")
136 # das 'service_name'-Detail wird fuer die anschliessende Beraeumung (firewall-Regeln usw.) verwendet
137 # nur nicht-leere Attribute werden geschrieben
138 service_details=
$(
while read -r
key value;
do [ -z
"$value" ] &&
continue; echo
"$key:$value";
done <<EOF
145 # Zeilenumbrueche durch Leerzeichen ersetzen, abschliessendes Leerzeichen entfernen
146 service_details=
$(echo
"$service_details" | tr
'\n' ' ' | sed
's/ $//')
147 # loesche alte Dienst-Announcements mit demselben Prefix
151 uci_prefix=
$(get_and_enable_olsrd_library_uci_prefix
"nameservice")
152 # shellcheck disable=SC2034
153 get_service_relay_olsr_announcement
"$service_name" |
while read -r this_unique this_details;
do
154 # der Wert ist bereits korrekt - wir koennen abbrechen
155 [
"$this_details" =
"$service_details" ] &&
break
156 # der Wert ist falsch: loeschen und am Ende neu hinzufuegen
157 msg_debug "Deleting outdated service-relay announcement: $service_unique $this_details"
158 uci_delete_list "${uci_prefix}.service" "$service_unique $this_details"
160 # falls keine Treffer gibt, fuegen wir ein neues Announcement hinzu
161 if [ -z
"$(get_service_relay_olsr_announcement "$service_name
")" ]; then
162 msg_debug "Adding new service-relay announcement: $service_unique $service_details"
163 uci_add_list "${uci_prefix}.service" "$service_unique $service_details"
168## @fn get_olsr_relay_service_name_from_description()
169## @brief Ermittle den Dienstnamen, der zu einer olsr-Relay-Service-Definition gehoert.
170get_olsr_relay_service_name_from_description() {
171 trap
'error_trap get_olsr_relay_service_name_from_description "$*"' EXIT
172 local service_description=
"$1"
176 fields=
$(echo
"$service_description" | parse_olsr_service_descriptions)
177 port=
$(echo
"$fields" | cut -f 4)
178 service_type=
$(echo
"$fields" | cut -f 1)
183# olsr-Nameservice-Beschreibungen entfernen falls der dazugehoerige Dienst nicht mehr relay-tauglich ist
184deannounce_unused_olsr_service_relays() {
185 # wir erwarten einen ausführbaren Testnamen
186 local test_for_activity=
"$1"
187 local service_description
190 uci_prefix=
$(get_and_enable_olsrd_library_uci_prefix
"nameservice")
191 uci_get_list "${uci_prefix}.service" |
while read -r service_description;
do
192 # unbenutzte Eintraege entfernen
193 service_name=
$(get_olsr_relay_service_name_from_description
"$service_description")
194 # falls es den Dienst noch gibt: ist er immer noch aktiv?
195 [ -n
"$service_name" ] &&
"$test_for_activity" "$service_name" &&
continue
202## @fn is_service_relay_possible()
203## @brief Pruefe ob ein Relay-Dienst aktiviert (nicht "disabled") ist und ob das WAN-Routing korrekt ist.
204is_service_relay_possible() {
205 trap
'error_trap is_service_relay_possible "$*"' EXIT
206 local service_name=
"$1"
210 uci_is_true
"$disabled" && trap
"" EXIT &&
return 1
212 uci_is_false
"$wan_routing" && trap
"" EXIT &&
return 1
217## @fn update_service_relay_status()
218## @brief Pruefe regelmaessig, ob Weiterleitungen für alle bekannten durchgereichten Diensten existieren.
219## @details Fehlende Weiterleitungen oder olsr-Announcements werden angelegt.
221 trap
'error_trap update_service_relay_status "$*"' EXIT
225 for service_name in
$(
get_services | filter_relay_services);
do
226 # WAN-Routing pruefen und aktualisieren
229 is_service_relay_possible
"$service_name" ||
continue
230 announce_olsr_service_relay
"$service_name"
232 update_relay_firewall_rules
233 deannounce_unused_olsr_service_relays is_service_relay_possible
235 deannounce_unused_olsr_service_relays
false
241## @fn filter_relay_services()
242## @brief Filtere aus einer Reihe eingehender Dienste diejenigen heraus, die als Dienst-Relay fungieren.
243## @details Die Dienst-Namen werden über die Standardeingabe gelesen und an die Standardausgabe
244## weitergeleitet, falls es sich um einen Relay-Dienst handelt.
245filter_relay_services() {
247 while read -r service_name;
do
248 [ -z
"$(get_service_value "$service_name
" "local_relay_port
")" ] || echo
"$service_name"
252# Ende der Doku-Gruppe
msg_debug(message)
Debug-Meldungen ins syslog schreiben.
is_on_module_installed_and_enabled(module)
Pruefe ob ein Modul sowohl installiert, als auch aktiv ist.
set eu case $1 in on usergw on function update_on_usergw_status on function update_service_relay_status
is_ipv4(target)
Prüfe ob der übergebene Text eine IPv4-Adresse ist.
filter_routable_addresses()
Filtere aus einer Menge von Ziel-IPs diejenigen heraus, für die eine passende Routing-Regel existiert...
is_service_routed_via_wan(service_name)
Pruefe ob der Verkehr zum Anbieter des Diensts über ein WAN-Interface verlaufen würde.
set_service_value()
Setzen eines oder mehrerer Werte fuer einen Dienst. Je nach Schluesselname wird der Inhalt in die per...
get_services(service_type)
Liefere alle Dienste zurueck, die dem angegebenen Typ zugeordnet sind. Falls kein Typ angegben wird,...
get_service_value(key, default)
Auslesen eines Werts aus der Service-Datenbank.
filter_services_by_value(key, value)
uci_get_list(uci_path)
Liefere alle einzelnen Elemente einer UCI-Liste zurück.
uci_add_list(uci_path, new_item)
Füge einen neuen Wert zu einer UCI-Liste hinzu und achte dabei auf Einmaligkeit.
uci_delete_list(uci_path, value)
Lösche ein Element einer UCI-Liste.