fff-babeld: redistribute all peer_ip and peer_ip6 addresses #87

Closed
jkimmel wants to merge 2 commits from jkimmel/firmware:babel_peer_ip into master
Owner

So far peer ips were only distributed via babel if they happened to fall
into the predefined network ranges. Currently, these only contain the
prefixes from the private and ULA ranges. Specifying any other address,
e.g. a globally routed one, will not result in the router being
reachable via that address.

Now peer ips are added to the loopback interface and babel is
instructed to redistribute addresses from lo, so any peer ip is
redistributed and therefore the router is now reachable via these
addresses.

Another option could have been to dynamically add a redistribute filter
for the peer ips before this section:

config filter
    option type 'redistribute'
    option local 'true'
    option action 'deny'

Sadly it almost impossible to do this in a reasonable manner with uci,
that doesn't involve iterating over all filter options or requiring this
specific section to be always named.

Adding the peer ips to lo is also the more conventional way to
configure an address "owned" by a router.

Signed-off-by: Johannes Kimmel fff@bareminimum.eu

So far peer ips were only distributed via babel if they happened to fall into the predefined network ranges. Currently, these only contain the prefixes from the private and ULA ranges. Specifying any other address, e.g. a globally routed one, will not result in the router being reachable via that address. Now peer ips are added to the `loopback` interface and babel is instructed to redistribute addresses from `lo`, so any peer ip is redistributed and therefore the router is now reachable via these addresses. Another option could have been to dynamically add a redistribute filter for the peer ips before this section: ``` config filter option type 'redistribute' option local 'true' option action 'deny' ``` Sadly it almost impossible to do this in a reasonable manner with uci, that doesn't involve iterating over all filter options or requiring this specific section to be always named. Adding the peer ips to `lo` is also the more conventional way to configure an address "owned" by a router. Signed-off-by: Johannes Kimmel <fff@bareminimum.eu>
jkimmel added the
bug
layer3
packages/fff
labels 2021-01-26 19:10:28 +01:00
fbl was assigned by jkimmel 2021-01-26 19:10:46 +01:00
Owner

Ist das mit der Reihenfolge irgendwo dokumentiert? Ich kann nirgends was finden ...

Ist das mit der Reihenfolge irgendwo dokumentiert? Ich kann nirgends was finden ...
Author
Owner

Ich bin mir nicht ganz sicher, was du mit Reihenfolge meinst, aber ich erklaer nochmal, warum peer_ip und peer_ip6 momentan nicht funkionieren:

Erst mal allgemein:

  1. Babel filter Regeln werden eine nach der anderen abgearbeitet. Das steht so nicht explizit in der Manpage, laeuft aber so.
  2. Wenn ein selector auf eine Route passt, dann wird die dazugehoerige action ausgefuert und das war es. Es werden keine anderen Filter mehr fuer diese Route angesehen. Also hier wird entschieden, ob eine Route durchgelassessn (accept, der default), verworfen (deny), oder sonst was damit gemacht wird.
  3. Eine Babel config verhaelt sich so, als wuerde immer eine redistribute local allow Filterregel am Ende stehen, die alle local Routen, also Routen aus der local Table, bzw. als local markierte Routen, uebernimmt.
  4. Das Openwrt Initscript uebernimmt die Reihenfolge der Filterregeln exakt so wie sie in /etc/config/babeld stehen.

Ich uebersetz jetzt mal grob, was in unserer /etc/config/babeld steht:

Konfiguriert man eine IP auf ein Interface, dann wird dazu ein entprechender Eintrag zur Hostroute (also nur /32, bzw. /128) in der local Table gesetzt. Mit den bisherigen Regeln kann Babel also nur Hostrouten aus den 3 vorangegangen Netzen weiterverteilen. Insbesondere fallen damit die globalen Adressen raus.

Wie kommen jetzt trotzdem die anderen Routen ins Babel?

Also weiter mit der Uebersetzung:

Ab jetzt sind erst mal keine weiteren Routen erlaubt, aber nicht alle routen matchen auf local. Insbesondere sind an dieser Stelle nur Hostrouten von Babel aufgenommen, es fehlen also noch die eigentlichen Netze.

Sollten jetzt noch zusaetzliche Routen in der fff Table angelegt sein (nicht local, meist proto static), die in die 3 Netze passen, werden diese auch uebernommen.

