Using socat to relay one TTY stream to multiple TCP/IP destinations, plus to one 'sniffer' program - tcp

Using an embedded Linux development board, I need to put together a widget that does the following:
Reads packets in via physical serial port, and relays those packets to a number of IP addresses (up to 20 of them; with IP destinations read from a configuration file).
Also 'sniff' those serial packets using a custom program, perhaps written in c.
As someone with a programming background, the most obvious solution (to me) would be to create a c program from scratch to achieve the above. However, as this is something I need to throw together quickly, and because I need an excuse to learn more about existing Linux command-line programs and script writing (which I'm not so good at), I'm wondering if much of this could be achieved with existing command-line programs and a shell script. Then, the only part I write from scratch is my packet sniffer (call it sniffer.c).
I understand that netcat and socat can be used for relaying between devices and addresses, and I have started experimenting with both. The thought occurs to me that I could avoid having to develop and test TCP/IP software by running multiple instances of socat to relay serial data from the TTY port to remote IP addresses. Each instance of socat could handle a particular remote IP address.
Does this sound feasible, and if so, how could I effectively 'multiplex' a stream from /dev/ttyS0 (say) as the source for multiple instances of socat plus one instance of sniffer.c? Could one way be to relay data read from /dev/ttyS0 to a cache file, and then have my socat instances and sniffer.c all have a read-only access to that file?

Related

Programming Arduino's from a centralized location

I have 16 Arduinos that are in very tight spaces and hard to get to when I need to reprogram them with my FTDI cable. I would like to have or create some sort of centralized place where I can connect my FTDI cable, make some sort of selection (switch of some sort), which will then connect the pins my cable is on to the selected arduino.
Does anyone have any thoughts on how this can be accomplished? I've toyed with transistors, but that takes a lot of them and didn't quite work.
Are there any premade solutions that are out there that I have yet to find?
Thanks very much!
Here is a thought! TCP to Serial.
Sound complicated.
Not really.
Note from AVRDUDE's manual the following
For programmers that attach to a serial port using some kind of higher
level protocol (as opposed to bit-bang style programmers), port can be
specified as net:host:port. In this case, instead of trying to open a
local device, a TCP network connection to (TCP) port on host is
established. The remote endpoint is assumed to be a terminal or
console server that connects the network stream to a local serial port
where the actual programmer has been attached to. The port is assumed
to be properly configured, for example using a transparent 8-bit data
connection without parity at 115200 Baud for a STK500.
With this, One could place your Arduino's behind your choice of TCP to Serial Server. Which is available in several forms. Cisco has a gang TS (but that is expensive, unless used). lantronix (and others have single end point devices. But then for Linux, there is "Net2Ser" which can serve up all your ttyS (aka Serial/COM ports).
With the later you could use a raspberry or TP-Link TL-WR703N (
In the latest IDE 1.5.6r2 add one entry for each TCP-to-Serial Port to ./Arduino/hardware/arduino/avr/programmers.txt file. While replacing the IP and Port with corresponding values.
TCP2001.name=TCP 2001
TCP2001.communication=serial
TCP2001.protocol=stk500v1
TCP2001.program.protocol=stk500v1
TCP2001.program.tool=avrdude
TCP2001.program.extra_params=-Pnet:192.168.1.100:2001
TCP2002.name=TCP 2002
TCP2002.communication=serial
TCP2002.protocol=stk500v1
TCP2002.program.protocol=stk500v1
TCP2002.program.tool=avrdude
TCP2002.program.extra_params=-Pnet:192.168.1.100:2002
...
Additionally change "protocol" to "upload.protocol" the following line in ./Arduino/hardware/arduino/avr/platform.txt
tools.avrdude.program.pattern="{cmd.path}" "-C{config.path}" {program.verbose} -p{build.mcu} -c{protocol} {program.extra_params} "-Uflash:w:{build.path}/{build.project_name}.hex:i"
to
tools.avrdude.program.pattern="{cmd.path}" "-C{config.path}" {program.verbose} -p{build.mcu} -c{upload.protocol} {program.extra_params} "-Uflash:w:{build.path}/{build.project_name}.hex:i"
With this you can use "Upload Using Programmer" with the selected programmer to send over TCP, rather then use the Upload.
That all said, it will only work on Linux.
avrdude: ser_open(): network connects are currently notimplemented for Win32 environments

Multiple programs on a machine should receive the network traffic arriving on one port

I have UDP network traffic arriving on my machine (OSC traffic from an iPad, to be exact) and I want two programs to be able to receive that traffic. The problem is that I can't bind to the same network port with two programs at once and I can't send to multiple ports with the iOS app I'm using. How can I solve this problem?
You can use the power of the command line for this. The following snippet uses socat (probably needs to be installed beforehand) and tee (should be preinstalled on any OS X or Linux).
socat -u UDP4-RECVFROM:8123,fork - | tee >(socat -u - UDP4-SENDTO:localhost:8223) | socat -u - UDP4-SENDTO:localhost:8323
Explanation: socat listens for traffic on UDP port 8123, pipes it to tee, which pipes it to two other instances of socat forwarding it to ports 8223 and 8323 on localhost respectively. With your two programs you need to listen to those ports on localhost.
While the answer with using socat is elegant it is not clear for me, what you are trying to do:
both programs should receive all parts of the traffic and they will only receive and not reply. This can be done with the proposed socat way
both program should receive all parts of the traffic and there reply will be mixed together (how?)
each of the programs should only receive parts of the traffic, e.g. the one which the other did not get. This should be possible if both of your programs use SO_REUSEADDR, SO_REUSEPORT. Replies will then be mixed together.
or do you actually want to communicate with each of the programs seperatly - then you would have to use either multiple sockets in the iOS app (which you don't want to do) or built your own protocol which does multiplexing, e.g. each message is prefixed with there target app and on the target machine a demultiplexer application will receive all packets and forward them to the appropriate application and wrap the replies back in the multiplexing protocol.
In summary: please describe the problem your are trying to solve, not only one small technical detail of it.
The problem is that I can't bind to the same network port with two programs at once
Yes you can. Just set SO_REUSEADDR and maybe SO_REUSEPORT on both of them before you bind.

Send files from Qt application on ethernet

I want to send files from Qt Application using Ethernet.As I click push Button the files must be transfered.
so my Question is:
Q: what are the configuration required because IP ,Net Mask is fixed in my device I am using :AM335x
:Linux OS
:Qt application
I am new to TCP/IP tell me how to proceed;
from Ethernet I am able to download Qt application executable file from PC to my device(AM335x) and it is running well .
But I want to send files from Am335x device to other device or PC.
Regards
Praveen
Basically what you want to be using is the Qt Network module. You can read about that here:
http://qt-project.org/doc/qt-5.0/qtnetwork/qtnetwork-programming.html
And find a class list here:
http://qt-project.org/doc/qt-5.0/qtnetwork/qtnetwork-module.html
Very briefly the two main classes you can use for TCP communication are QTcpServer and QTcpSocket. You can set up the server to listen for connections and it will return a QTcpSocket to do the actual communication. You can use the QTcpSocket for any outgoing communication.
If you don't want to use TCP, you can use datagrams (simpler, but ultimately less reliable). Here QUdpSocket is the main class to use, both for sending and receiving (you need to bind the socket to a port on your machine to receive).
It would be fairly easy to write a custom program to do simple file transfer based on these classes, however you can also look at higher level protocols designed to deal specifically with files.
For simple interaction with an FTP server at the other end of the connection you can use the QFtp class. An example of an FTP client application is here. Writing an FTP server in Qt would be rather more complicated, however you can look here: https://code.google.com/p/qt-ftp-server/.
All of this of this of course assumes that the Ethernet connection has been set up properly and that your computer has a valid IP address. Bear in mind that Ethernet is a link layer protocol and forms the raw basis for the higher level IP and TCP protocols. The idea of the higher level protocols is that they can used over a variety of link layers throughout the internet. It would be very unusual to write a program that interacts directly with a link layer protocol (unless of course you are writing a network stack for an OS).
On most networks configuration of IP addresses/netmasks etc is handled by a DHCP server running on one of the devices, most commonly on the router connecting everthing (if you have DHCP already running, then you probably don't have to worry). Without DHCP you can usually configure a static address and netmask on most devices. Choosing them is a fairly simple procedure. This page has a fairly good introduction to the concepts.
At first, you must be sure, that the target you want to send file to, is reachable. Use ping. If ping call is successful, then you can go further. Otherwise you should check your network settings to comply with your LAN.
You have then various ways to send files: FTP, HTTP, via netcat, using CIFS etc.

XBee Send To All

I have a simple xbee network operating where there are a bunch of slaves operating remotely and all talking to one master, who is connected to the server computer. That works no problem.
The slaves all send their ID as part of the packet and I'd like to have the master deliberately send an Ack after a delay. I'm trying to figure out how to do this efficiently and it seems that the only plausible way that doesn't involve reprogramming the master before each Ack is to send the Ack to all slaves and have them ignore the packet if it's not meant for them.
That solution is ok - I just can't figure out the command to use to do this. Is there some sort of Serial sendAll command? All of the devices are on the same ATID.
Typically in this situation, you would configure the master in API mode so you would get "Receive Explicit" frames with source addressing information, and could send with the "Transmit Explicit" frame type, and include addressing information in your frames.
If you use AT mode (transparent serial mode), then you're stuck having to change the DH and DL parameters on your coordinator every time you want to change who you send to. You should avoid using broadcast packets, since each one results in lots of network traffic (IIRC, each router will send the broadcast packet three times).
I do not know of a good XBee library on the Arduino, but it might be possible to port Digi's Open Source ANSI C XBee Host Library to that platform.

Hyper-V: Connecting VMs through named pipe loses data

We are trying to connect two Hyper-V VMs through a serial port. Hyper-V exposes the serial port as a named pipe to the host system, and implements the server end of the named pipe. Consequentially, to connect them, we need to write a named-pipe client which connects to both VMs, and copies the data back and forth.
We have written such an application. Unfortunately, this application loses data.
If we connect two hyperterms, and have them exchange data, the transmission sometimes succeeds, but in many cases, the receiving end reports errors, or the transmission just deadlocks. Likewise, if we use the link to run a kernel debugger, it also seems to hang often.
What could be the cause of the data loss? What precautions must be taken when connecting named pipes in such a manner?
Edit: We have worked around the problem, using kdsrv.exe. The COM port of the debuggee continues to be exposed through a named pipe, however, the debugger end talks to kdserv via TCP.
The data loss is not due to the named pipes. It is infact the COM ports (emulated and physical) that may lose data since they operate with a small buffer in the UART.
The named pipe receives all the data that is written to the COM port. Your program reads data from the named pipe and writes it to another named pipe. This is where data loss can originate if you write too fast the receiveing COM port's UART can overflow leading to data loss.
You may need to add some delay to avoid exceeding the baud rate expected by the receiving side.
In addition, you are missing ResetEvent() calls in your program.
For your KD issues, you may need to add resets=0 to the connection string.
I did not try to connect VM via Serial but I connected VM and Host via usb (through network)
and it works.
If it is required for your software to establish serial connection try to test via serial emulators with work through tcp\ip.
I think John's suggestion is correct - if u are using a slow CPU to emulate TWO VM, then the guest OS's drivers for serial port is highly drifted away from the high speed version. So John's suggestion is to set the input/output side of the serial link to the slowest possible speed. Ie, you cannot use high baud rate for the inter-VM serial communication. Instead u have to use the slowest possible speed, and so that the VM guest driver will take that cue and use the slower version of the driver. But your physical machine must have sufficient CPU speed to run two VM concurrently, to avoid the "emulation drift" of the the serial driver.
Well, just my guess, but there is a VirtualBox version of your problem, seemingly no issues running it:
http://bodocsi.net/2011/02/how-setup-serial-port-link-in-virtualbox-between-two-guest-virtual-machine-in-linux/
But the following bug ticket for VirtualBox does describe many similarities to your problem:
https://www.virtualbox.org/ticket/1548
And reading the end seemingly indicate the solution has to do with VirtualBox's internal source code. Perhaps it is Hyper-V's problem?

Resources