UDP multicasting: how do I know which group to send to? - c

I've got a little program that needs to communicate between two computers on the same LAN. I'm rather new to networking, but from what I've read it sounds like I want UDP multicasting so that the two computers can discover each other, after which I can establish a TCP connection for actual data communication. I've found this little example for UDP multicasting which I can follow. However, I'm wondering about the multicast group (HELLO_GROUP in that example, which is 225.0.0.37).
How can I know the group I should use? This program will be running on various networks, so I can't hard code one (as far as I know). Do I get the group from the router, and if so, how do I do that?

You can choose any multicast address (224.0.0.0 to 239.255.255.255) that isn't listed as reserved by IANA.
Its possible (if unlikely) that another program will also be using the same address. You can minimise the chances of this causing any confusion by making the announcement messages your program sends out suitably specific. e.g.
CORNSTALKS-DISCOVERY
HOST: {address:port}
[newline]
This would inform your recipients of the address to use for their TCP connection but should find its first line rejected by any other recipients.

You understood wrong.
What are you talking about is broadcasting. A broadcast UDP datagram is sent to every computer in the subnet. (Technically you send a datagram to the address 255.255.255.255.)
UDP broadcast work inside a specific subnet, but don't cross the subnet boundaties. That is, most of the routers are configured not to route broadcast datagrams (reduce spamming).
OTOH multicast is something completely different. The purpose of multicast is to avoid using TCP (or any other unicast) for data transmission. It's good when you need to send something to many other recipients "at once". Those machine agree preliminary on a specific multicast address (like 225.0.0.37 in your example), and "join" this multicast group. Within a specific subnet everything works pretty similar to broadcast, however in contrast to broadcast the multicast may also cross the subnet boundaries. This is due to the fact that when machines join a multicast group the appropriate routers are notified, and they are capable to route multicast datagrams appropriately.
EDIT:
Conclusion (for clarification).
In order to use a multicast one has to pick a multicast address. This is like choosing a port for the application.
The main purpose of multicast is to deliver content (transmit data) to a number of recipients. It's more efficient than unicast in this case.
A "network discovery" is usually done via broadcast. A multicast can theoretically be used for this as well, but this is like killing a fly with a cannon (because routers should also track the lifetime of the multicast session).

I would suggest you don't use multicast directly.
Rather, use zero-configuration networking. This, in its mDNS/DNS-SD incarnation, is available through Apple's Bonjour library on OS X and Windows, and Avahi on unices (and possibly on OS X and Windows too, not sure).
With DNS-SD, you define a name for your service, then use the library to advertise its availability on a given host, or to browse for hosts where it's available. This is how Macs discover printers, file shares, etc - exactly your use case, i believe. It's a simple but very effective technology. And it's an open standard with a good open source implementation, so it's not some proprietary Apple scarytime.

Related

Send Packets to another subnet/network using Sockets

