I have a very simple question that I cannot seem to find an answer for anywhere:
Using Linux C sockets, is it possible to bind() and then recvfrom() UDP packets on an IP address other than the local address?
i.e, if a host has been given the LAN address 10.0.0.4, and I want it to be able to receive UDP packets sent to the address 10.0.0.5 on port 5505 (for example) how would this be achieved?
I simply cannot find any examples of this use of bind/recvfrom, which seems like it should be quite commonplace.
Update
I am trying to communicate packet streams between multiple hosts. Each host streams UDP packets on its own address, and any of the other hosts can listen in by recvfrom()ing on a specific address.
No, you can't generally bind to a non-local unicast address. On an Ethernet, such packets would be addressed to the hardware address of the owner of that IP address, and by default you NIC won't even forward such packets to your kernel.
You can achieve the effect you want by using IP Multicast. You would pick a particular multicast address for your application and bind to that, and then use the IP_ADD_MEMBERSHIP socket option to join the multicast group. You can then use recvfrom() in the usual way.
Related
I need to send a multicast udp from multihomed computer. Found that in case socket is not bound to some specific interface, default interface will be used (whatever it could mean). My question: is it possible to specify something like inaddr_any to send multicast udp from all available interfaces or is it only possible to do that by enumerating all interfaces and manually send from each? Is there a standard for that?
Thank you
You can set which network interface IPv4 multicast packets leave from by setting the IP_MULTICAST_IF socket option. The value passed to setsockopt should be the address of a struct in_addr containing the IP address of the interface in question.
If you want to send a multicast packet on multiple interfaces, you'll need to call sendto multiple times, setting the IP_MULTICAST_IF option before each one.
I'm attempting to have two daemons running on the same port and IP but one is a server and the other is a client. Is there a method using socket options that would allow each socket to have a copy of the packet and let the daemons filter out the messages based on the protocol? It looks like reuse address blocks the first configured port and reuse port might just balance the packet between the two daemons.
Otherwise, I guess create another daemons to read the socket and send the packets to the correct daemon.
Thanks
You are correct at the end, you will need to have a third part that binds to the port and forwards the packets to the correct daemon.
The other way to do it would be to use three ports and use a firewall to redirect from the front end port to the backend ports; but that is a lot more complicated and not portable. But in the end you could use QOS or something. There is a wide range of possible types of use case behind the word protocol.
If the UDP packets you are receiving are multicast or broadcast packets, then you can set SO_REUSEADDR (and, for BSD-based OS's, SO_REUSEPORT) on the socket (using setsockopt()) before bind()-ing the socket, and then both sockets will receive a copy of each incoming UDP packet. (If the UDP packets are regular old unicast packets, OTOH, then doing the above will result in each received packet being received by only one of the two UDP sockets, which isn't what you want).
Note, however: You refer to the two daemons as being a "client" and a "server" -- the implication of those terms is that the two daemons are going to communicate with each other. If that is the case, then the typical approach would be to have the server-daemon bind to a well-known port number, and the client-daemon could bind to any port number (e.g. it could pass 0 as the port-number to bind(), and let the OS choose an available port-number for it). Then the client-daemon could start the conversation by sending one or more UDP packets to the server's well-known port number, and the server can find out which port the client is sending from (and therefore what port to send reply packets to) by examining the fifth argument of its recvfrom() call. In this case there is no need for the two programs to bind to the same port, and therefore no need for packet-forwarding.
In network programming (C & Linux) with a TCP socket, how can I check the interface that received the packet. I know this can be done very easily with a SOCK_DGRAM and the IP option IP_PKTINFO, but this option does not work on SOCK_STREAM. In this case (for what im programming) I must know the interface that received the packet (the respond that gives back the server depends on that).
One possible solution that I found is to use SOCK_RAW and IPPROTO_TCP (with SOCK_RAW I can set the IP_PKTINFO option) but that implies that i'll be receiving all the TCP traffic that arrives to the machine and i don't want that. Another possible solution that I'm thinking is to check the destination IP against the routing table and get the exit interface from there but what about IPv6? What if the destiny IP its IPv6 link-local?
If anyone has another solution or idea I'll be glad to read it. Thanks in advance
When your TCP server accepted a client connection, you will have a socket to represent the connection, you could call getsockname on the socket, it will give you the address associated on the socket, namely the ip addresses on your side.
Next step, you can call getifaddrs to get all the interfaces and their information on your system, including name(like eth0) and ip address. At this point, you can search this list with the ip obtained previously via getsockname, you can get the interface you want as a result.
reference:
http://linux.die.net/man/2/getsockname
http://linux.die.net/man/3/getifaddrs
I found a multicasting example at http://ntrg.cs.tcd.ie/undergrad/4ba2/multicast/antony/example.html that is simple enough. In our network, we intend to run the client app as a daemon on each of the machines. However, the server needs to multicast files only to specific clients at a time.
Is there a way to extend multicasting to specific IP addresses? If so, how do I extend the server code to do so?
Otherwise, I am thinking I will initially send a packet that contains the list of acceptable IPs. If the client sees that its IP is not on the list, it will simply ignore the packets that follow. This might work as I have complete control over the server and the client code. Is this a reasonable strategy?
If you know you're only sending to a single IP, it's just as easy for the server to send to an unicast IP address as it is to send to a multicast IP address. The socket on the client side that is set up to read multicast packets can also receive unicast packets sent to it directly.
It's a matter of setting the sin_addr field in the struct sockaddr_in you're using to pass to sendto(). So if 230.1.2.3 is your multicast address and 192.168.1.2 is the specific client you want to send to, instead of this:
addr.sin_addr.s_addr=inet_addr("230.1.2.3");
You do this:
addr.sin_addr.s_addr=inet_addr("192.168.1.2");
The method of having the payload of the multicast packet containing the list of acceptable IPs is also a good solution. This will allow you the flexibility to send to a subset of clients that are listening. Just make sure the packet has a well defined format. Having an application header that contains the number of IPs listed and/or the offset of the main payload is a good way to handle this.
EDIT:
If you want something off the shelf that can multicast files reliably, you can use an application I created called UFTP. It also has a unicast mode if you need that.
I'm working on a client-server application written in C. I want to broadcast a message to all the machines available on the local network.
How can I do that using the usual socket system calls in C?
Just send the message to the broadcast address of your subnet, which for 192.168.0.0/24 is 192.168.0.255, or just broadcast to 255.255.255.255.
you have to use UDP to send a broadcast message over a network. when creating your socket using the socket() function, specify AF_INET for the family parameter and SOCK_DGRAM for the type parameter. on some systems, you have to enable the sending of broadcast packet by setting the SO_BROADCAST socket option to 1, using setsockopt().
then use the sendto() function call to send a datagram, and use 255.255.255.255 as the destination address. (for datagram sockets, you don't need to call connect(), since there is no 'connection').
in standard implementations, this address broadcasts to all computer in the local network, this means that the packet will not cross gateway boundaries and will not be received by computers using a network mask diferent from the network mask of the sending computer.
Have a look at UDP sockets.
I recomend Beej's Guide to Network Programming. Have a look at 6.3 Datagram Sockets
You can use the special address of 255.255.255.255 to send a broadcast message to every computer on the local network.
For more info see section IP Network Broadcasting.