Socat: quando i dati passano via rete

Lavorando coi sistemi embedded molte volte mi capita di dovermi arrangiare su diverse cose, alcune volte la cosa è banale e poco interessante, ma altre no; in particolare, da un cliente, mi è capitato di dover testare le funzionalità di un modem GSM/GPRS collegato ad un sistema embedded ARM.

Il problema non era tanto nel test in se ma nel come poter accedere al modem (non poteva infatti essere scollegato dal sistema) utilizzando i tool standard che di solito si impiegano in questi casi. Il sistema del mio cliente era minimale, quindi non era subito disponibile nessun tool particolare tranne busybox, ed anche mettersi lì a ricompilare tutti i tool che mi sarebbero serviti era una soluzione poco fattibile, dato che non potevo stare tutto il giorno a ricompilare anziché testare il modem (venivo pagato per i test non per ricompilare pacchetti a destra e a sinistra! :).

Quindi come fare? Beh, la soluzione è abbastanza semplice: i tool di test del modem girano sul mio PC ed i dati  verso  e da il modem passano via rete; in pratica si realizza un collegamneto del genere (ASCII art):

 PC                      Embedded               Modem
+——————+    +—————–+    +—–
|   /dev/ttyS4<-+  |    | +->/dev/ttyUSB0 |<–>|
|               |  |    | |               |    +—–
|   +———–+  |    | +———-+    |
|   |              |    |            |    |
|   +->socat<->TCP |<–>| TCP<->a2e<-+    |
+——————+    +—————–+

Si tratta cioè di inviare tutti i dati che arrivano dal modem, attaccato alla porta ttyUSB0 del sistema embedded, su di un socket TCP; dal PC quindi, basta effettuare una connessione TCP verso il sistema embedded e rigirare di nuovo il flusso dati su di un dispositivo seriale (virtuale, in questo caso). L’ultimo passaggio mi serve per fare in modo che i tool di test del modem GSM non si accorgano di nulla e pensino di lavorare su di un dispositivo seriale fisico a cui è attaccato direttamente il modem!

I due programmi che ho utilizzato sono socat e a2e.

Il primo programma, socat, come detto anche nel sito del progetto, è considerato una sorta di netcat++ (gergo per indicare una evoluzione di netcat), in pratica è un tool che invia e riceve dati via rete ed estende le funzionalità di netcat. In particolare noi lo useremo per collegarci via rete al sistema embedded e convertire il flusso dati in un terminale. Questo ultimo passo è realizzato grazie ai terminali virtuali o pseudo terminal. In pratica dei terminali emulati dal sistema e non fisicamente collegati a nessun terminale reale.

Il secondo programma, s2e, è una utility presente nel sistema di sviluppo dell’XPort Pro (un web server di cui ho già avuto modo di parlare in passato) e serve a convertire un flusso dati da e per una porta seriale verso un socket di rete.

La prima domanda che potrebbe sorgere spontanea è: perché usare a2e e non usare direttamente socat anche sul sistema emebdded? La risposta è altrettanto semplice: perché compilare socat sul sistema embedded (date le risorse software limitate) non è banale, mentre per compilare s2e basta un comando del compilatore!

Ok, chiarito questo vediamo come fare. Una volta trasferito il programma compilato di s2e sul sistema embedded ho usato il seguente file di configurazione:

# s2e.config
tty {
        device  /dev/ttyUSB0    # device
        baudrate 9600           # baudrate
        parity  none            # parity <none/odd/even>
        stopbit 1               # stopbit <1/2>
        length  8               # data length <5/6/7/8>
        flow    none            # flow control <none/soft/hard>
        dma     disable         # dma transfer mode <disable/enable>
        timeout 1000            # tty timeout for tx trigger (msec)
        size    2048            # size for tx trigger <0/1-2048>
        delim   0a              # xxxx (hex 1 or 2 bytes)
}

net {
        mode    server          # mode <disable/server/client>
        host    0.0.0.0         # host ipv4 address
        proto   tcp             # protocol <tcp/udp>
        port    5000            # port number
}

In pratica non ho fatto altro che dire a s2e quali sono i parametri di gestione della porta seriale usata per parlare con il modem GSM e la porta a cui attendere connesisoni di tipo TCP/IP (la 5000).

Una volta salvato il file s2e.conf si lancia il programma con:

# s2e -C s2e.conf

A questo punto s2e si mette in ascolto sulla porta 5000 del sistema embedded.

Andiamo ora sul PC; per dire a socat di collegarsi al sistema embedded e di rigirare il flusso dati da e per uno pseudo terminale si usa il comando:

