I am doing some socket programming and have run across something that I can deal with, but it is annoying.
The distro is Mandriva 2008. Basically, I am trying to write some protocol agnostic code, with the goal of handling either ipv6 or ipv4, whichever comes up.
At this point, I am writing some server code that is listening on a port for a connection, and then is connecting, passing some data back and forth, then upon command shutting down. Vanilla stuff.
At this time, I am communicating with this server code via telnet across my LAN from another Mandriva machine. The networking code is based on the libunp.a code that is provided in the book Unix Network Programming Second Edition by Richard Stevens. I am using it because I have a lot of working code that is based on it.
When I set up the listener socket on the server, I do it like this:
hints.ai_flags = AI_PASSIVE;
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
if ( (n = getaddrinfo(host, serv, &hints, &res)) != 0)
err_quit("tcp_listen error for %s, %s: %s",
host, serv, gai_strerror(n));
At a later time, the server accepts a communication from my other machine via telnet based upon this code:
struct sockaddr *cliaddr;
commandfd = Accept(listenfd, cliaddr, &addrlen);
where Accept is a wrapper subroutine that calls accept.
Immediately after this, I want to get the IP address of the client that has contacted me. So I do this:
namelen = INET6_ADDRSTRLEN;
get_ip_str(cliaddr, &s, namelen);
printf("new client: connecting to %s\n", s);
where the subroutine get_ip_str() is defined as:
char *get_ip_str(const struct sockaddr *sa, char *s, size_t maxlen)
inet_ntop(AF_INET, &(((struct sockaddr_in *)sa)->sin_addr),
inet_ntop(AF_INET6, &(((struct sockaddr_in6 *)sa)->sin6_addr),
strncpy(s, "Unknown AF", maxlen);
Now, my network is defined using IPv4 and I rather expected to have an IPv4 definition provided for me. But when I execute the program and print out the result of my network address search, this is what I get:
new client: connecting to ::ffff:192.168.0.2
You can see that the correct IPv4 address is buried in the IPv6 field, but in fact my socket has been declared as IPv6.
This is not a huge problem; I can always parse the string, but I am wondering what this means, and why I am not getting the proper IPv4 definition when the network is configured that way.
Also, of course, this could cause me some issues actually identifying that I am really on an IPv6 network, if I make the necessary hack to assume this is an IPv4 network regardless of what the socket says.
Does anyone know what I can do to get this to behave properly?