is ipv6 backward compatible with ipv4? - c++

I've got a little udp example program written using ipv4. If I alter the code to ipv6 would I still be able to communicate with anyone using the listener with an ipv4 address? I was looking at porting examples at
http://ou800doc.caldera.com/en/SDK_netapi/sockC.PortIPv4appIPv6.html
I'm not sure if simply altering the code would ensure that it worked or if I'd have to write it in duel-stack mode.

Yes and no... IPv6 does contain completely different addressing, so you'll have to recode your app to use the alternative headers and structure sizes.
However, the IPv4 address range is available within IPv6, the syntax is to add two colons before the standard address (eg ::10.11.12.13). You can also embed IPv4 addresses within IPv6 packets.

Not without the assistance of an IPv4/IPv6 gateway in the network, and even then communication will be limited by the typical problems introduced by network address translating gateways. The traditional advice for programmers facing decisions like this is to recommend supporting both IPv4 and IPv6 at the same time.

IPv4 and IPv6 are inherently incompatible with each other.
A few basic reasons:
the address space is completely different (IPv6 has 128 bit addresses, IPv4 has 32 bit addresses)
the protocol header of IPv6 looks nothing like the protocol header of IPv4. if you try to parse an IPv6 packet as IPv4 you'll get nonsense.
The obvious result of these is that if you open an IPv6 socket you can't listen to it using an IPv4 socket.

Related

IP address and MAC address used in DPDK

Hello Stackoverflow experts,
I have been struggling with how to use the ip fragmentation provided by DPDK. and was wondering I have the correct concept of IP address and the MAC address used in rte-mbuf ethernet header.
Is Ip address alone in the header of rte-mbuf can be used to transfer from local to remote?
I see in the DPDK sample applications that the ip address is used in the hashed tables such as IP fragment table after the packets are received, but the fact that data is actually received just by using ethernet mac address, gives me the impression that IP address is only defined by the DPDK user (developers using DPDK API) and not used in actual data transfer.
Is there something missing to what I understand?
You are right. Most DPDK examples work on the second level of the OSI model, i.e. they only care about MAC addresses, not IP.
The IP reassembly example is based on L2 forwarding example, i.e. it acts as an Ethernet bridge. Though, it requires IP addresses to be analyzed, i.e. source and destination IPs must match for all the fragments of the same flow.
Now answering your questions:
Is Ip address alone in the header of rte-mbuf can be used to transfer from local to remote?
If you mean transfer using rte_eth_tx_burst() then no, IP header is not enough. The ethernet header must be filled properly as well.
IP address is only defined by the DPDK user (developers using DPDK API) and not used in actual data transfer.
Since the reassembly example is based on L2 forwarding example, it acts as reassembling Ethernet bridge. So you have a right impression, this example does not route packets based on IP addresses. It just uses IP addresses to reassemble IP fragments.

Accept IPv4 and IPv6 together in boost::asio

Short and simple question: I am new to boost::asio and I was wondering if it is possible to create a tcp::acceptor listening for both, IPv4 and IPv6 connections together. The tutorials on boost's homepage show something like this:
_acceptor = new tcp::acceptor(_ioService, tcp::endpoint(tcp::v4(), 3456));
where the endpoint is always specified with a specific protocol. Is it not possible to listen for IPv4 and IPv6 on the same port at the same time?
If you create a IPv6 acceptor, it will accept both IPv4 and IPv6 connections if IPV6_V6ONLY socket option is cleared. IPv4 addresses will be presented as IPv6 addresses, in the IPv4-mapped format.
Problems arise mainly around whether IPV6_V6ONLY is available or what the default value is (turned on or off). So I find it's better to set it explicitly to what you want.
Also Windows XP doesn't support the option at all.
So if you want to be compatible across systems, it's recommended to create two sockets, one for v4 and one for v6 setting IPV6_V6ONLY.

Ip Address resolution using Mac Address programatically