I am trying to find out whether the machines in a network are running a certain app. More like, I am trying to resolve addresses of nodes in a network.
I built a small code based on ARP, but it works only on a local network(same subnet). What I want to do is resolve addresses out of the subnet i.e. all other nodes.
I read these answers: UDP broadcast packets across subnets
and Broadcast on different subnets
But they all talk about changing router setting or creating a multicast network.
From what I read for multicasting to work, I need to create a multitask network beforehand. Is it really necessary?
And for changing router setting, does it really have to be a "special" router?
This is all for a college assignment and would be demonstrating it probably on an ad-hoc network or something like that.
I am open to ideas to solve the original problem.
PS:
1. I am a beginner in networking so do excuse me for any fault or misinterpretation.
I am using sockets and C(No other option).
Edit 1:
I am well aware ARP is useless outside the subnet. I mentioned it because I used it and it helped explaining the problem.
Edit 2:
The original problem is:
Building a chat application, nothing fancy sending messages from one point to another, without using a central server of any kind. Not even a hybrid network with a central store is allowed.
i.e. if A and B are two clients, A should directly connect to B and vice versa.
I did some research and decided to use P2P architecture. And now I am stuck to how will A discover address of B. If I know the subnet of B, I can brute force and locate B but since I don't have such information what do I do?
ARP is not intended to be routed outside the local network, where in IPv4, the "local network" typically corresponds to a subnet. You should not expect ARP traffic to transit routers from inside to outside or vise versa.
Similarly, UDP broadcasts generally do not propagate outside the local network, and it's a good thing that they don't, for reasons related to both security and traffic volume.
From what I read for multicasting to work, I need to create a multitask network beforehand. Is it really necessary?
Basically, yes. Your routers need to be configured to support multicasting (which may be their default). All participants need to agree on and join the same multicast group. There might not be a need for any new networking hardware, but multicast communication has its own protocols and network requirements; it is not merely a broadcast that can traverse network boundaries.
And for changing router setting, does it really have to be a "special" router?
If you mean changing router settings so that UDP broadcasts are routed between networks, you do indeed need a router that exposes this capability. But I urge you not to do this, as it will let broadcasts from all other sources, for all other reasons transit the router, too. At minimum, this will significantly increase the noisiness of all networks involved, but it could produce bona fide misbehavior of applications and services other than yours.
The Limited Broadcast (255.255.255.255, which is used by ARP requests as the destination address, and ARP only works for IPv4 on the local LAN) cannot cross a router, and a Network Broadcast (last network address, where the host is all ones) by default cannot cross a router (Directed Broadcast) because it is a security risk (see RFC 2644, Changing the Default for Directed Broadcasts in Routers).
Some routers can be configured to forward directed broadcasts, but this can be dangerous.
Multicast is a form of broadcast. Multicast routing is very different than unicast routing, and every router in a path must be configured for multicast routing. Also, hosts must subscribe to a multicast group before they will even listen for packets from a multicast group. Additionally, there are some multicast groups that all hosts listen for, but those are link-local multicasts that cannot be forwarded off the local LAN.
Adding to what other answers have provided:
ARP is not useful for a system in another subnet. Even if you were able to send an ARP request to a system in the other subnet, and receive its response somehow -- providing you with that system's MAC address -- you could not use it to send a packet to that system because Ethernet does not provide a routing mechanism, and so the system will never see any Ethernet packet you address to it.
If you are simply trying to identify which systems within another IP subnet are live, you can probably do this by other means. Take a look at the nmap command, for example. It supports a wide variety of IP communications methods that will be routed to the other subnet and can often detect what machines are present and which services are available on the machines found.
And you can of course duplicate what nmap does yourself. For example, if you want to find out which systems in subnet 192.168.10.0/24 are listening on TCP port 80, one way is to simply attempt to connect to port 80 on each system in that subnet. In general, there are four answers you may receive back:
Connection success (No error: the machine is present and there is a program listening to that port)
Connection refused (errno ECONNREFUSED: the machine is present but there
is no program listening to that port)
No route to host (EHOSTUNREACH: there is no machine answering to
that IP address)
No response (ETIMEDOUT: several reasons why this can happen; for example, the system could have firewall settings causing it to simply ignore the request)
(And there are other less likely possibilities as well.) Using other IP access methods (ICMP/ping, UDP packets) will have a different matrix of possible results.
As others have explained, multicast mechanisms would only be helpful for discovering a set of cooperating machines that are pre-configured to join a multicast group.

understanding link layer multicasting

