Erlang: receive multiple multicast streams on the same port - sockets

I have a multicast-based IPTV in my network.
All channels have muticast addresses like 239.0.1.*.
Streamer device sends UDP data to target port 1234.
So to receive a tv stream I do usual stuff like:
{ok, S} = gen_udp:open(1234, ....
inet:setopts(S, [{add_membership, {{239,0,1,2}, {0,0,0,0}}}]),
It works.
Now I want to subscribe to multiple channels to receive several streams simultaneously.
So I do another call:
inet:setopts(S, [{add_membership, {{239,0,1,3}, {0,0,0,0}}}]),
It works too. I see both streams in Wireshark. I can distinguish them by destination IP addresses - 239.0.1.2 and 239.0.1.3.
BUT.
In Erlang I cant figure out a channel to which incoming packet belongs, cause UDP data arrives as messages:
{udp, Socket, IP, PortNo, Packet},
where IP and PortNo is the source address (10.33.33.32 in my case) and port (49152).
So the question is - how to determine destination IP address of incoming multicast UPD packet.
Windows 7, Erlang 5.9/OTP R15B.
Thanks!

This should retrieve the destination IP from received UDP data:
{udp, Socket, IP, PortNo, Packet},
{ok, {Address, Port}} = inet:sockname(Socket),
Address will contain tuple like {239,0,1,3}.

Related

Monitoring UDP data on wireshark shows ARP packet

I am trying to send UDP packet to my server 10.20.1.2 with port number 20000. I have implemented UDP client on PC and when i send data using sendto API , at the same time i monitor data on wireshark wireshark shows it as an ARP packet.
18967 5440.858646 PcsCompu_ef:b4:89 Broadcast ARP 42 Who has 10.20.1.2? Tell 192.168.1.70
192.168.1.70 is my machine ip where UDP client is running.
I am not sure how UDP packet is getting converted into ARP packet ?
I understand ARP is for finding MAC address of target node but here i already know MAC address of target device , How can i add it in my udp client so it directly starts UDP communication . My target device is one embedded camera , i am not expecting it to reply on ARP request so i want to prevent sending ARP request.
Below is my UDP client code :
Any inputs are highly appreciated. Thanks in advance.
/*
Simple udp client
*/
#include<stdio.h> //printf
#include<string.h> //memset
#include<stdlib.h> //exit(0);
#include<arpa/inet.h>
#include<sys/socket.h>
#define SERVER "10.20.1.2"
#define PORT 20000 //The port on which to send data
char message[3]={0x00, 0x00 , 0x24};
int main(void)
{
struct sockaddr_in si_other;
int s, i, slen=sizeof(si_other);
int ret;
if ( (s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
{
printf("socket failed");
}
memset((char *) &si_other, 0, sizeof(si_other));
si_other.sin_family = AF_INET;
si_other.sin_port = htons(PORT);
if (inet_aton(SERVER , &si_other.sin_addr) == 0)
{
fprintf(stderr, "inet_aton() failed\n");
exit(1);
}
ret = sendto(s, message, sizeof(message) , 0 , (struct sockaddr *) &si_other, slen);
close(s);
return 0;
}
Some clarifications regarding networking.
1. ARP must be sent and replied
Your camera has IP interface, which means it must handle ARP requests fine without any doubts. ARP is essential part of communicating via IP, camera without ARP support makes no sense. And ARP isn't a result of converting UDP, it's a preliminary step before sending actual UDP datagram. Once ARP reply is discovered with destination MAC-address, UDP packet is sent to that destination. The issue you see isn't about hardcoding MAC to avoid ARP.
2. Your code looks fine
Compiled it locally with minor corrections (missing #include <unistd.h> header with close() declaration), tested on several targets, client works as expected.
3. Something is wrong with your network topology
You are sending message from 192.168.1.70 to 10.20.1.2, which is weird. 192.168.0.0/24 and 10.0.0.0/8 are private IP addresses from different ranges, so they normally can't reach each other without black magic (like NAT traversal). And, what is much weirder, during your attempt ARP request is sent to strange destination. Let me illustrate different cases:
if both devices are in same subnet (e.g. 192.168.1.70 sends to 192.168.1.71), then message is sent directly, so client asks "who has 192.168.1.71" in ARP request.
if devices are in different subnets (e.g. 192.168.1.70 sends to 8.8.8.8), then message is sent through gateway, thus ARP request reads "who has 192.168.1.1" or whatever your gateway address is. Gateway MAC may be already in cache, in which case ARP isn't sent at all.
in your case subnets are obviously different, but ARP is asking about direct destination address rather than gateway MAC address.
It's a shot in the dark, but probably you have two network interfaces on your PC, one connected to 192.168.0.0 subnet, the other to 10.0.0.0 and ARP request is sent from both. If you sniff the wrong interface, you see weird ARP request and don't see UDP, which is actually sent after it. By the way, seeing single arp request is also confusing, because it should be repeated several times if noone answers.
Anyway, you need to check network topology and/or simplify it. Remove unnecessary network interfaces, configure PC and camera to be on the same subnet connected to the same switch/router and investigate further.

the port_no in struct vport of openvswitch is different from the port number?

I modified the ovs2.6.0 and want to handle some packets.
I printk the prev_port(prev_port = nla_get_u32(a)) in do_execute_actions function. However, the prev_port sometimes is not the correct port number which the packet is forwarded to. But the TCP transmission is normal. I guess that the port number in ovs is numbered in a random way?

Implementing three-way handshake

I wanted to implement the three-way handshake using python.And here is what I did:
1-I created syn packet .
2-I send the packet to the destination .
3-I created a function that will listen to all the traffic that pass through my NIC .it's kinda like sniffer.If this function were to find a packet that is destined to my IP address and the same port that I send the syn packet through, it will parse it .
4-If the flags in the captured packet are set to syn+ack,the function will generate a TCP packet with the ack flag set.
The problem is, before I send the ack packet the system send RST packet .
So , what is the meaning of the behaviour?? Is there anyway to stop it??
Note:
I am not implementing the three-way handshake for production purposes.I just want to understand how the protocol TCP work.
Disable the system's TCP/IP stack so that you have complete control over what it sends over the network. Usually the easiest way to do this is simply not to configure IP on the interface you are using. Note that you will need to handle ARP requests.

Is raw socket datagram socket or not?

For a non-blocking datagram socket, like UDP, when I call write()/send() on the socket, each call of write()/send() or read()/recv() deals with exactly 1 packet.
I'm wondering if a raw socket, like the below, is a datagram socket or not?
int on = 1;
rawfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
setsockopt(IPPROTO_IP, IP_HDRINCL, &on, sizeof(on));
That depends on the kind of IP header you will include in your packets (TCP or UDP). Actually it's more easier to include the UDP header since the kernel will manage some TCP mechanism.
So you have to add the UDP header in your packets, then it will be a datagram socket.
When you send data out, TCP/IP stack will add TCP/UDP header, IP header and then Ethernet header, and network work card transmit the whole packet out. For raw socket, you prepare all the headers(TCP/UDP, IP and MAC), and network work card transmit the whole packet out. So whether it is datagram depends on the header you add is TCP or UDP.

BroadCasting

Ok in order to broadcast, I have created a socket:
notifySock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
And to send the hostname of my computer to all other computers connected to the same lan, I am using the send(Byte[] buffer) method:
notifySock.Send(hostBuffer);
hostBuffer contains the hostname of my computer.
However because I am using a 'datagram' socket-type do I need to format the data I need to send.
If possible please provide the code that I must put in between the two lines of code I have entered to create a socket and send the data.
For broadcast from a user application, UDP is typically used. You need to design a suitable protocol, i.e. a way to format the information you want to send into the UDP packet.
In your example you haven't specified who you are sending to. You need something like:
UdpClient notifySock = new UdpClient(endPoint);
notifySock.Send(buffer, buffer.Length, new IPEndPoint(IPAddress.Broadcast, 1234));
For the other hosts on your LAN to receive that they have to be listening on UDP port 1234.