I am writing a discovery program, written in C++ that will run on linux, to enable me to determine if certain devices are connected to the network. I have the Mac Address of the other devices and I need to resolve their Ip Addresses.
I have checked /proc/net/arp and the devices don't appear.
I tried pinging the broadcast address and this doesn't reach the target and therefore the ARP cache is not updated. However, if I ping the ip address directly it is (but this is not an option).
Also, the devices can be configured with either static ips or can get them via dhcp.
Is there any way that I can determine the ip addresses given the Mac addresses?
Some years ago I'd have suggested to use RARP but it is not supported by Linux kernel any more. Unless there is already a solution I would suggest you the following home-made solution:
-You can use Packet sockets to implement your own Layer 2 protocol: instead of using IP as payload of the Ethernet frame you can select your own protocol code (for example: instead of 0x0800 for IP use 0xABAB, always a number greater than 1536)
-In each node you implement a simple server that use packet socket to read the frames with that protocol code or you could use pcap, as you prefer.
-Whenever you need the IP address of another node you send an Ethernet frame to that MAC address. The server will read the new frame and respond with another frame conveying its own IP address.
-If you choose this solution please remember the payload has to be at least 46 Bytes long, so you may need to use padding. Also you can use the TLV (type length value) format for your own protocol.
Read this:
http://en.wikipedia.org/wiki/Ethernet_frame
http://man7.org/linux/man-pages/man7/packet.7.html
I hope this helps.

Select a listening addresses for IPv6 server (Dual stack)

It will be seem a weird question to some. but I've searched and didn't find any answer.
When I want a dual stack server, I need to listen on INADDR_ANY for IPv4 and to in6addr_any for IPv6.
If I have more than one network card then I need to choose if I want to listen to all, or to specify which card to listen.
For this exact propose I'm using getaddrinfo method with configurable host_name. If the host_name had not configured, then I call getaddrinfo with NULL, and get the two "ANY" addresses. If I configured it with an IP (v6 or v4) I get only one address, which is also fine.
But when I'm using my hostname as the configured host_name, on a Windows machine I'm getting from getaddrinfo 3 address: one IPv4 address, and two IPv6 address. the first is seen by ipconfig as "Link-local IPv6 Address" the second is seen as "IPv6 Address" under the section "Tunnel adapter 6TO4 Adapter:".
The addresses ordered like this:
IPv6 Link Local
IPv6 Address
IPv4
So, if I'm listening to all the addresses the dual stack is actually triple stack. If I take the first IPv6 address, (as it was the convention in IPv4 server with configured host_name) I'm listening only on the "Link-local IPv6 Address" which is less accessible than the "IPv6 Address" and many client can't connect to it, while they can connect to the IPv4 address.
Now I'm trying to complicate it further. I'm connected my cellphone to the USB and activate the USB Tethering. when I resolve addresses by getaddrinfo I'm getting 5 addresses:
by this order:
USB IPv6 Link Local
Ethernet IPv6 Link Local
IPv6 Address
USB IPv4
Ethernet IPv4
So my questions are:
If it was IPv4 only I would say I take only the first IPv4. and don't care about the rest. but when using IPv6, it look like the last IPv6 is the most appropriate. is there any convention for it?
If I have multi-network machine I need to choose the first network, and listen on both IPv4 and IPv6, but here the results are mixed. again, is there any convention?
Do I need to listen to all IPv6 addresses? in that case I will listen to an IPv6 address which I don't listen to the corresponding IPv4. and I hope to avoid from it.
Thanks for any help or comment.
But please don't advice to listen only on "ANY" since I can't.
Link-local addresses are valid only within a network segment and often just for your machine to the machine at the other end of the communication link. For instance, your USB link-local address will work only for communications between your phone and your computer but not beyond that; your link-local Ethernet IPv6 address will be usable from all machines on the same hub/switch but not beyond a router (somewhat similar to a private IPv4 address). If this is not your expected use case, I suggest that you simply ignore link-local addresses.
Auto-assigned link-local addresses are created with a very specific pattern and mask, so you can detect them programmatically. Link-local IPv6 addresses are in the fe80::/64 range (meaning the first bytes of the address are fe80:0000:0000:0000 and the 8 remaining bytes can be anything), and link-local IPv4 addresses range from 169.254.1.0 to 169.254.255.255.
Also note that all hosts configure all IPv6-capable interfaces with a link-local address, and will retain it even if they are assigned another address, so there's no getting away from it.
Old post, i know, how did you resolve it finally? I am really interested to know.
For this I would recommend the option you avoid, bind to ANY, wildcard "::" , bind(.., "::", ..) and use some firewall or pack filter rules to rule out the connections you don't want to.

