C unix domain sockets, recvfrom () does not set struct sockaddr * src_addr

I am writing an application that listens for UDP packets through a unix domain socket. Consider the following block of code.

int sockfd; struct sockaddr_un servaddr; sockfd = socket(AF_LOCAL, SOCK_DGRAM, 0); if(sockfd < 0) { perror("socket() failed"); } unlink(port); bzero(&servaddr, sizeof(servaddr)); servaddr.sun_family = AF_LOCAL; strcpy(servaddr.sun_path, port); if(bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) { perror("bind() failed"); close(sockfd); } int n; struct sockaddr_un cliaddr; socklen_t len = sizeof(cliaddr); discovery_msgs client_message; bzero(&client_message, sizeof(client_message)); // Wait for a message to be received n = recvfrom(sock_fd, &client_message, sizeof(client_message), 0, (struct sockaddr *) &cliaddr, &len); // At this point n = 560, client_message is filled with the expected data //len = 0 and cliaddr has no information about the client that sent the data 

Now the type client_message not very important, I get a UDP packet, and client_message contains all the data that I expect. The problem starts when I look at cliaddr and len after calling recvfrom . cliaddr does not change with recvfrom , as usual with a normal TCP / UDP network, and len set after 0 (0), which means that recvfrom did not write data to &cliaddr ). I need information in cliaddr to populate the unix domain path, so I can send a response.

What am I doing wrong?

+6
source share
1 answer

The solution binds a client-side socket when using Unix domain sockets. Otherwise, the transient path created to send the UDP packet immediately disappears after sendto() , which explains why the client address information is not available on the server side.

See p. 419 “Stevens Network Programming” or see this for an example client implementation that solves this problem: libpix.org/unp/unixdgcli01_8c_source.html

 #include "unp.h" int main(int argc, char **argv) { int sockfd; struct sockaddr_un cliaddr, servaddr; sockfd = Socket(AF_LOCAL, SOCK_DGRAM, 0); bzero(&cliaddr, sizeof(cliaddr)); /* bind an address for us */ cliaddr.sun_family = AF_LOCAL; strcpy(cliaddr.sun_path, tmpnam(NULL)); Bind(sockfd, (SA *) &cliaddr, sizeof(cliaddr)); bzero(&servaddr, sizeof(servaddr)); /* fill in server address */ servaddr.sun_family = AF_LOCAL; strcpy(servaddr.sun_path, UNIXDG_PATH); dg_cli(stdin, sockfd, (SA *) &servaddr, sizeof(servaddr)); exit(0); } 

Note. unp.h defines Bind() , which is just Bind() with some error checking (commonly used in all Stevens networking programs). Similarly, (SA *) equivalent to (struct sockaddr *) .

+6
source

Source: https://habr.com/ru/post/977624/


All Articles