UDP packets not delivered - recvfrom() never returns - c

I have setup a UDP receiver, as:
int rx_socket;
struct sockaddr_in my_addr;
struct sockaddr_in rem_addr;
socklen_t addrlen = sizeof(rem_addr);
rx_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(9900);
rc = bind(rx_socket, (struct sockaddr *) &(my_addr), sizeof(my_addr));
if (!rc) {
printf("BIND SUCCESSFULL\n");
}
char buf[250];
while(1) {
printf("WAITING\n");
recvfrom(rx_socket, buf, sizeof(buf), 0, (struct sockaddr *)&rem_addr, &addrlen);
printf("RECEIVED\n");
}
The recvfrom() never returns. I have done some Wireshark analysis, and it indicates the packets are there:
Summary:
User Datagram Protocol, Src Port: 57506 (57506), Dst Port: iua (9900)
Checksum: 0x14a2 [validation disabled]
Data (8 bytes)
Any help will be appreciated.
EDIT:
An interesting observation is that the source, which is a DSP fails to send packets, i.e., sendto() returns -1, until I ping to it, from destination. Right after the ping, the source can start transmitting packets.
EDIT 2:
Here is the sender's code:
int fd;
fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
struct sockaddr_in my_addr;
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(9900);
inet_aton("10.0.201.102", &(my_addr.sin_addr));
char buf[250];
for (;;) {
int bytesSent = sendto(fd, buf, 8, 0,
(struct sockaddr *) &(my_addr), sizeof(my_addr));
printf("sent: %d bytes\n", bytesSent);
sleep(1000);
}

So the problem turned out to be with virtualbox. My sender is on host, but receiver is on a virtual machine. If I run the receiver on the host as well, UDP packets are being received.

Related

Socket Programming (Client - Server UDP)

