Ruby: How to convert ipv6 uo address to ipv4 ip address? - ruby

It is easy to convert ipv4 to ipv6 with ipv4_mapped. But how about the other around?
I did not find a way to do that in IpAddr documentation.

Firstly, it's important to understand that it's impossible to convert most IPv6 addresses to IPv4 addresses (for several reasons, the most obvious being that there's no way to fit a 128-bit number into 32 bits). The only IPv6 addresses that can be converted to IPv4 are ones that are mapped from IPv4 address (such as those produced by IPAddr#ipv4_mapped). For that, we have IPAddr#native:
require "ipaddr"
ip = IPAddr.new("192.168.2.128")
ipv6 = ip.ipv4_mapped
puts ipv6.native
# => 192.168.2.128

Related

Golang: net.ParseIP()

some perfectly valid IPv6 addresses are considered IPv4 by net.ParseIP(), e.g. 0000:0000:0000:0000:0000:ffff:0100:0000 / ::ffff:0100:0. (please see https://play.golang.org/p/57jAJVSIrHF for a simple example)
What would be the most idiomatic way to deal with this situation? The net package does not export most of the functionality, so rewriting net.Parse would result in a lot of code duplication.
Thank you in advance for your help!
best regards,
Stefan
What you consider perfectly valid IPv6 addresses like ::ffff:0100:0000 are in fact IPv4 addresses mapped into the IPv6 space, commonly written as ::ffff:1.0.0.0. Thus essentially it is an IPv4 address. See section about IPv4-mapped IPv6 addresses in Wikipedia:IPv6 for more information.
The IPAddress Go library provides more fine-grained control over IPv4-mapped addresses (and other schemes for mapping IPv4 to IPv6). Disclaimer: I am the project manager.
addrStr := ipaddr.NewIPAddressString("::ffff:0100:0")
addr := addrStr.GetAddress()
converter := ipaddr.DefaultAddressConverter{}
var ipv4Addr *ipaddr.IPv4Address
if converter.IsIPv4Convertible(addr) {
ipv4Addr = converter.ToIPv4(addr)
}
fmt.Printf("original IPv4-mapped IPv6 address is %v, IPv4 address is %v",
addr, ipv4Addr)
Output:
original IPv4-mapped IPv6 address is ::ffff:100:0, IPv4 address is 1.0.0.0

Why does Go net.IPv4 create a 16 byte address internally

I noticed Go creates a 16 byte internal representation of a 4 byte IPv4 Address when using:
// IPv4 returns the IP address (in 16-byte form) of the
// IPv4 address a.b.c.d.
func IPv4(a, b, c, d byte) IP {
p := make(IP, IPv6len)
copy(p, v4InV6Prefix)
p[12] = a
p[13] = b
p[14] = c
p[15] = d
return p
}
https://golang.org/src/net/ip.go
Is there a reason that IPv4 is initially created with 16 bytes? I was doing some calculations for Broadcast and Networkaddress where I accessed the internal byte[] directly and got confused that I had to call To4() to do something like
start := binary.BigEndian.Uint32([]byte(ip))
and actually get the IPv4 Address as uint32.
It looks like they're using a representation that allows them to easily handle both IPv4 and IPv6 addresses with the same code. They're using a single 16-byte representation for either type of IP.
The comments at the top of the code (that you linked to) explain in pretty clearly:
// IPv4 addresses are 4 bytes; IPv6 addresses are 16 bytes.
// An IPv4 address can be converted to an IPv6 address by
// adding a canonical prefix (10 zeros, 2 0xFFs).
// This library accepts either size of byte slice but always
// returns 16-byte addresses.
You can pass in either 4-byte or 16-byte representations of IPv4 addresses, but the library will internally use 16-byte ones and always return those.
The 16 byte address for IPV4 is known the IPv4-mapped address.
For 1.2.3.4 it looks like 0:0:0:0:0:ffff:12:34.
IPv4-mapped addresses are one way of storing an IPv4 address inside an IPv6 address.
Seems that going straight to the IPv4-mapped address was some kind of design choice made with that package, the reasoning is not clear to me though.

ipv6calc outputs wrong address when converting from ipv4 to ipv6?

Having a strange issue while trying to convert an ipv4 list file to ipv6:
ipv6calc -q --action conv6to4 --in ipv4 1.1.23.1 --out ipv6
2002:101:1701::
Trying to validate that result is correct, I used some online converters and it seems that 1.1.23.1 is 2002:0:0:0:0:0:101:1701 (or else 2002::101:1701).
So the last "::" should be removed & 2002 should have extra ":".
I really don't want to use sed/awk commands in order to manipulate this result, so the questions are:
is there alternative cmd/linux SW?
is this somehow fixed inside ipv6 calc, am I doing something wrong?
Thanks
This is the correct 6to4 address. A 6to4 subnet is on the format 2002:IP4_HI:IP4_LO::/48. IP4_HI is the top 16 bits of the IPv4 address, while IP4_LO is the low 16 bits of the address.
For example, the IPv4 address 1.2.3.4 gives you the 6to4 subnet 2002:0102:0304::/48.
See 6to4 address block allocation for more details.
A different question is whether this is actually the address you want? There are other ways to map IPv4 addresses to IPv6 addresses. For example, there are IPv4-mapped IPv6 addresses, which are typically written as ::ffff:1.2.3.4.
The address format you need depends on what you are going to use it for.

IP address of customer in Magento

I Want IP address from which the user is viewing the current page
and i m using
echo $_SERVER['REMOTE_ADDR'];
and it show me 127.0.0.1
Here is a Magento function to get customer's IP Address:
echo Mage::helper('core/http')->getRemoteAddr();
getRemoteAddr() also accepts a boolean parameter. When false (default) it will return the IP address as a string in the common dotted-decimal notation (e.g. 192.168.0.1). When true it will return the IP in its decimal notation--a 32-bit integer. See IPv4 Address Representations to understand the formats.
When Magento (server) and the browser (client) are both on your computer (localhost), then it's not an error, but correct that PHP's $_SERVER['REMOTE_ADDR'] contains 127.0.0.1 (or ::1).
This is because 127.0.0.1 is the standard IPv4 loopback address for any localhost.
See section "3. Global and Other Specialized Address Blocks" of RFC 5735:
127.0.0.0/8 - This block is assigned for use as the Internet host loopback address. A datagram sent by a higher-level protocol to an address anywhere within this block loops back inside the host. This is ordinarily implemented using only 127.0.0.1/32 for loopback.
You can use this one: Mage::helper('core/http')->getRemoteAddr();
This will return ip address such as '127.0.0.1'
When you use Mage::helper('core/http')->getRemoteAddr(true); it will return long (2130706433)
If you have the machine behind a proxy it is better to use this kind of code:
$ips = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
$ip =trim($ips[count($ips) - 1]);

'getaddrinfo()' function, it returns IP address from 'etc\hosts' file only ...?

I have dual stack Windows m/c, with IPv4 and IPv6 address.
The etc\hosts contains only IPv4 address of that hostname.
So whenever I call getaddrinfo() function, it returns IP address from etc\hosts file (i.e IPv4 only not IPv6 address).
ipconfig command shows both IPv4 as well as IPv6 address.
How to configure getaddrinfo() function to always return IPs from DNS rather than etc\hosts file ?
Any other way to do this ?
Name resolution is entirely independent from address configuration. Unless the name resolver learns of the IPv6 address (by inclusion in the hosts file, or a DNS entry, or mDNS, or...), it cannot return the address.

Resources