Any small program to receive multicast packets on specified UDP port? - multicast

I'd like to debug some multicast issues, and I hope to have some small programs/utilities to display incoming multicast packets.
From the sending machine(A), I use Richard Stevens's sock program(provided with his TCP/IP Illustrated book Vol1) to send multicast packets(source port=dest port=7000), like this:
sock -u -b 7000 224.0.0.7 7000
On the receiving machine(B), I can capture the very sent packet with Wireshark, however, the same sock command running on B does not report receiving anything.
Then, what program should I use on B to see incoming multicast packets, aside from Wireshark which is overkill.
Linux and Windows programs are both welcome.

Here's a python script that will print the incoming data;
# Multicast client
# Adapted from: http://chaos.weblogs.us/archives/164
import socket
ANY = "0.0.0.0"
MCAST_ADDR = "224.0.0.7"
MCAST_PORT = 7000
# Create a UDP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
# Allow multiple sockets to use the same PORT number
sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
# Bind to the port that we know will receive multicast data
sock.bind((ANY,MCAST_PORT))
# Tell the kernel that we want to add ourselves to a multicast group
# The address for the multicast group is the third param
status = sock.setsockopt(socket.IPPROTO_IP,
socket.IP_ADD_MEMBERSHIP,
socket.inet_aton(MCAST_ADDR) + socket.inet_aton(ANY))
# setblocking(0) is equiv to settimeout(0.0) which means we poll the socket.
# But this will raise an error if recv() or send() can't immediately find or send data.
sock.setblocking(0)
while 1:
try:
data, addr = sock.recvfrom(1024)
except socket.error as e:
pass
else:
print "From: ", addr
print "Data: ", data

You can use netcat (nc) to do that:
netcat -vv -l -p 1234 -u
This means netcat is verbosely listening on port 1234 of the localhost in UDP mode.

I've written a multicast testing application back in the day.
You can check it out here: https://github.com/eranbetzalel/SimpleMulticastAnalyzer

This is the first hit when I searched for capturing multicast packets using netcat, and I found out that tcpdump does a job better. Just making a note for any one else hitting this post.
To install:
sudo apt install tcpdump
To run:
tcpdump -c 8 -n -i eth0 portrange 1234-1239
looks like there may be a Windows port too, but I didn't try it: https://www.winpcap.org/windump/

Related

tcpdump does not display packets seen by Wireshark

The host (seen below) receives DNS requests from another host on the same network. It has port UDP/53 closed, still the packets are displayed by Wireshark.
Indeed, the are requests sent to 192.168.16.2 on port UDP/53, so the expression should be right:
tcpdump -v -s0 udp and dst port 53 and dst 192.168.16.2
If I do:
tcpdump -v -s0 udp
the DNS requests aren't displayed either.
Why doesn't tcpdump display the DNS requests, and how can I make it display them?
If your machine has several network interfaces, then you also need to set the interface to listen on using the -i option.
Your expression would then read:
tcpdump -v -s0 -i eth1 udp and dst port 53 and dst 192.168.16.2

Cant receive Hex response from Imatic board