Das heisst irgendwas installiert in die fff Table static routen. Hier verhaelt sich OpenWRT etwas eigenartig:

In der /etc/config/network fuegen wir folgende zeilen dem client Interface hinzu:

config interface 'client'
	...
	option ip4table 'fff'
	option ip6table 'fff'

Wenn die angegeben Table nicht die main Table ist, dann werden entsprechend den ipaddr und ip6addr noch die Routen als proto static in die fff Table geschrieben.

Jetzt sind aber immernoch keine anderen Netze als die Freifunk internen erlaubt. Das faellt natuerlich auf, deswegen werden hier noch fuer die Netze aus dem client Interface erlaubt.

Na dann pack doch auch so eine Filterregel fuer die Peer Ips einfach hinten dran!

Jaha... das ginge tatsaechlich. Statt einfach Adressen auf lo zu erlauben koennte man:

  1. peer_ip und peer_ip6 immer an die Babelinterfaces kleben (das machen wir schon!)
  2. Zusaetzlich noch option ip4table 'fff' und option ip6table 'fff' bei den Babelinterface setzen, damit OpenWRT aus total offensichtlichen gruenden eine static Route installiert.
  3. Entsprechende Filter in /etc/config/babeld anhaengen.

Also fuer mich klingt das ja etwas undurchsichtig, vorallem die Eigenheiten von Schritt 2 waren mir bis heute nicht klar.

Na dann pack doch einfach ne static Route so in die Table!

Hab ich probiert, geht nicht:

# ip -6 route add 2001:db8:: dev lo table fff proto 
static
# ip -6 route show table fff proto static
...
unreachable 2001:db8:: dev lo metric 1024 error 4294967168 pref medium

Das geht nur, wenn man die Route als local markiert, aber dann... genau :)


Ich werde den PR auch noch dahingehend aendern und die Peer IPs (jedenfalls IPv6) nicht mehr auf den Babelinterfaces setzen. Die IPv4 Adresse ist noch so lange notwendigt, bis wir einen aktuellen Kernel haben und Babel mit IPv6 nexthops fuer IPv4 klar kommt.

Mit dem Ansatz die Adressen von lo zu verteilen, sparen wir uns dynamische Filterregeln in /etc/config/babeld und es ist meiner Meinung klarer, was passiert. Ausserdem koennen wir so die eher ungewoehnlichen IP Adressen auf den Babelinterfaces loswerden.

Warum genau nochmal lo

lo ist eigentlich der Platz fuer diese Art Adressen. Es handelt sich ja um Adressen, die dem Router selbst gehoeren, bzw. die ihn identifizieren. Man muesste die Adressen also entweder auf alle Interfaces packen, oder wie es ueblich ist, eben nur auf lo.