I would like to build a client - server model where, for any number of clients connected to the server, the server should send a broadcast Message. Below is the code which I implemented, it does not throw any error, but I could not see any communication happening between the server and the client. Please let me know, where is the problem in the code.
I would like to see the message passed from the server on the clients system.
/************* UDP SERVER CODE *******************/
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char *argv[]){
int udpSocket, nBytes, buflen;
char buffer[1024];
char string[1024];
int portNum;
struct sockaddr_in serverAddr, clientAddr;
struct sockaddr_storage serverStorage;
socklen_t addr_size, client_addr_size;
int i;
/*Create UDP socket*/
udpSocket = socket(AF_INET, SOCK_DGRAM, 0);
portNum=atoi(argv[1]);
/*Configure settings in address struct*/
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(5000);
serverAddr.sin_addr.s_addr = inet_addr("192.168.1.117");
memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);
/*Bind socket with address struct*/
int bStatus=bind(udpSocket, (struct sockaddr *) &serverAddr, sizeof(serverAddr));
if (bStatus < 0) {
printf("error binding on server's port number\n");
exit(1);
}
/*Initialize size variable to be used later on*/
addr_size = sizeof serverStorage;
memset(&clientAddr, 0, sizeof(clientAddr));
clientAddr.sin_family = AF_INET;
clientAddr.sin_port = htons(portNum); // this is where client is bound
clientAddr.sin_addr.s_addr = inet_addr("192.168.1.114");
while(1){
sprintf(buffer,"Hello Client");
buflen=strlen(buffer);
int bytesSent = sendto(udpSocket,buffer,buflen,0,(struct sockaddr *)&clientAddr, sizeof(clientAddr));
if (bytesSent < 0) {
printf("Error sending/ communicating with client\n");
exit(1);
}
printf("%s\n",buffer);
/*
// ****************************************************
memset(buffer, 0, 1024);
buflen=65536;
recvfrom(udpSocket,buffer,buflen,0,(struct sockaddr *)&serverStorage, &addr_size);
printf("Received from server: %s\n",buffer);
*/
}
return 0;
}
Below is the client code :
/************* UDP CLIENT CODE *******************/
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
int main(int argc, char *argv[]){
int clientSocket, portNum, nBytes, buflen;
char buffer[1024];
char string[1024];
struct sockaddr_in serverAddr,clientAddr;
socklen_t addr_size;
/*Create UDP socket*/
clientSocket = socket(AF_INET, SOCK_DGRAM, 0);
portNum = atoi(argv[1]);
/*Configure settings in address struct*/
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(portNum);
serverAddr.sin_addr.s_addr = inet_addr("192.168.1.117");
// memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);
memset(&serverAddr,0,sizeof(serverAddr));
// binding
bind(clientSocket, (struct sockaddr *) &clientAddr, sizeof(clientAddr));
/*Initialize size variable to be used later on*/
addr_size = sizeof serverAddr;
while(1){
memset(buffer, 0, 1024);
buflen=65536;
recvfrom(clientSocket,buffer,buflen,0,(struct sockaddr *)&serverAddr, &addr_size);
//recvfrom(clientSocket,buffer,buflen,0,NULL,NULL);
printf("Received from server: %s\n",buffer);
/*
//********************************************************************
sprintf(buffer,"Hello Client");
buflen=strlen(buffer);
sendto(clientSocket,buffer,buflen,0,(struct sockaddr *)&serverAddr,addr_size);
printf("%s\n",buffer);
*/
}
return 0;
}
At a high level there are a few things that need to be addressed. Given the code in the post has a server that initiates communication with the client following line needs to be modified (and related code for these)
On the server side:
sendto(udpSocket,buffer,buflen,0,(struct sockaddr *)&serverStorage,addr_size);
Essentially what's happening here is that udpSocket is bound to serverAddr and we are trying to sendto serverStorage (2nd last argument). The trouble here is that the serverStorage is not bound to anything. Basically sendto has the source right but not the destination.
On the client side:
recvfrom(clientSocket,buffer,buflen,0,(struct sockaddr *)&serverAddr, &addr_size);
The clientSocket is not bound to anything so the system picks a random port where it will listen. In the recvfrom call, 2nd last argument captures the address details of the other side. Whereas in the code you have bound it to server's IP and port, it does not have any effect because it is filled in by the recvfrom call and returned.
To make things work here is what I'd suggest (you can add the details but have worked out the skeleton based on what you posted)
server_initiating_with_client.c
//...
int udpSocket, nBytes, buflen;
char buffer[1024];
int portNum;
struct sockaddr_in serverAddr, clientAddr;
struct sockaddr_storage serverStorage;
socklen_t addr_size, client_addr_size;
/*Create UDP socket*/
udpSocket = socket(AF_INET, SOCK_DGRAM, 0);
portNum=atoi(argv[1]);
/*Configure settings in address struct*/
memset(&serverAddr, 0, sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(5000); // Making sure server has a unique port number
serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
/*Bind socket with address struct*/
int bStatus = bind(udpSocket, (struct sockaddr *) &serverAddr, sizeof(serverAddr));
if (bStatus < 0) {
printf("error binding on server's port number\n");
exit(1);
}
/*Initialize size variable to be used later on*/
addr_size = sizeof serverStorage;
/* Because server is initiating the communication here one needs to set the
* clientAddr and needs to know the port number of the client
*/
memset(&clientAddr, 0, sizeof(clientAddr));
clientAddr.sin_family = AF_INET;
clientAddr.sin_port = htons(portNum);
clientAddr.sin_addr.s_addr = htonl(INADDR_ANY);
while(1){
sprintf(buffer,"Hello Client");
buflen=strlen(buffer);
int bytesSent = sendto(udpSocket,buffer,buflen, 0,
(struct sockaddr *)&clientAddr,
sizeof(clientAddr));
if (bytesSent < 0) {
printf("Error sending/ communicating with client\n");
exit(1);
}
printf("Done sending %s\n", buffer);
sleep(1);
}
..
and on the client side something along these lines
//..
int clientSocket, portNum, nBytes, buflen;
char buffer[1024];
struct sockaddr_in serverAddr;
struct sockaddr_in clientAddr;
socklen_t addr_size;
/*Create UDP socket*/
clientSocket = socket(PF_INET, SOCK_DGRAM, 0);
portNum = atoi(argv[1]);
/*Configure settings in address struct*/
memset(&clientAddr, 0, sizeof(clientAddr));
clientAddr.sin_family = AF_INET;
clientAddr.sin_port = htons(portNum);
clientAddr.sin_addr.s_addr = htonl(INADDR_ANY);
memset(&serverAddr, 0, sizeof(serverAddr));
/*Bind on client side as well because you are specifically sending something over
* to the client. Usually the server will know where to talk back to the client
* but in your example because of the reversed semantics this will be needed
*/
bind(clientSocket, (struct sockaddr *) &clientAddr, sizeof(clientAddr));
/*Initialize size variable to be used later on*/
addr_size = sizeof serverAddr;
while(1){
memset(buffer, 0, 1024);
buflen=65536;
recvfrom(clientSocket,buffer,buflen,0,(struct sockaddr *)&serverAddr, &addr_size);
printf("Received from server: %s\n",buffer);
sleep(1);
}
return 0;
The code can be simplified if you reverse your comm from client to server, thereby, eliminating the need for a fixed port number on the client side.
just make a few changes in it. Assign a socket length predefined (socklen_t *) structure to typecast length
n = recvfrom(sockfd, (char *)buffer, MAXLINE,MSG_WAITALL, (struct sockaddr *) &servaddr, (socklen_t*)&len);
socklen_t* convert a length into socket length.
Make these changes at both client-side as well as a server-side
.

Cannot receive the message of udp broadcast

I wrote a simple UDP broadcast sample. When I write the IP address to the struct sockaddr_in with inet_addr("192.168.152.128"), I cannot receive the message from another UDP broadcast program with the broadcast 192.168.152.255. But when I write htonl(INADDR_ANY), it can receive the message. Why could that be?
This the code:
#include"myhead.h"
char rbuf[50];
char wbuf[50];
int main()
{
int udp, size, len, opt = 1;
struct sockaddr_in laddr;
struct sockaddr_in raddr;
laddr.sin_family = AF_INET;
laddr.sin_port = htons(8888);
laddr.sin_addr.s_addr = htonl(INADDR_ANY);
//when i write inet_addr("192.168.152.128")
//it cannot receive the message.
size = sizeof(struct sockaddr_in);
udp = socket(AF_INET, SOCK_DGRAM, 0);
setsockopt(udp, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof opt);
bind(udp, (struct sockaddr*)&laddr, size);
len = sizeof(struct sockaddr);
while (1)
{
recvfrom(udp, rbuf, 50, 0, (struct sockaddr*)&raddr, &len);
printf("%s\n", rbuf);
bzero(rbuf, 50);
}
}

C listen to multicast on all interfaces, respond on same as recieved

I am trying to listen to multicast on all interfaces in system, but responds only on this on which I've received multicast packet.
What I've did is to create a socket for each of the interfaces and here the problems starts.
When I bind interface to INADDR_ANY it will receive packets for all interfaces and send on default one. If I bind port to specific interface it will not receive multicast packet (but it will be able to send it on correct interface).
I've tried setting options like IP_ADD_MEMBERSHIP or IP_MULTICAST_IF but without success.
I think the other options whould be to create one socket to receive on all ifs and senders sockets for all interfaces, but on this approach I have no idea on which ifs packet entered...
Code samples (simplified, without error handling and stuff):
Creating socket:
//here i am looping over all interfaces from getifaddrs
struct sockaddr_in *pAddr = (struct sockaddr_in *)tmp->ifa_addr;
sockets[i] = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
setsockopt(sockets[i], SOL_SOCKET, SO_REUSEADDR, &optval, sizeof optval);
mreq.imr_multiaddr.s_addr=inet_addr(MDNS_ADDRESS);
mreq.imr_interface.s_addr=pAddr->sin_addr.s_addr;
setsockopt(sockets[i], IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
setsockopt(sockets[i], IPPROTO_IP, IP_MULTICAST_IF, &pAddr, sizeof(struct in_addr));
memset(&my_addr, 0, sizeof(struct sockaddr_in));
my_addr.sin_family = AF_INET;
my_addr.sin_addr.s_addr = INADDR_ANY; //or pAddr->sin_addr.s_addr;
my_addr.sin_port = htons(port);
bind(sockets[i], (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1);
Receiving and sending:
recvfrom(sockfd, buf, MAXBUFLEN-1 , 0, (struct sockaddr *)&their_addr, &addr_len);
//do some magic and response (response should be a multicast too)
destination.sin_addr.s_addr = inet_addr(MULTICAST_ADDRESS);
destination.sin_family = AF_INET;
destination.sin_port = htons( port );
sendto(sockfd, buffer, len, 0, (struct sockaddr *)&destination, sizeof destination);
I would like to create something similar in work to mDNS so when packet entered on specific interface program should answer on the same if with some data about this if. It should not send this on other ifs as it may not be relevant for them, but it should send it as multicast so any other host in same network will receive the respond.
You should only need one socket for this.
First bind to INADDR_ANY and your port of choice. Then call setsockopt with IP_ADD_MEMBERSHIP on each interface you want to receive multicast on. Finally, call setsockopt with IP_MULTICAST_IF on the interface you want to send multicast on. Make sure to check for errors on each call.
int socket s;
struct sockaddr_in sin;
struct ip_mreq mreq;
struct in_addr out_addr;
bzero(&sin,sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr=htonl(INADDR_ANY);
sin.sin_port = htons(1044); // or whatever port you listen on
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
perror("socket failed");
exit(1);
}
if (bind(s, (struct sockaddr *)&sin, sizeof(sin))==-1) {
perror("bind failed");
exit(1);
}
// Do this in a loop for each interface
mreq.imr_multiaddr = inet_addr("230.4.4.1"); // your multicast address
mreq.imr_interface = inet_addr("192.168.1.1"); // your incoming interface IP
if (setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&mreq, sizeof(mreq)) == -1) {
perror("Error joining multicast group");
exit(1);
}
out_addr.s_addr = inet_addr("192.168.1.1"); // your outgoing interface IP
if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, (char *)&out_addr,sizeof(out_addr))== -1) {
perror("Error setting outgoing interface");
exit(1);
}
When using multicast, you should always bind to the INADDR_ANY address. Failure to do so breaks multicast on Linux systems.
Initially, I accepted #dbush answer as it allowed me to get on right track. For sake of completeness I post more detailed answer and as suggested by him I accepted my own answer.
Some of the code was found here: Setting the source IP for a UDP socket
I was able to do all of this with single socket and setting IP_PKTINFO.
Code samples (simplified, without error handling and stuff):
Creating socket:
if ((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP)) == -1) {
perror("socket");
exit(1);
}
if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof optval) < 0) {
perror("setsockopt");
exit(1);
}
optval2 = 1;
if(setsockopt(sockfd, IPPROTO_IP, IP_PKTINFO, &optval2, sizeof(optval2)) < 0) {
perror("setsockopt");
exit(1);
}
memset(&my_addr, 0, sizeof(struct sockaddr_in));
my_addr.sin_family = AF_INET;
my_addr.sin_addr.s_addr = INADDR_ANY;
my_addr.sin_port = htons(5353);
if (bind(sockfd, (struct sockaddr *)&my_addr,
sizeof(struct sockaddr)) == -1) {
perror("bind");
exit(1);
}
Receiving and responding:
char buf[MAXBUFLEN];
char cmsgbuf[MAXBUFLEN];
struct iovec iov[1];
iov[0].iov_base=buf;
iov[0].iov_len=sizeof(buf);
struct cmsghdr *cmsg;
struct msghdr message;
message.msg_name=&their_addr;
message.msg_namelen=sizeof(their_addr);
message.msg_iov=iov;
message.msg_iovlen=1;
message.msg_control=cmsgbuf;
message.msg_controllen=MAXBUFLEN;
if ((numbytes = recvmsg(sockfd, &message, 0)) == -1) {
perror("recvfrom");
exit(1);
}
for (cmsg = CMSG_FIRSTHDR(&message); cmsg != NULL; cmsg = CMSG_NXTHDR(&message, cmsg)) {
// ignore the control headers that don't match what we want
if (cmsg->cmsg_level != IPPROTO_IP ||
cmsg->cmsg_type != IP_PKTINFO)
{
continue;
}
struct in_pktinfo *pi = CMSG_DATA(cmsg);
addr = pi->ipi_spec_dst.s_addr;
}
//DO SOME MAGIC
//HERE WE ARE SETTING ADDR - INTERFACE WITH THIS ADDR WILL SEND MULTICAST
sock_opt_addr.s_addr = addr;
setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_IF, &sock_opt_addr, sizeof(sock_opt_addr));
sendto(sockfd, buffer, len, 0, (struct sockaddr *)&destination, sizeof destination);

