dimanche 13 décembre 2020

TinySA

Un petit 'spectrum analyser' étonant, le tinySA. Une cinquantaine d'euros, il permet de se faire une idée du spectre électromagnétique jusqu'à 960 MHz.

Une première captation autour de 162 MHz, avec l'option 'Max hold', où l'on voit les deux canaux de l'AIS à 161.975 et 162.025 MHz. C'est capté du côté de la Citadelle de Liège et c'est émis par des bateaux, en contrebas sur la Meuse. Il faut noter que le scan sur 100 kHz dure 514 mS et que donc, on loupe des paquets. Ceux-ci, émis à 9600 bauds ne font que 168 ou 440 bits et ne sont donc présent que 20 ou 40 mS. Il arrive aussi que le TinySA ne voie que le début ou la fin du paquet et on n'a donc qu'une partie du spectre. La partie qu'il était en train de scanner pendant sa transmission. D'où l'utilisation de 'Max hold' pour cumuler les spectre.


Spectre UHF, jusqu'à 500 MHz, du côté de la Place Saint-Lambert à Liège. Pas de 'Max hold' ici, pour différencier les émissions continues des émissions par paquets.


En allant jusqu'à 960MHz, on voit des bandes GSM (?).




Bizarre, bizarre, le plan des fréquences de l'IBPT ne semble pas aider beaucoup à l'identification des signaux.

Un bout de la bande FM avec 'Max hold'. Le petit pic à droite du curseur est Bel-RTL sur 103.6.


Sur Linux,
$ sudo minicom -D /dev/ttyACM0 -b 115200

ch> help

Commands: version reset freq dac saveconfig clearconfig data frequencies scan scanraw sweep test touchcal 
touchtest pause resume caloutput save recall trace trigger marker usart capture vbat vbat_offset help info
 color if attenuate level sweeptime leveloffset levelchange modulation rbw mode spur load offset output
 deviceid selftest correction threads
permet de contrôler le TinySA en mode terminal

lundi 1 juin 2020

Simple ad hoc SNMP

SNMP est l'acronyme de 'Simple Network Management Protocol' et, comme tout ce qui est simple, cela fini par devenir compliqué...

Ci-dessous un petit programme en 'C', utilisant la librairie Net-snmp pour extraire quelques valeurs de la dskTable en SNMP version 2c.

Le programme fait une peu plus d'une centaine de lignes. On passe en paramètre la cible, la 'community string' et un index. Une session est ouverte vers la machine cible avec sa 'community string', un PDU est construit pour interroger 4 variables. Les 4 OIDs sont construites à partir de l'OID de base et un index passé en paramètre au programme. Le programme envoie la requête et reçoit la réponse. On suppose que la réponse reflète la requête et que l'on reçoit, dans l'ordre, les chaînes de caractères dskPath, dskDevice et les entiers dskUsed et dskTotal. Il ne reste plus qu'à les imprimer. Tous les problèmes possibles ne sont pas traités en profondeur mais il y a quand même un minimum de 'sanity checks'.

#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>

#define DSK_PATH 2
#define DSK_DEVICE 3
#define DSK_TOTAL 6
#define DSK_USED 8
unsigned char oid_str[128];
char *oid_template = ".1.3.6.1.4.1.2021.9.1.%d.%d"; /* What, idx */

void build_part_req(netsnmp_pdu *pdu, int idx, int what)
 {
 oid oid_buf[128];
 size_t oid_len;

 sprintf(oid_str, oid_template, what, idx);
 if (!snmp_parse_oid(oid_str, oid_buf, &oid_len))
  {
  fprintf(stderr, "error snmp_parse_oid()\n");
  exit(-1);
  }
 snmp_add_null_var(pdu, oid_buf, oid_len);
 }
netsnmp_pdu *build_req(int idx)
 {
 netsnmp_pdu *pdu;

 pdu = snmp_pdu_create(SNMP_MSG_GET);

 build_part_req(pdu, idx, DSK_PATH);
 build_part_req(pdu, idx, DSK_DEVICE);
 build_part_req(pdu, idx, DSK_USED);
 build_part_req(pdu, idx, DSK_TOTAL);
 return(pdu);
 }
void use_it(struct snmp_pdu *response)
 {
 char buf[1024];
 struct variable_list *vp;
 char dskPath[1024];
 char dskDevice[1024];
 long dskUsed;
 long dskTotal;

 if (response->errstat == SNMP_ERR_NOERROR)
  { /* vp->type (4=str; 2=int), vp->val.string, *vp->val.integer ; snprint_variable(), snprint_value() */
  vp = response->variables;
  strcpy(dskPath, vp->val.string); /* DSK_PATH */
  vp = vp->next_variable;
  strcpy(dskDevice, vp->val.string); /* DSK_DEVICE */
  vp = vp->next_variable;
  dskUsed = *vp->val.integer;  /* DSK_USED */
  vp = vp->next_variable;
  dskTotal = *vp->val.integer;  /* DSK_TOTAL */
  printf("%ld/%ld for %s on %s\n", dskUsed, dskTotal, dskPath, dskDevice);
  }
 else {
  printf("Uhm... : response->errstat = 0x%lx\n", response->errstat);
  }
 }
