How to multicast to specific IP addresses? - c

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.

Related

Can a RAW socket be bound to an ip:port instead of an interface?

I need to write a proxy server in C language on Linux (Ubuntu 20.04). The purpose of this proxy server is as follows. There're illogical governmental barriers in accessing the free internet. Some are:
Name resolution: I ping telegram.org and many other sites which the government doesn't want me to access. I ask 8.8.8.8 to resolve the name, but they response of behalf of the server that the IP may be resolved to 10.10.34.35!
Let's concentrate on this one, because when this is solved many other problems will be solved too. For this, I need to setup such a configuration:
A server outside of my country is required. I prepared it. It's a VPS. Let's call it RS (Remote Server).
A local proxy server is required. Let's call it PS. PS runs on the local machine (client) and knows RS's IP. I need it to gather all requests going to be sent through the only NIC available on client, process them, scramble them, and send them to RS in a way to be hidden from the government.
The server-side program should be running on RS on a specific port to get the packet, unscramble it, and send it to the internet on behalf of the client. After receiving the response from the internet, it should send it back to the client via the PS.
PS will deliver the response to the client application which originates the request. Of course this happens after it will unscramble and will find the original response from the internet.
This is the design and some parts is remained gloomy for me. Since I'm not an expert in network programming context, I'm going to ask my questions in the parts I'm getting into trouble or are not clear for me.
Now, I'm in part 2. See whether I'm right. There're two types of sockets, a RAW socket and a stream socket. A RAW socket is opened this way:
socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
And a stream socket is opened this way:
socket(AF_INET, SOCK_STREAM, 0);
For RAW sockets, we use sockaddr_ll and for stream sockets we use sockaddr_in. May I use stream sockets between client applications and PS? I think not, because I need the whole RAW packet. I should know the protocol and maybe some other info of the packet, because the whole packet should be retrieved transparently in RS. For example, I should know whether it has been a ping packet (ICMP) or a web request (TCP). For this, I need to have packet header in PS. So I can't use a stream socket, because it doesn't contain the packet header. But until now, I've used RAW sockets for interfaces and have not written a proxy server to receive RAW packets. Is it possible? In another words, I've the following questions to go to next step:
Can a RAW socket be bound to localhost:port instead of an interface so that it may receive all low-level packets containing packet headers (RAW packets)?
I may define a proxy server for browser. But can I put the whole system behind the proxy server so that packets of other apps like PING may route automatically via it?
Do I really need RAW sockets in PS? Can't I change the design to suffice the data I got from the packets payload?
Maybe I'm wrong in some of the concepts and will appreciate your guidance.
Thank you
Can a RAW socket be bound to localhost:port instead of an interface so that it may receive all low-level packets containing packet headers (RAW packets)?
No, it doesn't make sense. Raw packets don't have port numbers so how would it know which socket to go to?
It looks like you are trying to write a VPN. You can do this on Linux by creating a fake network interface called a "tun interface". You create a tun interface, and whenever Linux tries to send a packet through the interface, instead of going to a network cable, it goes to your program! Then you can do whatever you like with the packet. Of course, it works both ways - you can send packets from your program back to Linux through the tun interface, and Linux will act like they just arrived on a network cable.
Then, you can set up your routing table so that all traffic goes to the tun interface, except for traffic to the VPN server ("RS"), which goes to your real ethernet/wifi interface. Otherwise you'd have an endless loop where your VPN program PS tried to send packets to RS but they just went back to PS.

UDP - Multi-server single client

