1

IP ranges in the ip2location database are represented by first and last IPs as integers.

I don't know how the conversion from IPs to integers is done, but documentation indicates it is equivalent to this code in PHP:

function ip62long($ipv6) {
  return (string) gmp_import(inet_pton($ipv6));
}

If it's a IPv4 (not IPv6), the IP is prepended with '::ffff:'.

I'm trying to import ip2location database into postgres using the column type INET. I would want to convert these integers back to IPs, i.e. revert this routine.

So far I'm using this code:

func StringToIp(in string) net.IP {
    var bigint big.Int
    bigint.SetString(in, 10)
    return bigint.Bytes()
}

That works fine for:

  • IPv6 addresses, e.g. 55838750788714571402502155597250560000 -> 2a02:26f7:e5c4:c6c1::

and would work in theory for

  • IPv4 addresses (without the ::ffff: prefix), e.g. 16909060 -> 1.2.3.4

But it does not work for these case:

  • All IPv4 prefixed with ::ffff:, e.g. 281470681743360 should become 0.0.0.0 instead of ?ffff00000000.
  • Cases like 0, 281470681743359, 281474439839744, 281474976710656.

I'm looking for a solution to convert all these values back to IPv4 or IPv6 addresses respectively to store them in postgres and look up IPs later on.

some-user
  • 3,888
  • 5
  • 19
  • 43
  • You should edit the question and add a description of the format produced by `ip62long()`. I am not interested in hunting it down by following the links. – Laurenz Albe Oct 18 '22 at 06:01
  • There is no documentation available for `ip62long()`. `gmp_import` and `inet_pton` are builtin functions of PHP. – some-user Oct 18 '22 at 06:06
  • PHP is open source, isn't it? Make it easy for the people who are willing to help you. – Laurenz Albe Oct 18 '22 at 06:08

1 Answers1

0

The cause of the problem seems to be that bigint.Bytes() returns less than 16 Bytes if the integer doesn't need it, while net.IP expects either 4 or 16 Bytes.

Prepending the []byte up with enough zeros results in proper net.IP:

func StringToIp(in string) net.IP {
    var bigint big.Int
    bigint.SetString(in, 10)
    ip := bigint.Bytes()

    for len(ip) < 16 {
        ip = append([]byte{0x00}, ip...)
    }

    return ip
}

Happy to see and accept other, more elegant, ... solutions.

some-user
  • 3,888
  • 5
  • 19
  • 43