Stefan Welscher: [MySQL] 128-Bit-Werte (IPv6) in DB speichern

Hi und zwar...
möchte ich IPv6-Adressen (128Bit) über Perl so in einer MySQl-Datenbank speichern, dass ich diese dann auch per Vergleich suchen kann.

Also sagen wir ich haben die v6IP 2001:db8::1 und ich möchte diese einem Datensatz einer Tabelle, die verschiedene Netzbereiche mit Start- und Endadresse enthält, zuordnen.
Die spätere Anweisung sollte also lauten:
Suche mir einen Datensatz, dessen Startbereich <= 2001:db8::1 und dessen Zielbereich >= 2001:db8::1 ist.

Da MySQL meines Wissens keinen 128-Bit Zahlwert hat müsste ich soweit ich gelesen habe auf BINARY oder VARBINARY ausweichen.
Darum die Frage: Wie bekomme ich die Netzbereiche in eine Binärform die DBI bzw. MySQL später richtig interpretiert?

Besten Dank!

P.S. Das "Auflängen" der IPs auf einen 32-stelligen Hexstring ist kein Problem, ich weiß nur nicht in welcher Form ich sie in die DB bekommen (bzw. später auch die Abfragen schreibe).

  1. Moin,

    http://stackoverflow.com/questions/6964143/storing-ipv6-addresses-in-mysql
    http://labs.watchmouse.com/2009/10/extending-mysql-5-with-ipv6-functions/
    http://dev.mysql.com/doc/refman/5.6/en/miscellaneous-functions.html#function_inet6-aton

    würde ich mir da mal angucken.

    Schönen Sonntag,
    Horst

  2. Moin!

    möchte ich IPv6-Adressen (128Bit) über Perl so in einer MySQl-Datenbank speichern, dass ich diese dann auch per Vergleich suchen kann.

    Die Frage des Speicherns ist abhängig von der Frage des wiederfindens.

    Wiederfinden wirst du diese IP sicherlich auch, wenn du sie einfach als Text in die DB packst. Das ist aber nicht unbedingt der erwartete Usecase bei IPv6. Exact dieselbe IP wiederfinden willst und wirst du nur, wenn du entweder mit Servern zu tun hast, oder mit Clients ohne Privacy Extensions.

    In allen anderen Fällen sind die letzten 64 Bit der IP nicht konstant.

    Also sagen wir ich haben die v6IP 2001:db8::1 und ich möchte diese einem Datensatz einer Tabelle, die verschiedene Netzbereiche mit Start- und Endadresse enthält, zuordnen.

    Für Netzbereichs-Zuordnung sind nur die ersten 64 Bit einer IPv6 zuständig. Und für 64 Bit gibts in MySQL eine Datenstruktur. Wenn dein Hauptaugenmerk also auf diesen ersten 64 Bit liegt, dann teile die IP in ihrer Bitdarstellung in zwei Teile und speichere sie in der Langform.

    Die spätere Anweisung sollte also lauten:
    Suche mir einen Datensatz, dessen Startbereich <= 2001:db8::1 und dessen Zielbereich >= 2001:db8::1 ist.

    Solch eine Anweisung kann technisch zwar denkbar sein, aus Sicht von IPv6 ist sie jedoch eher unsinnig. Entweder 2001:db8::1 ist ein Server - dann ist die IP konstant. Oder es ist kein Server - dann können 2001:db8::DDEE:1122:2345:9071 und 2001:db8::2 dieselbe Maschine sein, sogar zur gleichen Zeit.

    P.S. Das "Auflängen" der IPs auf einen 32-stelligen Hexstring ist kein Problem, ich weiß nur nicht in welcher Form ich sie in die DB bekommen (bzw. später auch die Abfragen schreibe).

    Entweder du speicherst die IP in der definierten Langform, immer alle 128 Bit. Für Suchen mit Bitmasken ist das vermutlich besser. Oder du speicherst sie immer in der kürzestmöglichen Form als Text - den Input dabei einmal auf Langform und dann auf Kurzform bringen, damit nicht äquivalente Schreibweisen wie 2001:db8:: und 2001:0db8:: unterschiedlich aussehen.

    - Sven Rautenberg

    1. Also sagen wir ich haben die v6IP 2001:db8::1 und ich möchte diese einem Datensatz einer Tabelle, die verschiedene Netzbereiche mit Start- und Endadresse enthält, zuordnen.

      Für Netzbereichs-Zuordnung sind nur die ersten 64 Bit einer IPv6 zuständig. Und für 64 Bit gibts in MySQL eine Datenstruktur. Wenn dein Hauptaugenmerk also auf diesen ersten 64 Bit liegt, dann teile die IP in ihrer Bitdarstellung in zwei Teile und speichere sie in der Langform.

      Die spätere Anweisung sollte also lauten:
      Suche mir einen Datensatz, dessen Startbereich <= 2001:db8::1 und dessen Zielbereich >= 2001:db8::1 ist.

      Solch eine Anweisung kann technisch zwar denkbar sein, aus Sicht von IPv6 ist sie jedoch eher unsinnig. Entweder 2001:db8::1 ist ein Server - dann ist die IP konstant. Oder es ist kein Server - dann können 2001:db8::DDEE:1122:2345:9071 und 2001:db8::2 dieselbe Maschine sein, sogar zur gleichen Zeit.

      So einfach ist es in meinem Fall leider nicht, dass ich nur 64Bit vergleichen muss.
      Ich bin im Provider-Umfeld unterwegs und habe Hauptsächlich mit Routern zu tun.
      Die können auf P2P-Links auch /127-Netze verwenden (und machen das auch [RFC6164]).
      Ob die Adresse selbst statisch oder dynamisch (z.B. durch EUI64/Privacy Extensions) generiert wurde spielt keine Rolle, es geht ja nur darum den zugehörigen Netzbereich zu finden, mit dem bestimmte Eigenschaften verknüpft sind (z.B. RIR, AS, etc.)

      Entweder du speicherst die IP in der definierten Langform, immer alle 128 Bit. Für Suchen mit Bitmasken ist das vermutlich besser. Oder du speicherst sie immer in der kürzestmöglichen Form als Text - den Input dabei einmal auf Langform und dann auf Kurzform bringen, damit nicht äquivalente Schreibweisen wie 2001:db8:: und 2001:0db8:: unterschiedlich aussehen.

      Mir geht es nur darum, wenn ich... sagen wir der Einfachkeit halber eine v6IP 2001:0000:0000:0000:0000:0000:0000:0010 habe, wie übergebe ich die bei Perl über DBI an MySQL, damit diese in der Datenbank als binär 0010000000000001...0000000000010000 gespeichert wird ich später auf der Basis Vergleiche ansetzen kann? Ich gehe mal davon aus den Binärstring so zu übergeben wird nicht zielführend sein...

      1. Tach!

        Mir geht es nur darum, wenn ich... sagen wir der Einfachkeit halber eine v6IP 2001:0000:0000:0000:0000:0000:0000:0010 habe, wie übergebe ich die bei Perl über DBI an MySQL, damit diese in der Datenbank als binär 0010000000000001...0000000000010000 gespeichert wird ich später auf der Basis Vergleiche ansetzen kann? Ich gehe mal davon aus den Binärstring so zu übergeben wird nicht zielführend sein...

        Ich würde versuchen, das so zu lösen: Feld vom Typ (VAR)BINARY und Werte als hexadezimale Literale in den Statements übergeben oder für Prepared Statements die Werte in Binärform binden.

        dedlfix.

        1. Tach!
          Ich würde versuchen, das so zu lösen: Feld vom Typ (VAR)BINARY und Werte als hexadezimale Literale in den Statements übergeben oder für Prepared Statements die Werte in Binärform binden.

          dedlfix.

          Vielen Dank! Damit läuft es!

          mysql> SELECT HEX(start), HEX(end) FROM rir_delegated_extended_ipv6 WHERE start<=X'20010410000000000000000000000001' AND end>=X'20010410000000000000000000000001';
          +----------------------------------+----------------------------------+
          | HEX(start)                       | HEX(end)                         |
          +----------------------------------+----------------------------------+
          | 20010410000000000000000000000000 | 20010410FFFFFFFFFFFFFFFFFFFFFFFF |
          +----------------------------------+----------------------------------+
          1 row in set (0.04 sec)