I have an ambiguous issue, I have a multicast group between two users one of them is a sender and another is receiver I did these scenarios in each side:
Receiver:
create a udp socket.
bind to a multicast group address
connect to the sender side ( connect(sender ip))
join the multicast group
recv from the multicast group.
Sender:
create a udp socket.
send to the multicast group.
In this scenario above when sender sent data receiver couldn't receive but if we checked the receiver side by tcpdump there is data was received from multicast group.
but if there is no connect to sender side in receiver, data will be received.
BUT Actually, If we let the sender bind to the multicast address before send to the multicast group and also receiver connect to the sender side as scenario above data will be received successfully!!!!
Any explanation when we added the bind in the sender side ???
You might want to connect(2) the sender's socket to the multicast group to speed up sending, but don't connect(2) the receiver since it restricts it to unicast (yes, it's a bit confusing, but that's how it works). Just bind(2) the receiver to the group/port, and do the setsockopt(2) with IP_ADD_MEMBERSHIP to join the group.
There is no such thing as 'connected UDP multicast'. It is is connected or it is multicast. Remove the connect() steps completely.
On the receiver side, both the bind() and connect() calls do the same thing: they associate a given Internet socket address with a given connectionless socket. For the bind() call -- in which the Internet socket address is the address of the multicast group -- this means that the socket will only receive UDP packets whose destination address is that of the multicast group. For the connect() call -- in which the Internet socket address is that of the sender -- this means that the socket will only receive UDP packets whose destination address is that of the sender, which isn't what you want.
The connect() call is overriding the bind() call, resulting in no packets being received.
Replace the bind() call with a connect() call to the multicast group and you should still receive the UDP packets -- or keep only the bind() call. It's your call.
Related
I am using libpcap to capture packet with the following filter:
"tcp[tcpflags] & (tcp-syn) != 0 and not net 127.0.0.1"
But I actually want to get the packet only if the sender is the client (SYN-SENT).
Basically what I am trying to do is to get inform only for new connection and not multiple time for every connection.
Is there a way to do that?
If you only want the SYN from the client but not the SYN+ACK from the server use:
tcp[tcpflags] & (tcp-syn|tcp-ack) == tcp-syn
On a system with several network interfaces, I can have the same multicast address and port combination used on different networks, with different data on them. I want to be able to connect to them with several network cards and receive different data on each interface.
To do so, I bind to the interface I want to receive on using the IP_MULTICAST_IF option:
ip_mreqn mreqn;
memset(&mreqn, 0, sizeof (ip_mreqn));
mreqn.imr_multiaddr.s_addr = inet_addr(mc);
mreqn.imr_address.s_addr = INADDR_ANY;
mreqn.imr_ifindex = if_nametoindex(device);
if (setsockopt(mct->fd, IPPROTO_IP, IP_MULTICAST_IF, &mreqn, sizeof(mreqn)) < 0) {
perror("setsockopt multicast if");
return 1;
}
and make sure the join request is only sent on that interface by setting IP_ADD_MEMBERSHIP with the same structure:
if (setsockopt(mct->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreqn, sizeof(mreqn)) < 0) {
perror("setsockopt add membership");
return 1;
}
While the IP_ADD_MEMBERSHIP code works (the join request is only sent on the interface specified), the IP_MULTICAST_IF does not. Instead once it is able to join the multicast on any of the interfaces, I receive the same data through all sockets, even if they have different imr_ifindex set.
The IP_MULTICAST_IF ioctl does not control incoming selection, it is setting the socket's default interface for its outgoing multicast packets.
IP_ADD_MEMBERSHIP is the only mechanism for configuring incoming multicast and the memberships it creates are for the entire host, the host does not tailor delivery to individual sockets based on their requested memberships. (You can observe the hosts memberships with netstat -gn and the reference count is being used to determine when the host can stop observing, but not which sockets are receiving fan-out. If you have a matching membership from any socket, all sockets that made an applicable bind(2) will start receiving that multicast, even if they have never used IP_ADD_MEMBERSHIP.)
The usual method to differentiate these packets with out changing the system setup, is to receive them all on a socket using ancillary data to identify their interface. On Linux, this ancillary data setup is done with IP_PKTINFO as described in ip(7).
I need to implement the following scheme (in C, however the language is not the case here):
client(192.168.1.2) <-> proxy(addr4: 192.168.1.1:1000, addr6: FE80:0000:0000:0000:0202:B3FF:FE1E:8329) <-> some_remote_host(remote_addr6)
The thing is addr6 on proxy side must be dynamically changed according to incoming ipv4 port. For example:
client connects to 192.168.1.1:1000, outgoing connection is made via addr6_0
client connects to 192.168.1.1:1001, outgoing connection is made via addr6_1
etc ...
The most straight-forward implementation would be: assign multiple static ipv6 addrs to ethernet interface and use bind() on socket before outgoing connection. The problem is that the number of incoming ports/outgoing addrs can be ~10000 (and as far as I understood recommended value for net.ipv6.conf.all.max_addresses is 32 or 64, default is 16).
The questions are:
What possible problems can I expect if I assign 10000 ipv6 addrs to one interface, I assume performance issues?
Is there a better way to achieve the goal?
Is it possible to receive data from more than one multicast group on a single socket?
For example:
void AddGroup(int sock,
const char* mc_addr_str,
int mc_port,
const char* interface) {
struct sockaddr_in mc_addr;
memset(&mc_addr, 0, sizeof(mc_addr));
mc_addr.sin_family = AF_INET;
mc_addr.sin_addr.s_addr = inet_addr(mc_addr_str);
mc_addr.sin_port = htons(mc_port);
if ((bind(sock, (struct sockaddr *) &mc_addr,
sizeof(mc_addr))) < 0) {
perror("bind() failed");
exit(1);
}
// construct an IGMP join request structure
struct ip_mreq mc_req;
mc_req.imr_multiaddr.s_addr = inet_addr(mc_addr_str);
mc_req.imr_interface.s_addr = inet_addr(interface);
if ((setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
(void*) &mc_req, sizeof(mc_req))) < 0) {
perror("setsockopt() failed");
exit(1);
}
}
This code works when I add one multicast group. But when I try to add another, the "bind" fails. I don't quite understand why the bind needs to be there in the first place? (but the code doesn't work without it).
Ideally I would like to call AddGroup multiple times on the same socket. Is this possible? Or do I need one socket per group and then just use polling?
You can join as many multicast groups as you like, using the appropriate setsockopt() call with the IP_ADD_MEMBERSHIP option, rather than bind().
You only bind a socket once. Skip the bind the second time and see what happens.
You can join as many multicast groups you want to on a single socket. See setsockopt(), IP_PKTINFO for a way to recognize which multicast group you are reading data from.
bind to the passive address, i.e. 0.0.0.0 for IPv4 and use ASM or SSM to pull in additional groups, e.g. IP_ADD_MEMBERSHIP as listed.
You can only bind once.
Yes, it's possible: look on the example in the link (http://www.tenouk.com/Module41c.html)
To shorten this up in a few steps:
You setsockopt with SO_REUSEADDR
You bind on INADDR_ANY
You setsockopt with IP_ADD_MEMBERSHIP on every group you want to receive datagram from.
It seems to me that using IP_PKTINFO gives an option to distinguish received packets, but sender must take care about preparing them(Setting the source IP for a UDP socket)
In unix based OSes:
If you need to bind to multicast address, you cannot call bind() more than once. And you will need to bind to multicast address when you expect more than one multicast streams using same destination port and multiple processes running in same device receiving those multicasts.
For example, when you have multicast streams: 239.0.0.1:1234, 239.0.0.2:1234, 239.0.0.3:1234 and 239.0.0.4:1234, and you want to receive 239.0.0.1, 239.0.0.2 in process-A and want to receive 239.0.0.3, 239.0.0.4 in process-B, you cannot accomplish this when both processes A and B running in same device.
I have my multicast (udp) sender/receiver program up and running. If I use setsockopt to enable loopback with the sender like so:
if(setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop)) < 0)
error("loopback failed.");
and later on I send out the message to every subscriber, how does my sender get the message that's sent out? The sender doesn't store its own IP address and Port number and sent itself a message (basically subscribing to itself) does it?
So it should be something like:
receiver1 (subscription) -> sender
receiver2 (subscription) -> sender
when it's time to send:
sender (info) -> receiver1
sender (info) -> receiver2
sender (info) -> sender? //how does this step work?
Thanks for the help :)
In your code, loop must be of type u_char, not int. Of course, this will also change the final setsockopt() parameter to have the value 1. I have no personal experience of this, but W. Richard Stevens says so in UNIX Network Programming (3rd edition), Vol. 1, Section 21.6, so it must be so.
He also says that using type int here is a common programming error.
In addition to enabling loopback (which actually may be enabled by default, according to http://tldp.org/HOWTO/Multicast-HOWTO-6.html#ss6.1), you also need to subscribe to the multicast group.
It isn't necessary to send a separate copy of the packet to each receiver. If the multicast subscriptions are correct and you're on a network that supports multicast, then a single transmission is sufficient.