PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Determina il paese da IP - IPv6

Credo di aver trovato la soluzione. Si tratta prima di modificare i dati e poi di massaggiare l'input. Ecco cosa ha funzionato.

Innanzitutto, i dati devono essere convertiti in modo che tutti gli indirizzi siano pieni, senza accorciamenti, con i separatori punto e virgola rimossi. I dati di esempio mostrati nella mia domanda vengono convertiti in:

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

Questo è ciò che è memorizzato nel database.

Il passaggio successivo è stato convertire l'indirizzo IP ricevuto nel codice in modo che fosse nello stesso formato. Questo viene fatto in PHP con il seguente codice (supponiamo che $ip_address è l'indirizzo IPv6 in entrata):

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

Ora variabile $ip_address conterrà l'indirizzo IPv6 completo, ad esempio

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

e così via.

Ora puoi semplicemente confrontare questo indirizzo completo con gli intervalli nel database. Ho aggiunto una seconda funzione al database per gestire gli indirizzi IPv6, che assomiglia a questo:

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;

Infine, nel mio codice php ho aggiunto il codice che chiama l'una o l'altra funzione Postgres in base all'input ip_address.