Ich bin mir nicht ganz sicher, was du mit Reihenfolge meinst, aber ich erklaer nochmal, warum `peer_ip` und `peer_ip6` momentan nicht funkionieren: **Erst mal allgemein:** 1. Babel `filter` Regeln werden eine nach der anderen abgearbeitet. Das steht so _nicht_ explizit in der Manpage, laeuft aber so. 2. Wenn ein `selector` auf eine Route passt, dann wird die dazugehoerige `action` ausgefuert und das war es. Es werden keine anderen Filter mehr fuer diese Route angesehen. Also hier wird entschieden, ob eine Route durchgelassessn (`accept`, der default), verworfen (`deny`), oder sonst was damit gemacht wird. 3. Eine Babel config verhaelt sich so, als wuerde immer eine `redistribute local allow` Filterregel am Ende stehen, die alle `local` Routen, also Routen aus der `local` Table, bzw. als `local` markierte Routen, uebernimmt. 4. Das Openwrt Initscript uebernimmt die Reihenfolge der Filterregeln exakt so wie sie in `/etc/config/babeld` stehen. **Ich uebersetz jetzt mal grob, was in unserer `/etc/config/babeld` steht:** * Routen werden aus der `fff` Table gelesen und auch exportiert. * `local` Routen werden trotzdem aus der `local` Table genommen * Wir erlauben explizit `local` Routen aus 1. `10.50.0.0/16` 2. `10.83.0.0/16` 3. `fd43:5602:29bd::/48` * Wir verbieten saemtliche weitere `local` Routen. * https://git.freifunk-franken.de/freifunk-franken/firmware/src/branch/master/src/packages/fff/fff-babeld/files/etc/config/babeld#L28 * Ab hier kann man so viele Filter hinschreiben, die sich auf `local` Routen beziehen, wie man will. Alle `local` Routen sind vorher durch die vorhergehende Regel schon aussortiert und kommen nicht an diesen Punkt. Konfiguriert man eine IP auf ein Interface, dann wird dazu ein entprechender Eintrag zur Hostroute (also nur /32, bzw. /128) in der `local` Table gesetzt. Mit den bisherigen Regeln kann Babel also nur Hostrouten aus den 3 vorangegangen Netzen weiterverteilen. Insbesondere fallen damit die globalen Adressen raus. **Wie kommen jetzt trotzdem die anderen Routen ins Babel?** Also weiter mit der Uebersetzung: Ab jetzt sind erst mal keine weiteren Routen erlaubt, aber nicht alle routen matchen auf `local`. Insbesondere sind an dieser Stelle nur Hostrouten von Babel aufgenommen, es fehlen also noch die eigentlichen Netze. Sollten jetzt noch zusaetzliche Routen in der `fff` Table angelegt sein (nicht `local`, meist `proto static`), die in die 3 Netze passen, werden diese auch uebernommen. Das heisst irgendwas installiert in die `fff` Table `static` routen. Hier verhaelt sich OpenWRT etwas eigenartig: In der `/etc/config/network` fuegen wir folgende zeilen dem `client` Interface hinzu: ``` config interface 'client' ... option ip4table 'fff' option ip6table 'fff' ``` Wenn die angegeben Table **nicht** die `main` Table ist, dann werden entsprechend den `ipaddr` und `ip6addr` noch die Routen als `proto static` in die `fff` Table geschrieben. Jetzt sind aber immernoch keine anderen Netze als die Freifunk internen erlaubt. Das faellt natuerlich auf, deswegen werden [hier](https://git.freifunk-franken.de/freifunk-franken/firmware/src/branch/master/src/packages/fff/fff-babeld/files/etc/layer3.d/40-babel#L91) noch fuer die Netze aus dem `client` Interface erlaubt. **Na dann pack doch auch so eine Filterregel fuer die Peer Ips einfach hinten dran!** Jaha... das ginge tatsaechlich. Statt einfach Adressen auf `lo` zu erlauben koennte man: 1. `peer_ip` und `peer_ip6` immer an die Babelinterfaces kleben (das machen wir schon!) 2. Zusaetzlich noch `option ip4table 'fff'` und `option ip6table 'fff'` bei den Babelinterface setzen, damit OpenWRT aus total offensichtlichen gruenden eine `static` Route installiert. 3. Entsprechende Filter in `/etc/config/babeld` anhaengen. Also fuer mich klingt das ja etwas undurchsichtig, vorallem die Eigenheiten von Schritt 2 waren mir bis heute nicht klar. **Na dann pack doch einfach ne static Route so in die Table!** Hab ich probiert, geht nicht: ``` # ip -6 route add 2001:db8:: dev lo table fff proto static # ip -6 route show table fff proto static ... unreachable 2001:db8:: dev lo metric 1024 error 4294967168 pref medium ``` Das geht nur, wenn man die Route als `local` markiert, aber dann... genau :) --- Ich werde den PR auch noch dahingehend aendern und die Peer IPs (jedenfalls IPv6) nicht mehr auf den Babelinterfaces setzen. Die IPv4 Adresse ist noch so lange notwendigt, bis wir einen aktuellen Kernel haben und Babel mit IPv6 nexthops fuer IPv4 klar kommt. Mit dem Ansatz die Adressen von `lo` zu verteilen, sparen wir uns dynamische Filterregeln in `/etc/config/babeld` und es ist meiner Meinung klarer, was passiert. Ausserdem koennen wir so die eher ungewoehnlichen IP Adressen auf den Babelinterfaces loswerden. **Warum genau nochmal `lo`** `lo` ist eigentlich der Platz fuer diese Art Adressen. Es handelt sich ja um Adressen, die dem Router selbst *gehoeren*, bzw. die ihn identifizieren. Man muesste die Adressen also entweder auf alle Interfaces packen, oder wie es ueblich ist, eben nur auf `lo`.
jkimmel force-pushed babel_peer_ip from 5799cc560c to 00a894c21b 2021-01-27 15:36:36 +01:00 Compare
Owner

