1## @defgroup modules Module 
    2## @brief Verwaltung der Opennet-Module für verschiedene Funktionen/Rollen 
    3# Beginn der Doku-Gruppe 
    6# Basis-URL für Opennet-Paketinstallationen 
    7ON_OPKG_REPOSITORY_URL_PREFIX=
"https://downloads.opennet-initiative.de/openwrt" 
    8# temporäre Datei für Installation von Opennet-Paketen 
    9ON_OPKG_CONF_PATH=
"${IPKG_INSTROOT:-}/tmp/opkg-opennet.conf" 
   10# shellcheck disable=SC2034 
   11DEFAULT_MODULES_ENABLED=
"on-olsr2" 
   14# Erzeuge die uci-Sektion "on-core.modules" und aktiviere Standard-Module.
 
   15_prepare_on_modules() {
 
   16    [ -n 
"$(uci_get "on-core.modules
")" ] && 
return 
   17    uci set 
"on-core.modules=modules" 
   21## @fn is_on_module_installed_and_enabled() 
   22## @brief Pruefe ob ein Opennet-Modul sowohl installiert, als auch aktiviert ist. 
   23## @param module Name des Opennet-Paketes (siehe 'get_on_modules'). 
   24## @details Die Aktivierung eines Modules wird anhand der uci-Einstellung "${module}.settings.enabled" geprueft.
 
   25##   Der Standardwert ist "false" (ausgeschaltet).
 
   27    trap 
'error_trap is_on_module_installed_and_enabled "$*"' EXIT
 
   31    trap 
"" EXIT && 
return 1
 
   35_is_on_module_enabled() {
 
   39    trap 
"" EXIT && 
return 1
 
   43## @fn is_on_module_installed() 
   44## @brief Pruefe ob ein Opennet-Modul installiert ist. 
   45## @param module Name des Opennet-Paketes (siehe 'get_on_modules'). 
   50    trap 
"" EXIT && 
return 1
 
   54## @fn enable_on_module() 
   55## @brief Aktiviere ein Opennet-Modul 
   56## @param module Name des Opennet-Paketes (siehe 'get_on_modules'). 
   58    trap 
'error_trap enable_on_module "$*"' EXIT
 
   64    apply_changes 
"on-core" "$module" 
   68## @fn disable_on_module() 
   69## @brief Deaktiviere ein Opennet-Modul 
   70## @param module Name des Opennet-Paketes (siehe 'get_on_modules'). 
   72    trap 
'error_trap disable_on_module "$*"' EXIT
 
   75    _is_on_module_enabled 
"$module" || 
return 0
 
   77    apply_changes 
"on-core" "$module" 
   81## @fn warn_if_unknown_module() 
   82## @brief Gib eine Warnung aus, falls der angegebene Modul-Name unbekannt ist. 
   83## @param module Name des Opennet-Paketes (siehe 'get_on_modules'). 
   84## @details Das Ergebnis der Prüfung ist nur für Warnmeldungen geeignet, da es im Laufe der Zeit 
   85##          Veränderungen in der Liste der bekannten Module geben kann. 
   89    echo >&2 
"The opennet module name '$module' is unknown - probably misspelled?" 
   90    echo >&2 
"The following module names are known: $(get_on_modules | xargs echo)" 
   94## @fn warn_if_not_installed_module() 
   95## @brief Gib eine Warnung aus, falls das Opennet-Module nicht installiert ist. 
   96## @param module Name des Opennet-Paketes (siehe 'get_on_modules'). 
  100    echo >&2 
"The opennet module name '$module' is not installed - maybe you want to install it?" 
  104## @fn get_on_modules() 
  105## @brief Liefere die Namen aller bekannten Opennet-Module zeilenweise getrennt zurück. 
  106## @details Die Liste kann in der Datei ON_CORE_DEFAULTS_FILE angepasst werden. 
  108    # zeilenweise splitten (wir erwarten nur kleine Buchstaben und Zahlen im Namen) 
  109    get_on_core_default 
"on_modules" | sed 
's/[^a-z0-9-]/\n/g' | grep -v 
"^$" || 
true 
  113## @fn get_not_installed_on_modules() 
  114## @brief Ermittle diejenigen Module, die aktuell nicht installiert sind. 
  123## @fn was_on_module_installed_before() 
  124## @brief Prüfe ob ein Modul "früher" (vor der letzten manuellen Änderung durch den Benutzer) installiert war.
 
  125## @details Diese Prüfung ist hilfreich für die Auswahl von nachträglich zu installierenden Paketen. 
  126## @param module Name des Opennet-Paketes (siehe 'get_on_modules'). 
  130    trap 
"" EXIT && 
return 1
 
  134## @fn get_missing_modules() 
  135## @brief Ermittle diejenigen Module, die vor dem letzten Upgrade installiert waren. 
  147## @fn install_from_opennet_repository() 
  148## @param packages Ein oder mehrere zu installierende Software-Pakete 
  149## @returns Eventuelle Fehlermeldungen werden auf die Standardausgabe geschrieben. Der Exitcode ist immer Null. 
  150## @brief Installiere ein Paket aus den Opennet-Repositories. 
  151## @details Für die Installation von Opennet-relevanten Paketen wird eine separate opkg.conf-Datei verwendet. 
  152##   Alle nicht-opennet-relevanten Pakete sollten - wie gewohnt - aus den openwrt-Repositories heraus installiert 
  153##   werden, da deren Paket-Liste umfassender ist. 
  154##   Die opkg.conf wird im tmpfs erzeugt, falls sie noch nicht vorhanden ist. Eventuelle manuelle Nachkorrekturen 
  155##   bleiben also bis zum nächsten Reboot erhalten. 
  157    trap 
'error_trap install_from_opennet_repository "$*"' EXIT
 
  159    local not_installed_packages
 
  160    not_installed_packages=$(get_not_installed_on_modules)
 
  161    run_opennet_opkg "update" && run_opennet_opkg "install" "$
@" 
  162    for package in "$
@"; do 
  163        if get_on_modules | grep -qwF "$package"; then
 
  164            # Eventuell schlug die Installation fehl? 
  166            # Falls es ein opennet-Modul ist, dann aktiviere es automatisch nach der Installation. 
  167            # Dies dürfte für den Nutzer am wenigsten überraschend sein. 
  168            # Wichtig: "enable" in einem neuen Skript-Kontext ausführen, damit sichergestellt ist,
 
  169            #          dass die "apply_changes"-Aktion mit den eventuell neuen Funktionen
 
  170            #          ausgeführt werden kann. 
  174    # wir wollen auch indirekt installierte Pakete aktivieren (z.B. on-openvpn via on-captive-portal) 
  175    for package in $not_installed_packages; 
do 
  176        # unveraendert nicht installiert? Ignorieren ... 
  180    # anschließend speichern wir den aktuellen Zustand, falls _alle_ Pakete installiert wurden 
  181    for package in "$
@"; do 
  182        # Paket fehlt? aktuelle Liste nicht speichern, sondern einfach abbrechen 
  183        is_package_installed "$package" || return 0
 
  189## @fn remove_opennet_modules()
 
  190## @param module Name der oder des zu entfernenden Modules
 
  191remove_opennet_modules() {
 
  192    # "--force-remove" ist für on-monitoring notwendig, da sonst xinetd wegen einer Änderung
 
  193    # /etc/xinet.d/munin nicht entfernt wird
 
  194    run_opennet_opkg --autoremove --force-remove remove "$
@" 
  199## @fn redirect_to_opkg_opennet_logfile() 
  200## @brief Führe die gegebene Aktion aus und lenke ihre Ausgabe in die opennet-opkg-Logdatei um. 
  201## @details Als irrelevant bekannte Meldungen werden herausgefiltert. 
  202redirect_to_opkg_opennet_logfile() { 
  204    log_file=$(get_custom_log_filename "opkg_opennet")
 
  206        | grep -vE 'resolve_conffiles: Existing conffile /etc/config/(openvpn|olsrd2) is different from the conffile in the new package\. The new conffile will be placed at /etc/config/(openvpn|olsrd2)-opkg\.' \ 
  207        | grep -v '^Collected errors:$' >>"$log_file"
 
  211# Ausführung eines opkg-Kommnados mit der opennet-Repository-Konfiguration und minimaler Ausgabe (nur Fehler) auf stdout.
 
  213    trap 'error_trap run_opennet_opkg "$*"' EXIT
 
  214    # erzeuge Konfiguration, falls sie noch nicht vorhanden ist
 
  215    [ -e "$ON_OPKG_CONF_PATH" ] || generate_opennet_opkg_config >"$ON_OPKG_CONF_PATH"
 
  216    # Vor der opkg-Ausführung müssen wir das Verzeichnis /etc/opkg verdecken, da opkg fehlerhafterweise
 
  217    # auch bei Verwendung von "--conf" die üblichen Orte nach Konfigurationsdateien durchsucht.
 
  218    # TODO: opkg-Bug upstream berichten
 
  219    mount -t tmpfs -o size=32k tmpfs /etc/opkg
 
  220    # opkg ausfuehren und dabei die angegebene Fehlermeldung ignorieren (typisch fuer Paket-Installation nach Upgrade)
 
  221    opkg --verbosity=1 --conf "$ON_OPKG_CONF_PATH" "$
@" || true 
  226## @fn save_on_modules_list() 
  227## @brief Speichere die aktuelle Liste der installierten opennet-Module in der uci-Konfiguration. 
  228## @details Nach einer Aktualisierung ermöglicht diese Sicherung die Nachinstallation fehlender Pakete. 
  229save_on_modules_list() { 
  232    [ -z "$(uci_get "on-core.modules")" ] && uci set "on-core.modules=modules"
 
  233    for modname in $(get_on_modules); 
do 
  238    apply_changes on-core
 
  242## @fn clear_cache_opennet_opkg() 
  243## @brief Lösche die eventuell vorhandene opennet-opkg-Konfiguration (z.B. nach einem Update). 
  245    rm -f 
"$ON_OPKG_CONF_PATH" 
  249## @fn get_default_opennet_opkg_repository_base_url() 
  250## @brief Ermittle die automatisch ermittelte URL für die Nachinstallation von Paketen. 
  251## @returns Liefert die Basis-URL zurueck. Anzuhängen sind im Anschluss z.B. /packages/${arch_cpu_type} oder /targets/${arch}/generic/packages 
  253    trap 
'error_trap get_default_opennet_opkg_repository_base_url "$*"' EXIT
 
  254    # ermittle die Firmware-Repository-URL 
  255    local firmware_version
 
  256    firmware_version=
$(get_on_firmware_version)
 
  257    # leere Versionsnummer? Damit können wir nichts anfangen. 
  258    [ -z 
"$firmware_version" ] && 
msg_error "Failed to retrieve opennet firmware version for opkg repository URL" && 
return 0
 
  259    # snapshots erkennen wir aktuell daran, dass auch Buchstaben in der Versionsnummer vorkommen 
  261    if echo 
"$firmware_version" | grep -q 
"[a-zA-Z]"; then
 
  262        # ein Buchstabe wurde entdeckt: unstable 
  263        version_path=
"testing/$firmware_version" 
  265        # kein Buchstabe wurde entdeckt: stable 
  266        # wir schneiden alles ab dem ersten Bindestrich ab 
  267        version_path=
"stable/$(echo "$firmware_version
" | cut -f 1 -d -)" 
  269    echo 
"$ON_OPKG_REPOSITORY_URL_PREFIX/$version_path" 
  273## @fn get_configured_opennet_opkg_repository_base_url() 
  274## @brief Ermittle die aktuell konfigurierte Repository-URL. 
  278    url=
$(uci_get 
"on-core.modules.repository_url")
 
  279    if [ -n 
"$url" ]; then
 
  287## @fn set_configured_opennet_opkg_repository_url() 
  288## @param repo_url Die neue Repository-URL (bis einschliesslich "/packages").
 
  289## @brief Ändere die aktuell konfigurierte Repository-URL. 
  290## @details Die URL wird via uci gespeichert. Falls sie identisch mit der Standard-URL ist, wird die Einstellung gelöscht. 
  294    if [ -z 
"$repo_url" ] || [ 
"$repo_url" = 
"$(get_default_opennet_opkg_repository_base_url "opennet
")" ]; then
 
  295        # Standard-Wert: loeschen 
  298        uci set 
"on-core.modules.repository_url=$repo_url" 
  304## @fn generate_opennet_opkg_config() 
  305## @brief Liefere den Inhalt einer opkg.conf für das Opennet-Paket-Repository zurück. 
  306## @details Die aktuelle Version wird aus dem openwrt-Versionsstring gelesen. 
  308    trap 
'error_trap generate_opennet_opkg_config "$*"' EXIT
 
  309    # schreibe den Inahlt der neuen OPKG-Konfiguration 
  312    echo 
"lists_dir ext /var/opkg-lists-opennet" 
  313    echo 
"option overlay_root /overlay" 
  319    # Füge non-core package hinzu (z.B. feeds routing,opennet,luci,...) 
  320    # Hole Architektur und CPU Type 
  322    arch_cpu_type=
$(opkg status base-files | awk 
'/Architecture/ {print $2}')
 
  323    local noncore_pkgs_url=
"$base_url/packages/$arch_cpu_type" 
  326    for feed in base packages routing luci opennet; 
do 
  327        echo 
"src/gz on_$feed $noncore_pkgs_url/$feed" 
  330    # Fuege zusaetzlich eine URL mit core packages hinzu (beinhaltet Kernel Module). 
  332    # shellcheck source=openwrt/package/base-files/files/etc/openwrt_release 
  333    arch_path=
$(. /etc/openwrt_release; echo 
"$DISTRIB_TARGET")
 
  334    local core_pkgs_url=
"$base_url/targets/$arch_path/packages" 
  335    echo 
"src/gz on_core $core_pkgs_url" 
  339## @fn is_package_installed() 
  340## @brief Prüfe, ob ein opkg-Paket installiert ist. 
  341## @param package Name des Pakets 
  343    trap 
'error_trap is_package_installed "$*"' EXIT
 
  346    # Korrekte Prüfung: via "opkg list-installed" - leider erzeugt sie locking-Fehlermeldung
 
  347    # bei parallelen Abläufen (z.B. Status-Seite). 
  348    #opkg list-installed | grep -q -w "^$package" && return 0
 
  349    # schneller als via opkg 
  350    status=
$(grep -A 10 
"^Package: $package$" "${IPKG_INSTROOT:-}/usr/lib/opkg/status" \
 
  351        | grep 
"^Status:" | head -1 | cut -f 2- -
d :)
 
  352    [ -z 
"$status" ] && trap 
"" EXIT && 
return 1
 
  353    echo 
"$status" | grep -qE 
"(deinstall|not-installed)" && trap 
"" EXIT && 
return 1
 
  358## @fn on_opkg_postinst_default() 
  359## @brief Übliche Nachbereitung einer on-Paket-Installation. 
  360## @details Caches löschen, uci-defaults anwenden, on-core-Bootskript ausführen 
  362    # Reset des Luci-Cache und Shell-Cache 
  364    # Paket-Initialisierungen durchfuehren, falls wir in einem echten System sind. 
  365    # In der Paket-Bau-Phase funktioniert die untenstehende Aktion nicht, da eine 
  366    # Datei fehlt, die in der /etc/init.d/boot geladen wird. 
  367    if [ -z 
"${IPKG_INSTROOT:-}" ]; then
 
  368        msg_info "Applying uci-defaults after package installation" 
  369        # Die Angabe von IPKG_INSTROOT ist hier muessig - aber vielleicht 
  370        # koennen wir die obige Bedingung irgendwann entfernen. 
  372            # der Rest sollte ohne Vorsicht stattfinden 
  374            # shellcheck source=openwrt/package/base-files/files/etc/init.d/boot 
  375            . 
"${IPKG_INSTROOT:-}/etc/init.d/boot" 
  377            # Boot-Skript aktivieren und ausführen (falls noch nicht geschehen) 
  378            /etc/init.d/on-core enable 2>/dev/
null || 
true 
  379            /etc/init.d/on-core start
 
  387## @fn on_opkg_postrm_default() 
  388## @brief Übliche Nachbereitung einer on-Paket-Entfernung 
  389## @details Caches löschen 
  395# Ende der Doku-Gruppe 
msg_error(message)
Die Fehlermeldungen werden in die Standard-Fehlerausgabe und ins syslog geschrieben.
 
msg_info(message)
Informationen und Fehlermeldungen ins syslog schreiben.
 
clean_luci_restart()
Starte den Webserver neu und lösche alle luci-Cache-Dateien und Kompilate.
 
is_on_module_installed(module)
Pruefe ob ein Opennet-Modul installiert ist.
 
get_missing_modules()
Ermittle diejenigen Module, die vor dem letzten Upgrade installiert waren.
 
get_on_modules()
Liefere die Namen aller bekannten Opennet-Module zeilenweise getrennt zurück.
 
was_on_module_installed_before()
Prüfe ob ein Modul "früher" (vor der letzten manuellen Änderung durch den Benutzer,...
 
get_default_opennet_opkg_repository_base_url()
Ermittle die automatisch ermittelte URL für die Nachinstallation von Paketen.
 
is_package_installed(package)
Prüfe, ob ein opkg-Paket installiert ist.
 
warn_if_unknown_module(module)
Gib eine Warnung aus, falls der angegebene Modul-Name unbekannt ist.
 
generate_opennet_opkg_config()
Liefere den Inhalt einer opkg.conf für das Opennet-Paket-Repository zurück.
 
on_opkg_postinst_default()
Übliche Nachbereitung einer on-Paket-Installation.
 
disable_on_module(module)
Deaktiviere ein Opennet-Modul.
 
set_configured_opennet_opkg_repository_url(repo_url)
Ändere die aktuell konfigurierte Repository-URL.
 
is_on_module_installed_and_enabled(module)
Pruefe ob ein Opennet-Modul sowohl installiert, als auch aktiviert ist.
 
on_opkg_postrm_default()
Übliche Nachbereitung einer on-Paket-Entfernung.
 
install_from_opennet_repository(packages)
Installiere ein Paket aus den Opennet-Repositories.
 
clear_cache_opennet_opkg()
Lösche die eventuell vorhandene opennet-opkg-Konfiguration (z.B. nach einem Update).
 
warn_if_not_installed_module(module)
Gib eine Warnung aus, falls das Opennet-Module nicht installiert ist.
 
get_not_installed_on_modules()
Ermittle diejenigen Module, die aktuell nicht installiert sind.
 
get_configured_opennet_opkg_repository_base_url()
Ermittle die aktuell konfigurierte Repository-URL.
 
enable_on_module(module)
Aktiviere ein Opennet-Modul.
 
uci_is_in_list(uci_path, item)
Prüfe ob ein Element in einer Liste vorkommt.
 
uci_delete(uci_path)
Lösche ein UCI-Element.
 
uci_replace_list()
Replace the items in a list. Wanted items are expected via stdin (one per line, uci_path).
 
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.
 
set eu grep root::etc shadow exit if command v chpasswd dev null
 
set eu on function print_services services log for dir in etc on services d var on services volatile d