Good day,
This is going to be long. I'm trying to communicate with the "SainSmart iMatic with RJ45" board, which is used together with the "SainSmart 16-Channel 12V Relay Module".
Basically, I'm able to send hex commands to the board, successfully, but can't receive a response from the board when required. What do I mean with this?
I have a laptop with Ubuntu 14.04.4 LTS connected directly to the board via an Ethernet Straight through cable (no longer crossover type needed). I have a configuration for this type of network (only two devices). The IP of the imatic board is fixed, 192.168.1.4 with port 3000. My laptop IP has a fixed IP of 192.168.1.2, with netmask 255.255.255.0, and no gateway.
I'm using netcat (in TCP protocol mode) in my laptop to send commands to the board in this format in terminal :
echo '580112000000016C' | xxd -r -p | nc 192.168.1.4 3000
How do I know it works? Well, basically the relays from a secondary board are turned on successfully ("SainSmart 16-Channel 12V Relay Module").
There's a list of hex commands to turn on and off each relay. In the previous instruction, I'm telling the board to turn on the relay number 1, leaving the other 15 off. The string '580112000000016C' is converted from hex into binary with xxd, and then sent into the netcat. This part works.
The only instruction that doesn't work is this one:
echo '580113000000006C' | xxd -r -p | nc 192.168.1.4 3000
This instruction only asks the board which relays are off an on at the moment, expecting a response in this format:
28 01 00 00 00 XX XX HH (XX XX 16 bit, each bit represents one relay state, "1" indicates on, "0" indicates OFF; HH is the sum of all previous data together, meaning it works as a checksum)
I've already tested and proved that, this is NOT an issue from the board. I wrote a code in visual basic, and windows was able to receive the response from the board, but something has to be wrong in my ubuntu configuration.
I've already disabled my firewall, ufw.
This is NOT a problem with the Ethernet cable.
I've already tried other command representations such as:
echo -n '5801100000000069' | xxd -r -p | nc -v -n -w3 192.168.1.4 3000 | xxd
I've already used netcat to scan all available ports in the board, and only the 3000 port is shown as available, as stated from the manufacturer.
This seems to be a network configuration problem though, but in windows, I specified the same IP, and netmask as in ubuntu.
What am I mising here?
Netcat is waiting for an EOF character, which is never sent by the iMatic board. That explains why netcat can't receive the response ever.
On the other hand, I wrote a python script (Python 2.7.6) which successfully receives the data from the iMatic board, after sending to it a certain instruction. Here it is:
import socket
import binascii
IPADDR = '192.168.1.4'
PORTNUM = 3000
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((IPADDR, PORTNUM))
data = '5801100000000069'.decode('hex')
s.send(data)
response= s.recv(8) #Buffer needs to be 8 for the fastest response without losing information
print binascii.hexlify(response)
s.close()
You can use this board now without a router, and directly connected to any computer through an Ethernet cable.
Regards,
Bernext.

Linux WiFI AP : refresh `iw dev wlan0 station dump` output (inactive time)

I have a Linux (3.14.36) embedded board acting as a WiFi AP.
The WiFi chipset doesn't support monitoring mode.
My laptop(the client) is connected to this board by WiFi
The WiFi AP is acting as a network bridge to another computer, and doesn't provide an IP adress to the client (the WiFi AP only has the MAC address of the client)
I want to monitor the signal strengh of the connection WiFi AP <-> Client and be able to trigger a "refresh" of the signal strengh value.
Doing : iw dev wlan0 station dump gives me :
Station xx:xx:xx:xx:xx:xx (on wlan0)
inactive time: 123820 ms // <-- The problem
rx bytes: 10291
rx packets: 60
...
signal: -65 dBm // What I want to refresh
...
I understood that the signal strengh is updated every time there is a network activity. (So, in the example above, it has been refreshed 123s ago).
How can I force a refresh of this value ? (By forcing the AP to send "something" to the client for example) Knowing that the board/WiFi driver/WiFi device doesn't support tools such as iwconfig
For anyone finding this thread now:
I had this issue and my solution was to ping the device before doing the iw dump, e.g.
Get the list of of connected MAC addresses:
iw dev wlan0 station dump | grep 'signal' | awk '{print $2}'
Then get the IP address from these MAC addresses (alternatively you could use arp):
ip neigh | grep 'ma:ca:dd:re:ss:ss' | awk '{print $1}'
Then ping each of those:
ping -c 1 'IP.address'
Then get the refreshed signal for that MAC address
iw dev wlan0 station get 'ma:ca:dd:re:ss:ss' | grep 'signal' | awk '{print $2}'
I wrapped all this up in a Python script and it seemed to give reliable data.
I'll give it a try:
You're embedded so I guess you have busybox. You have no IP but you may then use arping (if this applet is not configured in your busybox build, change the config) to send something small and useless that may wake up the thing. What IP to use for your ARP requests? Well it seems you can use a "dummy" IP.
I'm running this on a PC but I do have busybox with its arping, and I use a wired interface, but here is the concept:
jbm#sumo:~/sandbox/iw$ sudo busybox arping -w 1 -U -I eth0 0.0.0.0
ARPING to 0.0.0.0 from 192.168.1.66 via eth0
Sent 2 probe(s) (2 broadcast(s))
Received 0 reply (0 request(s), 0 broadcast(s))
The useful thing is that though the "dummy" IP, I can check with tcpdump that the arp requests do actually go on the wire (or in the air in your case):
jbm#sumo:~$ sudo tcpdump -i eth0 -v arp
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
10:42:20.111100 ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 0.0.0.0 (Broadcast) tell sumo, length 28
10:42:21.111206 ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 0.0.0.0 (Broadcast) tell sumo, length 28
^C
2 packets captured
2 packets received by filter
0 packets dropped by kernel
So sending ARP request on your wireless interface may be enough to "wake up" your connection and refresh your RSSI.
EDIT:
See the interesting uses and properties of IP 0.0.0.0 here:
https://en.wikipedia.org/wiki/0.0.0.0
EDIT 2:
Re-thinking about it, I realized there will be a problem if your wireless interface does not have an IP itself. Which, if I'm not mistaking, may not necessarily be case in your bridging configuration. In such case, arping will not have a source address to build its request packets (nor will know how to listen for responses), and will fail.
But you can create your own "mini-unidirectional arping", using an AF_PACKET socket and build your own ARP request packet with a dummy/random source IP address. It will be unidirectional because the response to your forged ARP request, if any, would go to to the random source IP which may and preferably should not exist. But it the principle of just awaking your wireless connection by sending "something", that may do the trick.
For inspiration on how to code this "mini-unidirectional arping", have a look at busybox implementation from its udhcpc/udhcpd (it's simpler than the full-blown arping busybox applet):
https://git.busybox.net/busybox/tree/networking/udhcp/arpping.c#n38
The from_ip parameter is what you want to forge. You can use your actual MAC as from_mac, just for the sake of dignity :-) You don't even have to wait for a response (starting line 89), so that would be something like 50 lines of C code + a little main if you want to add a few options to it.