Ich würde peer_ip* nicht ans Loopback Interface hängen. Die waren ursprünglich wirklich nur für die Babel Peeringinterfaces gedacht.

Ich sehe aber, was du haben möchtest. Was hälst du davon, dass wir stattdessen in der Gateway-Config eine neue option router_ip einführen? Die Adressen könnten dann ans Loopback gehängt, im babel announced werden und ggf. auch für NAT herhalten.

Ich würde `peer_ip*` nicht ans Loopback Interface hängen. Die waren ursprünglich wirklich nur für die Babel Peeringinterfaces gedacht. Ich sehe aber, was du haben möchtest. Was hälst du davon, dass wir stattdessen in der Gateway-Config eine neue option `router_ip` einführen? Die Adressen könnten dann ans Loopback gehängt, im babel announced werden und ggf. auch für NAT herhalten.
Owner

Für mich ist das alles irgendwie kein befriedigender Zustand.

Mittelfristig sollte man ggf. überlegen, ob man nicht hier direkt in Babel eine prio vergleichbar mit ip rule einbaut. Der Vorteil bei babel ist ja im Vergleich dazu, dass diese Information nicht dynamisch ist, sondern nur einmal beim Start gelesen wird und dann halt noch einmalig anhand der Prio sortiert werden muss. Das sollte sich eigentlich lösen lassen, sodass man dann Filter beliebig ordnen kann.

Für mich ist das alles irgendwie kein befriedigender Zustand. Mittelfristig sollte man ggf. überlegen, ob man nicht hier direkt in Babel eine prio vergleichbar mit ip rule einbaut. Der Vorteil bei babel ist ja im Vergleich dazu, dass diese Information nicht dynamisch ist, sondern nur einmal beim Start gelesen wird und dann halt noch einmalig anhand der Prio sortiert werden muss. Das sollte sich eigentlich lösen lassen, sodass man dann Filter beliebig ordnen kann.
Member

Ich würde peer_ip* nicht ans Loopback Interface hängen. Die waren ursprünglich wirklich nur für die Babel Peeringinterfaces gedacht.

Ich sehe aber, was du haben möchtest. Was hälst du davon, dass wir stattdessen in der Gateway-Config eine neue option router_ip einführen? Die Adressen könnten dann ans Loopback gehängt, im babel announced werden und ggf. auch für NAT herhalten.

Was ist dann eigentlich der Unterschied zwischen router_ip und peer_ip ? Also wann nutzt man was? Ich hab das so verstanden, dass das was wir machen wollen genau das ist was peer_ip liefert nur das es eben durch Babelfilter kaputt ist. Daher die Frage wo da jetzt der Unterschied am Ende sein soll oder auch anders gefragt, wenn man router_ip anlegt, wann (mal einen realistischen Zustand) nutzt man dann noch peer_ip?

> Ich würde `peer_ip*` nicht ans Loopback Interface hängen. Die waren ursprünglich wirklich nur für die Babel Peeringinterfaces gedacht. > > Ich sehe aber, was du haben möchtest. Was hälst du davon, dass wir stattdessen in der Gateway-Config eine neue option `router_ip` einführen? Die Adressen könnten dann ans Loopback gehängt, im babel announced werden und ggf. auch für NAT herhalten. Was ist dann eigentlich der Unterschied zwischen router_ip und peer_ip ? Also wann nutzt man was? Ich hab das so verstanden, dass das was wir machen wollen genau das ist was peer_ip liefert nur das es eben durch Babelfilter kaputt ist. Daher die Frage wo da jetzt der Unterschied am Ende sein soll oder auch anders gefragt, wenn man router_ip anlegt, wann (mal einen realistischen Zustand) nutzt man dann noch peer_ip?
Owner

Was ist dann eigentlich der Unterschied zwischen router_ip und peer_ip ? Also wann nutzt man was? Ich hab das so verstanden, dass das was wir machen wollen genau das ist was peer_ip liefert nur das es eben durch Babelfilter kaputt ist. Daher die Frage wo da jetzt der Unterschied am Ende sein soll oder auch anders gefragt, wenn man router_ip anlegt, wann (mal einen realistischen Zustand) nutzt man dann noch peer_ip?

