c - sockaddr value changes unexpectedly after calling getaddrinfo() -
i programming udp client. want bind socket given port on client machine, same port used sends. sockaddr server using getaddrinfo, , same sockaddr pass call getaddrinfo. however, after second call getaddrinfo address of server machine changes, , end sending packet client machine client machine itself.
the following code standalone example reproduces error:
#include <stdio.h> #include <stdint.h> #include <unistd.h> #include <string.h> #include <stdlib.h> #include <time.h> #include <errno.h> #include <sys/types.h> #include <sys/socket.h> #include <netdb.h> #include <netinet/in.h> #include <arpa/inet.h> #define server_host "www.google.com" #define udp_port "4000" static struct sockaddr_in *destination_addr = null; static int client_port; int main(){ uint8_t bytes[5] = { 0xaa, 0xab, 0xac, 0xad, 0xaf}; //some data send uint16_t length = 5; int status; //initialize socket , bind if (destination_addr == null) { struct addrinfo hints; struct addrinfo *servinfo, *p; srand(time(null)); memset(&hints, 0, sizeof hints); hints.ai_family = af_inet; hints.ai_socktype = sock_dgram; hints.ai_flags = ai_passive; if ((status = getaddrinfo(server_host, udp_port, &hints, &servinfo)) != 0) { printf("unable send udp. reason: %s", gai_strerror(status)); return 0; } (p = servinfo; p != null; p = p->ai_next) { if (p->ai_addr != null) destination_addr = (struct sockaddr_in *) p->ai_addr; } client_port = 1027 + rand()%50000; freeaddrinfo(servinfo); printf("created destination_addr ip %s\n", inet_ntoa(destination_addr->sin_addr)); } int send_socket_fd = socket(af_inet, sock_dgram, 0); if (send_socket_fd == -1) { printf("unable create udp socket. reason: %s", strerror(errno)); return 0; } printf("ip after socket creation %s\n", inet_ntoa(destination_addr->sin_addr)); int yes = 1; if (setsockopt(send_socket_fd, sol_socket, so_reuseaddr, &yes, sizeof (int)) == -1) { perror("setsockopt"); return 0; } printf("ip after sockopt %s\n", inet_ntoa(destination_addr->sin_addr)); // bind local address char str_client_port[6]; snprintf(str_client_port, 5, "%d", client_port); struct addrinfo *source_addr_info; struct addrinfo hints; hints.ai_family = af_inet; hints.ai_socktype = sock_dgram; // ***** destination_addr changes after call ***** getaddrinfo (null, str_client_port, &hints, &source_addr_info); printf("ip after getaddrinfo %s\n", inet_ntoa(destination_addr->sin_addr)); bind(send_socket_fd, source_addr_info->ai_addr, source_addr_info->ai_addrlen); printf("ip after binding %s\n", inet_ntoa(destination_addr->sin_addr)); // send int bytes_sent = sendto(send_socket_fd, bytes, length, 0, (struct sockaddr *)destination_addr, sizeof *destination_addr); printf("sent ip %s\n", inet_ntoa(destination_addr->sin_addr)); if (bytes_sent != length){ if (bytes_sent == -1){ printf("udp send failed. reason: %s", strerror(errno)); } else { printf("udp: not bytes sent."); } } close(send_socket_fd); return 1; }
the output generated execution of program in machine is:
created destination_addr ip 64.233.167.105 ip after socket creation 64.233.167.105 ip after sockopt 64.233.167.105 ip after getaddrinfo 0.0.0.0 ip after binding 0.0.0.0 sent ip 0.0.0.0
i rather new socket programming in c, , pretty sure doing silly mistake, after googling lot , trying many things, still stuck this. idea?
solved. @molbdnilo pointed out, error caused call freeaddrinfo
. fix copy value pointed p->ai_addr
, not lost when freeing. substituted:
if (p->ai_addr != null) destination_addr = (struct sockaddr_in *) p->ai_addr;
with
if (p->ai_addr != null){ destination_addr = malloc(sizeof *destination_addr); memcpy(destination_addr, (struct sockaddr_in *)p->ai_addr, sizeof *p->ai_addr); }
and worked.
Comments
Post a Comment