PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Land aus IP ermitteln - IPv6

Ich glaube, ich habe die Lösung gefunden. Es beinhaltet zuerst das Modifizieren der Daten und dann etwas Massieren der Eingabe. Folgendes hat funktioniert.

Zunächst müssen die Daten so konvertiert werden, dass alle Adressen vollständig sind, ohne Kürzung, mit entfernten Semikolon-Trennzeichen. Die in meiner Frage gezeigten Beispieldaten werden konvertiert in:

 t_start                          | t_end                            | t_country_code
----------------------------------+----------------------------------+----------------
 00000000000000000000000000000000 | 00ffffffffffffffffffffffffffffff | ZZ
 01000000000000000000000000000000 | 01ffffffffffffffffffffffffffffff | ZZ
...
 20000000000000000000000000000000 | 2000ffffffffffffffffffffffffffff | ZZ
...
 20011200000000000000000000000000 | 20011200ffffffffffffffffffffffff | MX
...

Das wird in der Datenbank gespeichert.

Der nächste Schritt bestand darin, die im Code empfangene IP-Adresse in dasselbe Format zu konvertieren. Dies geschieht in PHP mit folgendem Code (angenommen, dass $ip_adress ist die eingehende IPv6-Adresse):

$addr_bin = inet_pton($ip_address);                                                                                                              
$bytes = unpack('n*', $addr_bin);
$ip_address = implode('', array_map(function ($b) {return sprintf("%04x", $b); }, $bytes));

Jetzt Variable $ip_adress enthält die vollständige IPv6-Adresse, zum Beispiel

:: => 00000000000000000000000000000000
2001:1200::ab => 200112000000000000000000000000ab

und so weiter.

Jetzt können Sie diese vollständige Adresse einfach mit den Bereichen in der Datenbank vergleichen. Ich habe der Datenbank eine zweite Funktion hinzugefügt, um mit IPv6-Adressen umzugehen, die wie folgt aussieht:

CREATE OR REPLACE FUNCTION get_country_for_ipv6(character varying)
  RETURNS character varying AS
$BODY$
declare
    ip  ALIAS for $1;
    ccode   varchar;
begin
    select into ccode t_country_code from ipv6_to_country where addr between n_from and n_to limit 1;
    if ccode is null then
        ccode := '';
    end if;
    return ccode;
end;$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;

Schließlich habe ich in meinem PHP-Code den Code hinzugefügt, der die eine oder andere Postgres-Funktion basierend auf der Eingabe ip_address aufruft.