peer_ip war ursprünglich nur als Peeringadresse gedacht, sagen wir so wie das Peering-Netz an einem IX. Die Adressen sind dafür da an die Peeringinterfaces zu kommen, damit Babel etwas zu drauf routen hat. Für v6 brauchts das normal gar nicht, weil Link-Local. Für v4 brauchen wir das aktuell aber noch, wobei die Firmware sind das auch aus dem Client-Interface "klauen" kann.

Ich möchte diese Adressen hier nicht zweckentfremden und für etwas anderes benutzen, als die Option gedacht ist. Das eine ist ne Peeringadresse, das andere ne Adresse, unter der der Router erreichbar ist.
Wobei das für mich jetzt nicht ausschließt, dass wir babel noch so erweitern, dass es Peeringadressen ggf. auch aus der router_ip "klauen" kann. Es kann auch gut sein, dass wir feststellen, dass es die explizite peer_ip nicht mehr braucht, und wir das in Zukunft deprecaten. Aber dann möchte ich lieber den Namen peer_ip los werden, als ihn dann für etwas zu verwenden, was mit dem Namen nicht mehr zusammen passt.

> Was ist dann eigentlich der Unterschied zwischen router_ip und peer_ip ? Also wann nutzt man was? Ich hab das so verstanden, dass das was wir machen wollen genau das ist was peer_ip liefert nur das es eben durch Babelfilter kaputt ist. Daher die Frage wo da jetzt der Unterschied am Ende sein soll oder auch anders gefragt, wenn man router_ip anlegt, wann (mal einen realistischen Zustand) nutzt man dann noch peer_ip? peer_ip war ursprünglich nur als Peeringadresse gedacht, sagen wir so wie das Peering-Netz an einem IX. Die Adressen sind dafür da an die Peeringinterfaces zu kommen, damit Babel etwas zu drauf routen hat. Für v6 brauchts das normal gar nicht, weil Link-Local. Für v4 brauchen wir das aktuell aber noch, wobei die Firmware sind das auch aus dem Client-Interface "klauen" kann. Ich möchte diese Adressen hier nicht zweckentfremden und für etwas anderes benutzen, als die Option gedacht ist. Das eine ist ne Peeringadresse, das andere ne Adresse, unter der der Router erreichbar ist. Wobei das für mich jetzt nicht ausschließt, dass wir babel noch so erweitern, dass es Peeringadressen ggf. auch aus der router_ip "klauen" kann. Es kann auch gut sein, dass wir feststellen, dass es die explizite peer_ip nicht mehr braucht, und wir das in Zukunft deprecaten. Aber dann möchte ich lieber den Namen peer_ip los werden, als ihn dann für etwas zu verwenden, was mit dem Namen nicht mehr zusammen passt.
Member

alles klar, mit der Erklärung kann ich leben und macht für mich dann durchaus Sinn.

Zum Thema peer_ip los werden noch etwas:

Wenn wir etwas einbauen das alte config kaputt machen kann, müssen wir uns überlegen wie wir damit umgehen. Zwingend muss mMn die gateway.meta.config_version erhöht werden und sinnvoll wären vermutlich sogar Migrationsscripte damit beim Update dann nicht alles auseiander fällt. Das aber nur als kleine Anmerkung nebenbei und hat hier eigentlich auch gar nichts zu suchen da beim hinzufügen neur Optionen das Problem nicht auftritt (da würde ich jetzt auch die Version nicht unbedingt erhöhen), beim entfernen von Optionen allerdings schon.

alles klar, mit der Erklärung kann ich leben und macht für mich dann durchaus Sinn. Zum Thema peer_ip los werden noch etwas: Wenn wir etwas einbauen das alte config kaputt machen kann, müssen wir uns überlegen wie wir damit umgehen. Zwingend muss mMn die gateway.meta.config_version erhöht werden und sinnvoll wären vermutlich sogar Migrationsscripte damit beim Update dann nicht alles auseiander fällt. Das aber nur als kleine Anmerkung nebenbei und hat hier eigentlich auch gar nichts zu suchen da beim hinzufügen neur Optionen das Problem nicht auftritt (da würde ich jetzt auch die Version nicht unbedingt erhöhen), beim entfernen von Optionen allerdings schon.
jkimmel added a new dependency 2021-02-17 07:56:48 +01:00
Author
Owner

@ChristianD Ja da hast du recht. Ich glaube es macht Sinn fuer ein paar Versionen eine Warnung auszuspucken, dass die Option in Zukunft nicht mehr unterstuetzt wird und man die Alternative benutzen soll.