struct snmp_session *open_session(char *host, char *community)
 {
 struct snmp_session ss, *sp;

 init_snmp("get_snmp_fs");
 snmp_sess_init(&ss);
 ss.version = SNMP_VERSION_2c;
 ss.peername = strdup(host);
 ss.community = strdup(community);
 ss.community_len = strlen(community);
 if ((sp = snmp_open(&ss)) == NULL)
  {
  snmp_perror("snmp_open");
  exit(-1);
  }
 return(sp);
 }
void main (int argc, char **argv)
 {
 struct snmp_session *sp;
 netsnmp_pdu *req, *resp;
 char  *host, *community;
 int  index, status;

 if (argc != 4)
  {
  fprintf(stderr, "usage is '%s <host> <community> <index>\n", argv[0]);
  exit(-1);
  }
 host = argv[1];
 community = argv[2];
 index = atoi(argv[3]);

 sp = open_session(host, community);
 req = build_req(index);

 if ((status = snmp_synch_response(sp, req, &resp)) == STAT_SUCCESS)
  use_it(resp);
 else fprintf(stderr, "snmp_synch_response() returns %d\n", status);

 snmp_free_pdu(resp);
 snmp_close(sp);

 exit(0);
 }


Le Makefile, lui aussi, réduit à sa plus simple expression est :

CFLAGS=-I. `net-snmp-config --cflags`
BUILDLIBS=`net-snmp-config --libs`

get_snmp_fs: get_snmp_fs.o
 gcc -o get_snmp_fs get_snmp_fs.o $(BUILDLIBS)




Et maintenant, le test...



On regarde d'abord un disque avec df(1). On retrouve son indice en faisant un snmpwalk(1). On peut retrouver plusieurs valeurs avec snmpget(1) et les comparer avec ce que le programme ci-dessus donne.

$ df -h |grep sda1
/dev/sda1       916G  159G  711G  19% /


$ snmpwalk localhost -Os -m /usr/share/snmp/mibs/UCD-SNMP-MIB.txt -v 2c -c public  dskPath
dskPath.1 = STRING: /
dskPath.2 = STRING: /var
dskPath.3 = STRING: /
dskPath.4 = STRING: /run
dskPath.5 = STRING: /dev/shm
dskPath.6 = STRING: /run/lock
dskPath.7 = STRING: /sys/fs/cgroup


$ snmpget localhost -Os -m /usr/share/snmp/mibs/UCD-SNMP-MIB.txt -v 2c -c public  dskPath.1 dskDevice.1 dskUsed.1 dskTotal.1
dskPath.1 = STRING: /
dskDevice.1 = STRING: /dev/sda1
dskUsed.1 = INTEGER: 166654692
dskTotal.1 = INTEGER: 960379920


$ ./get_snmp_fs localhost public 1
166654708/960379920 for / on /dev/sda1


Les machines actuelles sont tellement rapides qu'il est difficile de mesurer la différence entre un programme ne faisant qu'un échange de PDUs et un programme qui doit, en plus, analyser une MIB (sinon plusieurs)... J'avais été motivé par le fait que Nagios utilise souvent des scripts shell lançant des tas de processus pour exécuter des fonctions élémentaires.

vendredi 17 avril 2020

De grand matin...

Activité aéroportuaire, ce jeudi 16 avril 2020, entre 04h13 et 05h13 captée avec un stick RTL-SDR (NewGen/RTL2832SDR alu TCXO .5 ppm) et dump1090 de la Citadelle de Liège... De la Citadelle de Liège, on capte l'ADS-B jusque Nancy.

jeudi 2 janvier 2020

SigInt ISM433

Petite captation sur la bande ISM 433 MHz avec un stick RTL-SDR v3, centrée sur 433.500 MHz avec 2048000 échantillons par seconde.

En regardant avec SDRAngel (ou sdrangelove)
En regardant avec gnuradio, on remarque de courtes trames centrées vers 433.922 MHz.
En important les données dans GNUoctave et en s'intéressant à la magnitude du signal, on observe :
En regardant de plus près, cela ressemble à du codage Manchester modulé en amplitude (ASK/OOK). Ce qui ne semble pas très économe en bande passante(?).
En s'intéressant à quelques bits seulement, on devrait pouvoir déduire le 'baud rate'...
En principe, on a tout pour créer un système pour décoder les trames avec gnuradio-companion...

Avec GnuRadio

(je ne maîtrise pas GnuRadio...) La première chose à faire est d'isoler le signal intéressant avec le 'Frequency Xlating FIR filter bloc'.
En envoyant ça dans 'Complex to Mag', puis dans un fichier qu'on analyse avec Octave, on obtient :


Autre signal, un FSK très soutenu

Si on s'intéresse au signal en FSK un peu à gauche, avec le bloc, 'Quadrature demod', le signal ressemble à :