Getting IP address from struct sockaddr doesn't work for 32bit compilation
I have a small client/server app that sends/receives UDP discovery packets. When a UDP packet is received I want to display the source IP. The client/server code is based on the UDP example from Beej: https:/开发者_如何学JAVA/beej.us/guide/bgnet/html/multi/clientserver.html
When I compile for 64bit the IP is displayed as expected but when I compile for 32bit (-m32 option) it doesn't get the right value at all.
Code snippit:
// get sockaddr, IPv4 or IPv6:
void *get_in_addr(struct sockaddr *sa)
{
if (sa->sa_family == AF_INET) {
return &(((struct sockaddr_in*)sa)->sin_addr);
}
return &(((struct sockaddr_in6*)sa)->sin6_addr);
}
...
printf("listener: waiting to recvfrom...\n");
addr_len = sizeof their_addr;
if ((numbytes = recvfrom(sockfd, buf, MAXBUFLEN-1 , 0,
(struct sockaddr *)their_addr, &addr_len)) == -1) {
perror("recvfrom");
exit(1);
}
printf("listener: got packet from %s\n",
inet_ntop(their_addr->sa_family,
get_in_addr((struct sockaddr *)their_addr),
s, sizeof s));
printf("Sockaddr: ");
for (i=0; i<sizeof(struct sockaddr_in); i++)
printf("%x ", ((char *)their_addr)[i]);
printf("\n");
Correct output when compiled for 64bit:
listener: waiting to recvfrom...
listener: got packet from 192.168.20.6
Sockaddr: 2 0 ffffff80 19 ffffffc0 ffffffa8 14 6 64 2e 40 0 0 0 0 0
Wrong output when compiled with -m32:
listener: waiting to recvfrom...
listener: got packet from 168.32.140.255
Sockaddr: 2 0 ffffff80 19 ffffffa8 20 ffffff8c ffffffff 50 ffffffdd 7d fffffff7 4 0 0 0
I don't really understand why there is a problem using get_in_addr or inet_ntop when compiling for 32bit?
addr_len
should be set to the size of the address structure, not the size of the pointer (it's happening to work in 64 bit mode, because pointers are twice as large in that mode). So it should be:
addr_len = sizeof *their_addr;
Incidentally, how is their_addr
initialised? There has to be a real structure to point to.
Aside from the bugs, this is a broken way to handle IP addresses. You should use getnameinfo
with the NI_NUMERICHOST
flag to get presentable forms of addresses. Then you don't have to care if it's v4 or v6, or even v7 or v8.
get_in_addr
isn't a standard function. Most likely your implementation does it wrong. Show the code.
精彩评论