Considering I have a
struct iphdr *ip_hdr;
and want to print saddr/daddr using printf.
Using two separate printf calls:
printf("received packet from %s\n",
inet_ntoa(*(struct in_addr*)&ip_hdr->saddr));
printf("received packet to %s\n",
inet_ntoa(*(struct in_addr*)&ip_hdr->daddr));
correctly prints the source/destination addr.
Why does
printf("received packet from %s to %s\n",
inet_ntoa(*(struct in_addr*)&ip_hdr->saddr),
inet_ntoa(*(struct in_addr*)&ip_hdr->daddr));
print use the source address for both the first and second placeholder (leading to incorrect output), and how can this be fixed?
The inet_ntoa
call returns a pointer to a static buffer, so the results of one call overwrite the results of a prior call.
The man page states as much:
The
inet_ntoa()
function converts the Internet host address in, given in network byte order, to a string in IPv4 dotted-decimal notation. The string is returned in a statically allocated buffer, which subsequent calls will overwrite.
So when you do this:
printf("received packet from %s to %s\n",
inet_ntoa(*(struct in_addr*)&ip_hdr->saddr),
inet_ntoa(*(struct in_addr*)&ip_hdr->daddr));
The two calls to inet_ntoa
both return the same pointer value, and whichever call happens to be done last (the C standard doesn't specify the order in which parameters are evaluated) will be the result printed for both cases.
You can either make two separate printf
calls as your first example does to work around this, or you can copy the results to one or more local buffers and print from those buffers.
char srcaddr[16], dstaddr[16];
strcpy(srcaddr, inet_ntoa(*(struct in_addr*)&ip_hdr->saddr));
strcpy(dstaddr, inet_ntoa(*(struct in_addr*)&ip_hdr->daddr));
printf("received packet from %s to %s\n", srcaddr, dstaddr);