I have a linux computer with a code in C that must communicate in UDP with 4 differents equipments. The computer sends differents commands to each equipment and receives responses, sometimes in parallel ...
I am a perfect beginner, and managed to communicate with one equipment using UDP socket. But now, i'm looking for a way to communicate with all these equipments, what i would like to call "multiple socket", but i don't know where to look/ what word to search to find a way ...
My linux computer is the client and all the equipment servers. I only have one eth port on the computer and will have to use a switch to have access to all the equipment. I would like to create functions like :
sendcmd(IPnumber, PORTnumber, cmd , ...)
readbuff(IPnumber, PORTnumber, buff, ...)
so i can choose which IP will received cmd ... i don't know if it's possible or if i need to open the socket, then close and redo the operation with another IP ...
So, if I ever managed to make myself understood, where should I look for a solution to my problem?
Thank you !
You can use a single UDP socket for your scenario. You can keep the socket open for the lifetime of your application.
UDP is not connection oriented. UDP sockets are also not classified into client sockets and server sockets. UDP sockets are always bound to a local port, either implicitly (typically for pure clients) or explicitly (which is usually the case for servers). In your case you do not care about the port for your UDP client.
To send to your four UDP server you can use sendto(). This lets you specify the destination IP address and port the UDP packet gets sent to.
To receive from your four UDP servers you can use recvfrom(). This will tell the IP address and port where the UDP packet came from.
You most likely want to have a receive loop of some kind. If you want to do anything else in your application you most likely want to either make recvfrom() non-blocking or you want to have the receive loop in its own thread. But this goes beyond your question.
The most important aspect of UDP is that it is not a protocol (despite its name which is misleading). It is one puzzle piece for a protocol. It is a tool to develop your own protocol. But I assume you already have a specific protocol at hand defined by your peripherals.

Get all hosts on LAN network in C?

Is it possible to get all the hosts on a LAN network(using C). I need to get the IP addresses and host names.
As explained in this answer, the to ping all hosts in your subnet and see which respond or access the ARP cache. The first approach is accomplished by creating a raw socket using
int sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP));
However, raw sockets basically give you only the IP header so you need to construct the ICMP echo packet yourself. After you constructed it, then you just send them to every IP in the subnet using sendto() and wait for response. For the second approach I suggest reading something like this.
As for determining the host names, it depends on whether the hosts have DNS or NETBIOS names. If you have a DNS configured on your LAN, you may get away with calling getaddrinfo() on the the addresses that respond. Unfortunately, I do not have any idea how to find out the NETBIOS name of any given IP.

Network Discovery of Servers

Ok, so I understand that communication between a client computer and a server computer can be initiated in windows with the creation of a socket between the two computers, but every tutorial that I have seen depends on the End User knowing the IP address of the computer that they wish to connect to.
In local network LAN games, however, the clients somehow autodetect the server. How is this done? Does the client autocheck every possible IP, is there some sort of "GetDetectedIPs" api, etc?
Im looking for answers that can be implemented in standard WIN32 API in straight C. No MFC, .NET, or C++ please. Thank you.
The technique you need is called broadcasting. It's used, for example, in BOOTP and DHCP protocols.
Sending a packet with broadcast destination address results in it being received by all devices in LAN. Broadcast address is an IP address in which the host identification field is filled with ones:
bcast_addr = ~netmask | my_addr;
The discovery process is usually like follows:
The client sends a UDP datagram with broadcast destination address at specific port.
The server listens on this port and receives the datagram. Other computers discard it.
Server sends all the necessary info about itself to the client by a usual UDP datagram.
This is usually done with zero-conf. Microsoft version of it is Simple Service Discovery Protocol.
You could just let the client send an UDP packet to every IP in a specified range and let the server answer with another UDP packet.

Filtering UDP loopback on Linux in C

I have an application bound to eth0, sending UDP packets on port A to 255.255.255.255. At the same time, I have a UDP server bound to eth0, 0.0.0.0 and port A.
What I want to do is to make sure that the server won't receive messages generated by the application (handled purely in software by the kernel) but it will receive messages generated by other hosts in the network.
I can't change the payload of UDP packets nor add any headers to it.
I've already implemented a solution using RTNETLINK to fetch all IP addresses of the machine I'm sitting on (and filter basing on address from recvfrom()), but I'm wondering if there might be a simpler and cleaner solution.
EDIT: I thought about something like tagging the skb - the tag would disappear after leaving a physical interface, but wouldn't if it's just routed in the software.
Any ideas?
If you can patch your Linux kernel, you could use a setsockopt() option for choosing if you want to loopback the broadcast packets you're sending or not.
This patch reuse the IP_MULTICAST_LOOP option exactly for this purpose.
Also, instead of "messing" with the IP_MULTICAST_LOOP option, you could easily add your own setsockopt() option, maybe called IP_BROADCAST_NO_LOOP. This would guarantee that you're not changing the behavior for any other application.
You can compute a checksum or CRC (better) over the payload and filter against this.
You can do this at the firewall level by dropping packets to broadcast address port A with source address of the eth0.

Resources