Tag alix
13/2/2010 Jouons avec kvm
J'ai codé un petit programme tout simple qui fait clignoter les leds de mon routeur dès qu'un service est par terre. Ma méthode (qui ne doit pas être la meilleure mais je m'en fout un peu) consiste à regarder régulièrement la liste des processus et détecter l'arrêt d'un service quand le processus associé n'existe plus. J'ai commencé avec un script shell, puis étant assez mauvais pour tout ce qui ressemble de près ou de loin à du script j'ai décidé de le faire en C (langage d'excellence n'est ce pas...?).
Je me suis volontairement compliqué la tache en utilisant des fonctions très proches du système, ainsi s'il est possible d'obtenir une liste de processus via ps(1) avec un popen(3) super crade ou encore sysctl(3) j'ai voulu utiliser kvm(3) kernel memory interface qui est en programmation système la méthode la plus appropriée (d'ailleurs 'ps' est codé avec ça), c'est juste une interface qui va nous permettre d'accéder au données du kernel (une copie bien entendu), ici la liste des processus en cours.
Le hic c'est que si les fonctions de kvm sont très standard l'implémentation est très différente suivant les systèmes, comme à peu près toute implémentation, l'important c'est que l'interface soit standard. Ainsi à la lecture de la structure qui décrit les processus kinfo_proc de sys/user.h on se dit chouette pleins d'info à disposition, sauf que sur OpenBSD c'est pas du tout la même forme (ni le même fichier d'ailleurs). D'où l'importance d'une interface riche et c'est ce que nous promet kvm.
Assez causé passons au code (je n'explique pas ou peu le code en dehors des fonctions kvm)
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <err.h> #include <libgen.h> #include <fcntl.h> #include <limits.h> #include <paths.h> #include <kvm.h> #include <sys/param.h> #include <sys/sysctl.h> #include <sys/wait.h> #include <sys/user.h> void start_leds(void) { /* Ici on execute /usr/sbin/gioctl -q gpio0 led3 (on|off) * suivant la parité du conteur statique 'i' * 60 fois avec une pause d'une seconde. */ static int i = 1; switch(fork()) { case -1: err(1, "fork"); break; case 0: execl("/usr/sbin/gpioctl", "gpioctl", "-q", "gpio0", "led3", (i%2) ? "on" : "off", (char*)NULL); err(1, "execl"); break; default: wait(NULL); break; } sleep(1); if (i++ <= 60) return start_leds(); return; } int main(int argc, char *argv[]) { kvm_t *kd; char berr[_POSIX2_LINE_MAX]; struct kinfo_proc *p, *procs; int n, j, k, found = 0; char **pargv; if (argc < 2) errx(1, "Usage check_proc procs ..."); /* On accède aux données du kernel qui tourne actuellement (NULL) */ if (!(kd = kvm_open(NULL, NULL, NULL, O_RDONLY, berr))) errx(1, "%s", berr); /* On demande la liste des processus, kinfo_proc est décrite * dans sys/sysctl.h sur OpenBSD et sys/user.h sur FreeBSD. * Il nous la donne dans un tableau continu de pointeurs de * taille qu'on récupère dans 'n'. */ if (!(procs = kvm_getprocs(kd, KERN_PROC_ALL, 0, &n))) err(1, "kvm_getprocs: %s", kvm_geterr(kd)); for (k = 1; k < argc; k++) { for (j = 0, p = procs; j < n; j++, p++) { /* On accède à la liste des arguments du programme qui a * généré le processus courant. */ pargv = kvm_getargv(kd, p, 0); if (pargv && pargv[0] && strstr(pargv[0], argv[k])) { found++; break; } } } if (-1 == kvm_close(kd)) err(1, "kvm_close"); if (found != argc-1) start_leds(); return 0; }
Et l'exécution, on veut tester si un processus du nom de 'dhcpd' tourne sur le système, si ce n'est pas le cas on lance le clignotement de la led pendant une minute :
# gcc -o check_proc check_proc.c -lkvm # ./check_proc dhcpd
Le mien s'exécute dans un cron toute les minutes :
* * * * * /root/bin/check_proc named dhcpd adsuck ntpd
8/2/2010 Alix fail et OpenWrt
Ce week end j'ai essuyé pas mal d'échecs en tout genres, j'ai une superbe alix qui tourne sur OpenBSD et j'ai une carte wifi en minipci dessus qui marche passablement mal sur OpenBSD (tous les modes ne marchent pas et beaucoup de pertes de paquets quand ça marche).
Du coup je me mis en tête le fait que ça tournera mieux sous un autre OS, j'ai donc essayé dans l'ordre FreeBSD, Debian et OpenWrt. Aucuns n'a su faire tourner ma carte même avec les derniers drivers, j'avais même pas d'interface, comme quoi le support matériel sur OpenBSD est pas aussi mauvais qu'on le pense.
Donc si quelqu'un à réussi à faire tourner convenablement la carte Engenius NMP-8602+ 400mW a/b/g miniPCI sur un OS libre merci de me faire signe.
J'ai donc remis OpenBSD dessus et enlevé la carte wifi (si quelqu'un est intéressé je suis prêt à la céder d'ailleurs, toute neuve jamais servie :>)
J'ai quand même beaucoup joué avec le boot pxe sur sortie série Linux/BSD donc je suis bien rodé là dessus maintenant. Et surtout j'ai découvert OpenWrt, une toute petite distribution linux pour l'embarqué, faite à la base pour flasher les firmware proprio sur les routeurs du marché elle tourne aussi bien sur tout autre matériel et c'est un projet très dynamique et original. L'installation par pxe est super simple, il suffit de compiler un ramdisk et de démarrer dessus.
$ ls -l /usr/local/pxe/ total 1796 -rw-r--r-- 1 phil phil 1786396 Feb 7 15:41 openwrt-x86-vmlinuz -rwxr-xr-x 1 root wheel 16466 Feb 6 21:31 pxelinux.0 drwxr-xr-x 2 root wheel 512 Feb 7 15:41 pxelinux.cfg $ cat /usr/local/pxe/pxelinux.cfg/default # Simplement spécifier la vitesse du port série # 38400 ici serial 0 38400 0 console 0 label linux kernel openwrt-x86-vmlinuz append init=/etc/preinit console=tty0 console=ttyS0,38400n8 reboot=bios
Après c'est du pxe classique, tftp et dhcpd et ça démarre :

Après il suffit d'envoyer l'image sur le disque dur (soit la votre, soit celle qui est distribuée) :
root@Solo:/# wget http://downloads.openwrt.org/kamikaze/8.09.2/x86/openwrt-x86-squashfs.image root@Solo:/# dd if=openwrt-x86-squashfs.image of=/dev/hda
Et c'est tout !
À coté de ça vous avez une interface de configuration web convi, un petit sshd dropbear et pleins de packages disponible (très orienté réseau bien sûr). Ça doit être encore plus réjouissant quand on flashe un routeur wifi proprio :)
Mais bon, alix mérite qu'on l'exploite plus que ça, j'aime bien l'interface web mais j'aime mieux éditer mon pf.conf avec vim.
2/11/2009 Controler les leds sur ALIX 2D3
Il y a 4 leds sur le devant, la première est réservée par l'alimentation et la dernière par la carte minipci, mais les deux autres sont à disposition pour nos amis scripteur. Ces deux leds se contrôlent sur les broches 25 et 27 du gpio.
Il faut les activer avant que securelevel passe à 1. Dans /etc/rc.securelevel :
# Configuring the leds echo -n "Configuring the leds : " /usr/sbin/gpioctl gpio0 25 set out led2 /usr/sbin/gpioctl gpio0 27 set out led3
Un petit reboot, et vous pouvez controler vos leds (q = quiet) avec :
gpioctl -q gpio0 led2 off gpioctl -q gpio0 led2 on
A vous de scripter ce que vous voulez derrière, style un script qui fait clignoter la led si la passerelle est accessible etc.