C unix domain sockets, recvfrom() doesn't set struct sockaddr* src_addr

I'm writing an application that listens for UDP packets over a unix domain socket. Consider the following code block.
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 of client_message isn't really important, I'm receiving a UDP packet and client_message contains all of the data I expect. The problem begins when I look at cliaddr and len after calling recvfrom. cliaddr is not modified by recvfrom like it normally is with normal network TCP/UDP and len is set to 0 after the call(which means recvfrom wrote no data to &cliaddr). I need the information in cliaddr to be populated with the unix domain path so I can send a response.
What am I doing wrong?
The solution is binding the socket on the client side when using Unix domain sockets. Otherwise the transient pathname created for sending the UDP packet immediately disappears after sendto(), which explains why the client's address information is not available on the server side.
See Stevens Network Programming page 419 or see this for an example client implementation that solves this issue: 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's 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 simply bind() with some error checking(commonly used throughout Stevens Network Programming). In the same manner, (SA *) is the equivalent to (struct sockaddr *).

Packet received in NIC not read via socket

I have opened an UDP socket to listen to incoming packet. I could see in the wireshark log the packets reaching the NIC. But the same is not available when reading via Socket. The 'netsatat ' command shows the port number is listened for the any incoming UDP messages. The socket reader keeps on waiting . I have checked using Java and C, in Linux(ubuntu) environment. I can see the Identification value for received IPV4 packet is 0. Is this value can play any role for a socket to read the data ?
My C code for reading the socket
int sock, n, nr;
socklen_t fromlen;
struct sockaddr_in server;
struct sockaddr_in from;
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0)
printf("Can not create socket in server\n");
memset(&server, 0, sizeof(struct sockaddr_in));
server.sin_family = AF_INET;
server.sin_port = htons(5555);
server.sin_addr.s_addr = INADDR_ANY;
if(bind(sock, (struct sockaddr *)&server, sizeof(server)) < 0)
fromlen = sizeof(struct sockaddr_in);
while(1) {
printf("Waiting to receive\n");
n = recvfrom(sock, &nr, sizeof(nr), 0, (struct sockaddr *) &from, &fromlen);
printf("I have received");
}
Please find the wireshark trace http://imgur.com/Au9BeS1
This is a problem:
if(bind(sock, (struct sockaddr *)&server, sizeof(server)) < 0)
fromlen = sizeof(struct sockaddr_in);
This will only set fromlen is the bind call fails. And since fromlen is not properly initialized, it will contain a seemingly random value that is not valid for recvfrom.

Resources