Traffic forwarding

I have an application that sends HTTP GET requests and receives answers from some web server.
Is it possible to accomplish following: read the incoming data on on wire on port 80 using Linux commands (no code) and forward it to multicast group or just any upd port. Tried to do it with nc, no success.
I am aware it can be easily done on application level, I am trying to avoid unnecessary latency on bringing the data up to application level and then putting it down to wire. Time is very crucial here.
Thanks all.
You can use tcpflow to capture the actual data in a TCP stream. For example I can start:
sudo tcpflow -C -v -i eth0 "tcp src port 80"
Then for example if I run curl google.com in another window, then tcpflow dumps the TCP stream.
You can then pipe this output to socat to send it to a UDP socket.
UDP listener:
socat -u UDP-RECV:5555 STDOUT
Pipe the tcpflow output to this UPD listener:
sudo tcpflow -C -v -i eth0 "tcp src port 80" | socat STDIN UDP-SENDTO:localhost:5555
Bear in mind that TCP and UDP are quite different protocols, and thus have quite different use-cases. TCP is stream-oriented, whereas UDP is datagram-oriented. Trying to stuff a stream over a datagram-oriented socket will at best be unreliable.
Also while you may be able to get the above to work, I'm not sure how much performance gain you'll actually see. No matter what happens, TCP stream reassembly must happen and the kernel will generally do this very efficiently. Unlikely that tcpflow will do this any better than the kernel.

How to retrieve ports in use in the system?

In a Linux specific way, how can I get the list of all open UDP ports and all TCP ports currently accepting connections in some interface?
The most common way is to use netstat console utility with the following flags:
netstat -plan
where:
-p : Show the PID and name of the program to which each socket belongs;
-l : Show only listening sockets;
-a : Show both listening and non-listening sockets;
-n : Show numerical addresses instead of trying to determine symbolic host, port or user names.
For additional output options and flags please check man pages man netstat. Based on your particular needs, only TCP or UDP (for example) protocol connections can be examined:
netstat -4 --tcp --udp --all
Alternatively, lsof -i might be helpful.
Most likely you are interested in the following information (special /proc filesystem):
/proc - Mount point for the proc filesystem, which gives access to kernel status information via the following files:
/proc/net/dev - device information
/proc/net/raw - raw socket information
/proc/net/tcp - TCP socket information
/proc/net/udp - UDP socket information
/proc/net/igmp - IGMP multicast information
/proc/net/unix - Unix domain socket information
/proc/net/ipx - IPX socket information
/proc/net/ax25 - AX25 socket information
/proc/net/appletalk - DDP (appletalk) socket information
/proc/net/nr - NET/ROM socket information
/proc/net/route - IP routing information
/proc/net/ax25_route - AX25 routing information
/proc/net/ipx_route - IPX routing information
/proc/net/nr_nodes - NET/ROM nodelist
/proc/net/nr_neigh - NET/ROM neighbours
/proc/net/ip_masquerade - masqueraded connections
/proc/net/snmp - statistics
List all listening processes and what port they are listening too. Running without sudo will list only user processes.
sudo ss -tlpn
explanation:
-t tcp
-l listening
-p show process
-n numeric, don't replace port numbers with their "popular" name.

Resources