On Thu, Nov 22, 2012 at 10:36:34PM +0100, Pablo Neira Ayuso wrote:
Hi Holger!
On Wed, Nov 07, 2012 at 03:21:14PM +0100, Holger Hans Peter Freyther wrote:
Dear Pablo,
getaddrinfo does not work for the combination of AF_INET, SOCK_RAW and IPPROTO_GRE. I have attached an example application that can be compiled with:
$ gcc -o fr fr.c `pkg-config --cflags --libs libosmocore libosmogb`
this prints: getaddrinfo returned NULL: Success FAILED
$ strace ./fr [...] socket(PF_NETLINK, SOCK_RAW, 0) = 3 bind(3, {sa_family=AF_NETLINK, pid=0, groups=00000000}, 12) = 0 getsockname(3, {sa_family=AF_NETLINK, pid=5936, groups=00000000}, [12]) = 0 sendto(3, "\24\0\0\0\26\0\1\3+\230\256P\0\0\0\0\0\0\0\0", 20, 0, {sa_family=AF_NETLINK, pid=0, groups=00000000}, 12) = 20 recvmsg(3, {msg_name(12)={sa_family=AF_NETLINK, pid=0, groups=00000000}, msg_iov(1)=[{"0\0\0\0\24\0\2\0+\230\256P0\27\0\0\2\10\200\376\1\0\0\0\10\0\1\0\177\0\0\1"..., 4096}], msg_controllen=0, msg_flags=0}, 0) = 108 recvmsg(3, {msg_name(12)={sa_family=AF_NETLINK, pid=0, groups=00000000}, msg_iov(1)=[{"@\0\0\0\24\0\2\0+\230\256P0\27\0\0\n\200\200\376\1\0\0\0\24\0\1\0\0\0\0\0"..., 4096}], msg_controllen=0, msg_flags=0}, 0) = 128 recvmsg(3, {msg_name(12)={sa_family=AF_NETLINK, pid=0, groups=00000000}, msg_iov(1)=[{"\24\0\0\0\3\0\2\0+\230\256P0\27\0\0\0\0\0\0\1\0\0\0\24\0\1\0\0\0\0\0"..., 4096}], msg_controllen=0, msg_flags=0}, 0) = 20
The interesting thing is that the function calls rtnetlink to obtain address information from the kernel, and it seems it gets it right.
Let me decipher that netlink trace:
bind(3, {sa_family=AF_NETLINK, pid=0, groups=00000000}, 12) = 0 ^^ bind this socket to rtnetlink
Send the request message to ask for the address information.
sendto(3, "\24\0\0\0\26\0\1\3+\230\256P\0\0\0\0\0\0\0\0", 20, 0, {sa_family=AF_NETLINK, pid=0, groups=00000000}, 12) = 20
- We get the multipart message with the information that we
requested:
recvmsg(3, {msg_name(12)={sa_family=AF_NETLINK, pid=0, groups=00000000}, msg_iov(1)=[{"0\0\0\0\24\0\2\0+\230\256P0\27\0\0\2\10\200\376\1\0\0\0\10\0\1\0\177\0\0\1"..., 4096}], msg_controllen=0, msg_flags=0}, 0) = 108 recvmsg(3, {msg_name(12)={sa_family=AF_NETLINK, pid=0, groups=00000000}, msg_iov(1)=[{"@\0\0\0\24\0\2\0+\230\256P0\27\0\0\n\200\200\376\1\0\0\0\24\0\1\0\0\0\0\0"..., 4096}], msg_controllen=0, msg_flags=0}, 0) = 128 recvmsg(3, {msg_name(12)={sa_family=AF_NETLINK, pid=0, groups=00000000},
The problem seems to be in glibc, at sysdeps/posix/getaddrinfo.c, line 125:
{ SOCK_RAW, 0, GAI_PROTO_PROTOANY|GAI_PROTO_NOSERVICE, true, "raw" }
The GAI_PROTO_NOSERVICE flag is set, while interating over the list of addresses that it has obtained from the kernel to return the addrinfo object, it seems to skip the raw protocol and it returns EAI_SERVICE.
To be more precise, it returns EAI_SERVICE before even iterating over the list of address.
This behaviour seems a bit inconsistent to me, ie. requst data from the kernel, get it all right and discard it :-)