In dem Moment, wo man es tatsaechlich abdreht muesste man die Version erhoehen.

@fbl

Aber dann möchte ich lieber den Namen peer_ip los werden, als ihn dann für etwas zu verwenden, was mit dem Namen nicht mehr zusammen passt.

Ich habe jetzt auch noch einmal ueberlegt und ich haette gern den PR mehr oder weniger so gemerged, damit das VXLAN Zeug wirklich auch mal ansatzweise fertig werden kann. Die Aenderungen, die gerade Vorgeschlagen sind, sollten weder etwas kaputt machen, noch grossartig zukuenftige Sachen behindern.

Waere natuerlich schoen, wenn man es gleich richtig fixen koennte, aber da sind noch ein paar Kleinigkeiten ungeklaert. Ich wuerde also gern hier lieber iterativ der Sache naeher kommen, statt andere Sachen ewig auf die perfekte Loesung warten zu lassen.

@ChristianD Ja da hast du recht. Ich glaube es macht Sinn fuer ein paar Versionen eine Warnung auszuspucken, dass die Option in Zukunft nicht mehr unterstuetzt wird und man die Alternative benutzen soll. In dem Moment, wo man es tatsaechlich abdreht muesste man die Version erhoehen. @fbl > Aber dann möchte ich lieber den Namen peer_ip los werden, als ihn dann für etwas zu verwenden, was mit dem Namen nicht mehr zusammen passt. Ich habe jetzt auch noch einmal ueberlegt und ich haette gern den PR mehr oder weniger so gemerged, damit das VXLAN Zeug wirklich auch mal ansatzweise fertig werden kann. Die Aenderungen, die gerade Vorgeschlagen sind, sollten weder etwas kaputt machen, noch grossartig zukuenftige Sachen behindern. Waere natuerlich schoen, wenn man es gleich richtig fixen koennte, aber da sind noch ein paar Kleinigkeiten ungeklaert. Ich wuerde also gern hier lieber iterativ der Sache naeher kommen, statt andere Sachen ewig auf die perfekte Loesung warten zu lassen.
Owner

Der zweite Commit gefällt mir nicht, der macht nämlich das Verhalten, für das diese Option mal gedacht war, kaputt. Auch wenn diese Konfiguration vielleicht nicht sinnvoll erscheint, würde ich das nur sehr ungern so handhaben.

Den ersten Commit kann ich mir als Übergangslösung vorstellen. Ich bin aber nach wie vor der Meinung, dass man das lieber gleich sauber lösen und neue Optionen einführen sollte, die dieses neue Feature "Routeradresse" abbilden.

Der zweite Commit gefällt mir nicht, der macht nämlich das Verhalten, für das diese Option mal gedacht war, kaputt. Auch wenn diese Konfiguration vielleicht nicht sinnvoll erscheint, würde ich das nur sehr ungern so handhaben. Den ersten Commit kann ich mir als Übergangslösung vorstellen. Ich bin aber nach wie vor der Meinung, dass man das lieber gleich sauber lösen und neue Optionen einführen sollte, die dieses neue Feature "Routeradresse" abbilden.
Author
Owner

Jap verstehe ich. Der erste commit ist auch der einzige wichtige. Allerdings fuer "gleich richtig machen" muessen wir erst einmal noch Zeit finden und die ganzen Moeglichkeiten durchsprechen, wie man das Loesen kann und wo man alles Sachen anpassen muss. Da ergeben sich naemlich einiges an Abhaengigkeiten, die man dann anpassen muss.

Jap verstehe ich. Der erste commit ist auch der einzige wichtige. Allerdings fuer "gleich richtig machen" muessen wir erst einmal noch Zeit finden und die ganzen Moeglichkeiten durchsprechen, wie man das Loesen kann und wo man alles Sachen anpassen muss. Da ergeben sich naemlich einiges an Abhaengigkeiten, die man dann anpassen muss.
Owner

Wie sieht es mit #136 aus?

Wie sieht es mit #136 aus?
Author
Owner

Closed in favor of #136.

Closed in favor of #136.
jkimmel closed this pull request 2021-08-11 17:00:16 +02:00
jkimmel removed a dependency 2021-08-11 17:00:56 +02:00

Pull request closed

Sign in to join this conversation.
No description provided.