# socat pty,link=/dev/ttyS4 /tmp/pipe tcp:192.168.0.221:5000

La seconda parte del comando serve per stabilire la connessione TCP/IP mentre la prima apre uno pseudo terminale e chiede a socat di creare un link simbolico verso il nuovo device (che viene creato dinamicamente) in modo da poterlo poi trovare ed usare subito. Il nome che ho scelto, /dev/ttyS4, è ovviamente strategico; infatti ho simulato il fatto di avere una nuova porta seriale presente nel sistema la quale, se fosse stata un porta seriale fisica, avrebbe preso quel nome.

Se socat non dà errori ecco quello che dovreste ottenere:

# mike@mike-desktop:~$ ls -l /dev/ttyS*
crw-rw—- 1 root dialout 4, 64 Jun 18 11:33 /dev/ttyS0
crw-rw—- 1 root dialout 4, 65 Jun 18 11:33 /dev/ttyS1
crw-rw—- 1 root dialout 4, 66 Jun 18 09:11 /dev/ttyS2
crw-rw—- 1 root dialout 4, 67 Jun 18 09:11 /dev/ttyS3
lrwxrwxrwx 1 root root       10 Jun 18 11:32 /dev/ttyS4 -> /dev/pts/1

Come si vede, socat ha creato un link simbolico allo pseudo terminale /dev/pts/1.

A questo punto il gioco è fatto! Se provo a lanciare il programma di configurazione di wvdial, in modo tale che lui cerchi di identificare il modem automaticmente, ottengo:

mike@mike-desktop:~$ sudo wvdialconf
Editing `/etc/wvdial.conf’.

Scanning your serial ports for a modem.

ttyS0<*1>: ATQ0 V1 E1 — failed with 2400 baud, next try: 9600 baud
ttyS0<*1>: ATQ0 V1 E1 — failed with 9600 baud, next try: 115200 baud
ttyS0<*1>: ATQ0 V1 E1 — and failed too at 115200, giving up.
ttyS1<*1>: ATQ0 V1 E1 — failed with 2400 baud, next try: 9600 baud
ttyS1<*1>: ATQ0 V1 E1 — failed with 9600 baud, next try: 115200 baud
ttyS1<*1>: ATQ0 V1 E1 — and failed too at 115200, giving up.
Modem Port Scan<*1>: S2   S3   
WvModem<*1>: Cannot get information for serial port.
ttyS4<*1>: ATQ0 V1 E1 — OK
ttyS4<*1>: ATQ0 V1 E1 Z — OK
ttyS4<*1>: ATQ0 V1 E1 S0=0 — OK
ttyS4<*1>: ATQ0 V1 E1 S0=0 &C1 — OK
ttyS4<*1>: ATQ0 V1 E1 S0=0 &C1 &D2 — OK
ttyS4<*1>: ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0 — OK
ttyS4<*1>: Modem Identifier: ATI — 332
ttyS4<*1>: Speed 4800: AT — OK
ttyS4<*1>: Speed 9600: AT — OK
ttyS4<*1>: Speed 19200: AT — OK
ttyS4<*1>: Speed 38400: AT — OK
ttyS4<*1>: Speed 57600: AT — OK
ttyS4<*1>: Speed 115200: AT — OK
ttyS4<*1>: Speed 230400: AT — OK
ttyS4<*1>: Speed 460800: AT — OK
ttyS4<*1>: Max speed is 460800; that should be safe.
ttyS4<*1>: ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0 — OK

Found a modem on /dev/ttyS4.
Modem configuration written to /etc/wvdial.conf.
ttyS4<Info>: Speed 460800; init “ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0”

Bingo!

Su Rodolfo Giometti

Ingegnere informatico libero professionista ed esperto GNU/Linux offre supporto per: - device drivers; - sistemi embedded; - sviluppo applicazioni industriali per controllo automatico e monitoraggio remoto; - corsi di formazione dedicati. Manutentore del progetto LinuxPPS (il sottosistema Pulse Per Second di Linux) contribuisce attivamente allo sviluppo del kernel Linux con diverse patch riguardanti varie applicazioni del kernel e dispositivi (switch, fisici di rete, RTC, USB, I2C, network, ecc.). Nei 15+ anni di esperienza su Linux ha lavorato con le piattaforme x86, ARM, MIPS & PowerPC.

Lascia un commento

Utilizzando il sito, accetti l'utilizzo dei cookie da parte nostra. maggiori informazioni

Questo sito utilizza i cookie per fonire la migliore esperienza di navigazione possibile. Continuando a utilizzare questo sito senza modificare le impostazioni dei cookie o clicchi su "Accetta" permetti al loro utilizzo.

Chiudi