I am fairly new to network programming especially L2.
I am working on an implementation of LLDP(Link Layer Discovery Protocol) in C. I understand that multicasting over link layer works on directly connected LAN devices. My aim is to have it work across VLAN's (Eg: a device in 10.1.1.0 pool should be able to receive L2 multicast packets sent by a device in 192.168.1.0).
Is there a possible way to achieve this ..or am I missing something vital here?
Wireshark wiki on LLDP says:
LLDP Data Units (LLDPDUs) are sent to the destination MAC address 01:80:c2:00:00:0e. This address is defined as the "LLDP_Multicast" address. This address is defined within a range of addresses reserved by the IEEE for protocols that are to be constrained to an individual LAN. AN LLDPDU will not be forwarded by MAC bridges (e.g. switches) that conform to IEEE Std 802.1D-2004.
so does that mean that a switch or a router just ignores link layer multicast packets coming from another device in another subnet?
does multicast over link layer work only on directly connected devices?
what is the scope of a data link layer multicast address?
From your question, it seems you are mixing L2 and L3 technologies. If you are dealing L2 multicast, IP addresses have no meaning there.
As for the questions:
1) When talking about switches, you have to consider if a switch is 802.1D compliant or not. A dumb switch (a. la Generic $5 from a store next door) will treat your LLDP PDU as a broadcast frame and will distribute it to all other ports except for the one it received it from. This is because MAC address starts with 01 which indicates that the group address bit is set.
A switch which is 802.1D compliant will not forward this frame anywhere. It might process it locally to learn about a device sending it. This will happen if the switch has LLDP protocol support enabled.
A router will act in the same way as a 802.1D compliant switch. It will not forward the LLDP frame and might process it if the LLDP is enabled.
A PC will act the same was as a router.
2) Scope will depend on the endpoints of a link. Any smart device will terminate the journey of the LLDP frame. A dumb switch will treat it as a broadcast frame.
Link-local multicasts will not be propagated off a link. Because of that, the question of ignoring, or not, a link-local multicast from another link will never come up.
You will not be successful in creating an LLDP implementation which originates on one link and is received on a different link. You will need to create a completely different protocol to do what you want, and you will need to change the software on the network devices to recognize this new protocol. This will not be possible with network devices which run proprietary software.

When using PF_PACKET type of socket, what does PACKET_ADD_MEMBERSHIP?

