Reputation: 21
I am creating a UDP server-client program. Client requests a file and the server sends to client if found. Based on Beej's Guide to Networking,
- inet_ntoa() returns the dots-and-numbers string in a static buffer that is overwritten with each call to the function.
- inet_ntop() returns the dst parameter on success, or NULL on failure (and errno is set).
The guide mentions ntoa is deprecated so ntop is recommended since it supports IPv4 and IPv6.
On my code I am getting different results when I use function or the other and my understanding is that they should throw the same result. Anything I am missing? Any help would be greatly appreciated.
Code:
//UDP Client
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#define MAXBUFLEN 1024
#define SER_IP "176.180.226.0"
#define SER_PORT "1212"
// Get port, IPv4 or IPv6:
in_port_t get_in_port(struct sockaddr *sa){
if (sa->sa_family == AF_INET) {
return (((struct sockaddr_in*)sa)->sin_port);
}
return (((struct sockaddr_in6*)sa)->sin6_port);
}
int main(int argc, char *argv[]){
int sock, rv, numbytes;
struct addrinfo hints, *servinfo, *p;
char buffer[MAXBUFLEN];
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
rv = getaddrinfo(NULL, SER_PORT, &hints, &servinfo);
if (rv != 0){
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
exit(1);
}
// Printing IP, should provide same result
for(p = servinfo; p != NULL; p = p->ai_next) {
char str1[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &p->ai_addr, str1, INET_ADDRSTRLEN);
printf("ntop:%s\n", str1) ;
printf("inet_ntoa:%s \n", inet_ntoa(((struct sockaddr_in *)p->ai_addr)->sin_addr));
printf("\n");
}
exit(1);
}
Current output:
ntop:64.80.142.0
inet_ntoa:0.0.0.0
ntop:160.80.142.0
inet_ntoa:127.0.0.1
Upvotes: 2
Views: 10717
Reputation:
As per the man
page, in the case of AF_INET
the argument src
must point to a struct in_addr
(network byte order).
In your struct addrinfo
you have a pointer to struct sockaddr
which is basically
sa_family_t sa_family;
char sa_data[];
However, struct sockaddr_in
is
sa_family_t sin_family;
in_port_t sin_port;
struct in_addr sin_addr;
So, you need to replace
inet_ntop(AF_INET, &p->ai_addr, str1, INET_ADDRSTRLEN);
by either
inet_ntop(AF_INET, &p->ai_addr->sa_data[2], str1, INET_ADDRSTRLEN);
(the src
argument may be &p->ai_addr->sa_data[1 << 1]
to avoid the "magic number" 2
- the offset which counts for the port number storage)
or
inet_ntop(AF_INET, &((struct sockaddr_in *)p->ai_addr)->sin_addr, str1, INET_ADDRSTRLEN);
Then it will produce correct output.
Upvotes: 6