How to support both IPv4 and IPv6 connections

I'm currently working on a UDP socket application and I need to build in support so that IPV4 and IPV6 connections can send packets to a server.
I was hoping that someone could help me out and point me in the right direction; the majority of the documentation that I found was not complete. It'd also be helpful if you could point out any differences between Winsock and BSD sockets.
Thanks in advance!
The best approach is to create an IPv6 server socket that can also accept IPv4 connections. To do so, create a regular IPv6 socket, turn off the socket option IPV6_V6ONLY, bind it to the "any" address, and start receiving. IPv4 addresses will be presented as IPv6 addresses, in the IPv4-mapped format.
The major difference across systems is whether IPV6_V6ONLY is a) available, and b) turned on or off by default. It is turned off by default on Linux (i.e. allowing dual-stack sockets without setsockopt), and is turned on on most other systems.
In addition, the IPv6 stack on Windows XP doesn't support that option. In these cases, you will need to create two separate server sockets, and place them into select or into multiple threads.
The socket API is governed by IETF RFCs and should be the same on all platforms including windows WRT IPv6.
For IPv4/IPv6 applications it's ALL about getaddrinfo() and getnameinfo(). getaddrinfo is a genius - looks at DNS, port names and capabilities of the client to resolve the eternal question of “can I use IPv4, IPv6 or both to reach a particular destination?” Or if you're going the dual-stack route and want it to return IPv4-mapped IPv6 addresses, it will do that too.
It provides a direct sockaddr * structure that can be plugged into bind(), recvfrom(), sendto() and the address family for socket()… In many cases this means no messy sockaddr_in(6) structures to fill out and deal with.
For UDP implementations I would be careful about setting dual-stack sockets or, more generally, binding to all interfaces (INADDR_ANY). The classic issue is that, when addresses are not locked down (see bind()) to specific interfaces and the system has multiple interfaces requests, responses may transit from different addresses for computers with multiple addresses based on the whims of the OS routing table, confusing application protocols—especially any systems with authentication requirements.
For UDP implementations where this is not a problem, or TCP, dual stack sockets can save a lot of time when IPv*-enabling your system. One must be careful to not rely entirely on dual-stack where it`s not absolutely necessary as there are no shortage of reasonable platforms (Old Linux, BSD, Windows 2003) deployed with IPv6 stacks not capable of dual stack sockets.
I've been playing with this under Windows and it actually does appear to be a security issue there, if you bind to the loopback address then the IPv6 socket is correctly bound to [::1] but the mapped IPv4 socket is bound to INADDR_ANY, so your (supposedly) safely local-only app is actually exposed to the world.
The RFCs don't really specify the existence of the IPV6_V6ONLY socket option, but, if it is absent, the RFCs are pretty clear that the implementation should be as though that option is FALSE.
Where the option is present, I would argue that it should default FALSE, but, for reasons passing understanding, BSD and Windows implementations default to TRUE. There is a bizarre claim that this is a security concern because an unknowing IPv6 programmer could bind thinking they were binding only to IN6ADDR_ANY for only IPv6 and accidentally accept an IPv4 connection causing a security problem. I think this is both far-fetched and absurd in addition to a surprise to anyone expecting an RFC-compliant implementation.
In the case of Windows, non-compiance won't usually be a surprise. In the case of BSD, this is unfortunate at best.
As Craig M. Brandenburg observes, getaddrinfo does all the heavy lifting to make dual IPv4/IPv6 possible. I have an experimental server and client on my localhost. I use this in the server:
hints.ai_family = AF_INET6;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = AI_PASSIVE;
...
The client can then connect to the server using any kind of address:
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
host_port = "4950"; // whatever
// All of these work.
host_ip = "127.0.0.1"; // Pure IPv4 address
host_ip = "::ffff:127.0.0.1"; // IPv4 address expressed as IPv6
host_ip = "::1"; // Pure IPv6 address
host_ip = "localhost"; // Domain name
int rv = getaddrinfo(host_ip, host_port, &hints, &result);
...