When using a PF_PACKET type of socket with protocol type ETH_P_IP, the man packet documentation talks about a socket option for multicast. The socket option is PACKET_ADD_MEMBERSHIP.
Assuming you use PACKET_ADD_MEMBERSHIP socket option on a PF_PACKET socket correctly, what features and benefits and use cases is this socket option for?
Right now I receive all incoming IP packets so I look at each packet to see if it has the correct IP dst-address and UDP dst-port and I skip over all the other packets. Would using PACKET_ADD_MEMBERSHIP socket option mean I don't need to do my own filter because the kernel or driver would filter for me?
I dug into the linux-kernel source and traced down the code a little bit. I found that the ethernet-mac-address you pass in via setsockopt() is added to a list of ethernet-mac-addresses. And then the list is sent to the network-device hardware to do something... but I can't find any authoritative documentation telling me what happens next.
My educated guess is that the ethernet-mac-address list is used by the hardware to filter at the layer-2 ethernet protocol (i.e. the hardware only accepts packets that have a destination ethernet-address that matches one on the list). If there is some good documentation I would welcome that.
(I'm more familiar with TCP/UDP sockets and so this looks very similar to AF_INET type of socket's IP_ADD_MEMBERSHIP socket option... so I was expecting IGMP reports to be generated which would start multicast traffic from the router... but I found out experimentally that no IGMP reports are generated when you use this socket option.)
Your guess is correct. PACKET_ADD_MEMBERSHIP should add addresses to the NIC's hardware filter. As you've surmised, it's intended to allow you to receive multicasts for a number of different addresses without incurring the load(*) of full promiscuous mode.
(* With modern full duplex ethernet, there's generally not a lot of traffic coming to the NIC that it wouldn't want to receive anyway, unless it's in a virtualized environment.)
Note that there is also a separate PACKET_MR_UNICAST which does not appear in the packet(7) man page but works analogously. I would use the appropriate one (unicast vs multicast) for the type of address you're filtering on, as it's conceivable (though unlikely) that a driver would refuse to put a unicast address into the multicast filtering table.
All that being said, you'll still need to keep your software filtering as backup. There are some older drivers that don't implement MAC filtering at all (particularly for multiple unicast addresses). The core kernel or the driver handles this by simply turning on promiscuous mode if the feature isn't available.
As for the relationship with IP_ADD_MEMBERSHIP, the IP_ADD_MEMBERSHIP code will automatically construct the appropriate multicast MAC address and add it to the interface. See ip_mc_filter_add.

How to bind a Raw Socket to a specific port?

I am currently working on a programming assignment. The assignment is to implement a client,network emulator, and server. The client passes packets to a network emulator, and the network emulator passes to the server. Vice-versa applies as well. The prerequisite for the assignment is that I may only use raw sockets. So I will create my own IP and UDP headers. I have tested my packets with wireshark. They are all correct and in the proper format(it reads them properly).
Another requirement is that the emulator, client and server all have specific ports they must be bound to. Now, I do not understand how to bind a raw socket to a specific port. All my raw sockets receive all traffic on the host address they are bound to. According to man pages, and everywhere else on the internet, including "Unix Network Programming" by Richard Stevens, this is how they are supposed to work. My teacher has not responded to any of my emails and I probably will not be able to ask him until Tuesday.I see two options in front of me. First I can use libpcap to filter from a specific device and then output to my raw socket. I feel this is way out of scope for our assignment though. Or I can filter them after I receive them from the socket. This apparently has a lot of overhead because all the packets are being copied/moved through the kernel. At least, that is my understanding(please feel free to correct me if i'm wrong).
So my question is:
Is their an option or something I can set for this? Where the raw socket will bind to a port? Have I missed something obvious?
Thank you for your time.
--
The man page for raw(7) says:
A raw socket can be bound to a specific local address using the bind(2) call. If it isn't bound all packets with the specified IP protocol are received. In addition a RAW socket can be bound to a specific network device using SO_BINDTODEVICE; see socket(7).
Edit: You cannot bind a raw socket to a specific port because "port" is a concept in TCP and UDP, not IP. Look at the header diagrams for those three protocols and it should become obvious: you are working at a lower level, where the concept of port is not known.
I would think you're expected to filter the packets in your software. It sounds like the exercise is to learn what the different components of the IP stack do by recreating a simplified piece of it in user space. Normally in the kernel, the IP code would process all packets, verify the IP headers, reassemble fragments, and check the protocol field. If the protocol field is 17 (udp), then it passes it to the UDP code (every UDP packet). It's up to the UDP code to then validate the UDP header and determine if any applications are interested in them based on the destination port.
I imagine your project is expected to more or less mimic this process. Obviously none of it will be as efficient as doing it in the kernel, but since the assignment is to write (part of) an IP stack in user-space, I'd guess efficiency isn't the point of the exercise.

How to do IP walk in C

my computer's IP is 192.168.1.101 over eth0.
I want to know what are other active/used IP under 192.168.1.*
I am expecting a list of IP address that is ping-able under 192.168.1.*
How can I do that in C? And preferably in linux platform.
Any C functions available?
There is no built-in function in C that sends ping packet. There is, however, function that just sends packet. There is also a lot of code in the internet that already implements ping.
What you have to do is just take one of them (this for example) and ping in a loop for all addresses in your network.
You should know, however, that ping is not a reliable way of saying which addresses are in use. RFC 792 - Internet Control Message Protocol says:
The Internet Protocol is not designed
to be absolutely reliable. The purpose
of these control messages is to
provide feedback about problems in the
communication environment, not to make
IP reliable. There are still no guarantees that a datagram will be
delivered or a control message will
be returned. Some datagrams may still
be undelivered without any report
of their loss.
which means that any message can be easily lost, with no notification. Furthermore, target does not have to respond.

Resources