Je me prends la tete depuis qqes jours/semaines de temps en temps sur la doc
CUDA,
tout n'est pas très clair, mais ça l'est devenu un peu plus grâce a ce lien
:
http://www.caam.rice.edu/~timwar/RMMC/CUDA.html
Enjoy!
Aller au contenu | Aller au menu | Aller à la recherche
mercredi 3 avril 2013
Par eau le mercredi 3 avril 2013, 11:40 - geeking
Je me prends la tete depuis qqes jours/semaines de temps en temps sur la doc
CUDA,
tout n'est pas très clair, mais ça l'est devenu un peu plus grâce a ce lien
:
http://www.caam.rice.edu/~timwar/RMMC/CUDA.html
Enjoy!
dimanche 23 décembre 2012
Par eau le dimanche 23 décembre 2012, 21:31 - geeking
rhalalal je perds parfois du temps en conneries, la j'en ai vraiment perdu
beaucoup sur une bêtise...
Je ne pigeais pas pourquoi un read(bpf_fd, buffer, size) me retournait
un EINVAL a chaque fois...
et j'ai juste relu religieusement bpf(4) et voila ce qu'on y trouve d'intéressant en étant un tout petit peu "attentif":
[...] Reads from these files return the next group of packets that have matched the filter. To improve per- formance, the buffer passed to read __MUST BE THE SAME SIZE AS THE BUFFERS USED INTERNALLY BY BPF__. This size is returned by the BIOCGBLEN ioctl (see below), and can be set with BIOCSBLEN. Note that an indi- vidual packet larger than this size is necessarily truncated. [...]
Et voila... c'est aussi bête que ça et ça marche... grmlbmlmb
jeudi 7 juin 2012
Par poz le jeudi 7 juin 2012, 15:14 - geeking
Une petite news pour dire qu'on vit encore, et j'en profite pour vous vendre un tool bien sympathoche.
Un collègue de bureau m'a montré l'existence de cppcheck, et je dois dire que c'est pas mal du tout, ce truc.
C'est un outil d'analyse statique pour du C/C++. Il est intégré (ou intégrable) à des IDE, pour ceux qui s'en servent, pour plus de facilité d'utilisation.
Ça sort des rapports au format xml/html faciles à exploiter, il y a relativement peu de faux positifs, trouve aisément des memory leaks, etc.
Bref, une petite passe sur chaque projet aide à trouver des bugs en très peu de temps.
Ouala, c'est tout, enjoy ! :)
Edit : il y a aussi l'utilitaire de la suite clang, le bien nommé `scan-build'. Dans un repository il suffit de taper `scan-build make' puis `scan-view <nom du rapport>'. Ça marche bien et c'est un bon complément à cppcheck.
lundi 19 mars 2012
Par eau le lundi 19 mars 2012, 18:04 - geeking
Un tres simple introduction au NDK Android sur un billet sympathique et a lire pour ceux qui veulent s'y mettre! (et le cross compilo facile c'est par la aussi!! :))
https://www.synthetos.com/blog/native-embedded-code-on-android/
jeudi 16 février 2012
Par poz le jeudi 16 février 2012, 13:45 - geeking
Dans la même veine qu'un précédent ticket, j'avais besoin de faire une tâche particulière : calculer la distance de Hamming entre plusieurs fichiers, dans un objectif absolument top secret de ouf.
Contrairement à fdup(1), cette fois j'ai (rapidement) cherché dans les dépôts debian/ubuntu si un truc existait déjà. En regardant un peu kdiff3, xdelta, etc, j'ai rien trouvé de bien satisfaisant, alors je l'ai codé. C'est absolument bidon, je préviens, mais ptet que ça servira à quelqu'un, sait-on jamais...
C'est par ici : hamming.
lundi 13 février 2012
Par poz le lundi 13 février 2012, 10:42 - geeking
Bon, ce week end je me faisais passablement chier, et en explorant le contenu de mon $HOME je me suis rendu compte que c'était un peu le bordel, quand même. Des fichiers inutiles, des doublons, etc.
Du coup, illumination, le doigt du génie a effleuré mon front obtus l'espace d'un instant : et si je codais un truc-machin pour repérer tous les fichiers identiques sur ma machine ?!
Et voilà, fdup est né (c'est du C, parce que comme je m'embêtais je voulais pas faire un "one-liner" en shell avec find(1) + awk(1), faut bien s'occuper) ! C'est super minimaliste pour l'instant, hein, y'a genre 2-3 options qui se tirent la bourre, et pis c'est tout.
Je vous entends ricaner d'ici : bien sûr qu'il y a d'autres outils qui font le même boulot (fdupes(1), duff, y'a même un fdup déjà présent sur github -- bon, la description dans le README est un peu nawak mais on s'en fout !), mais ça, je m'en suis aperçu qu'après mon premier commit. Comme d'hab'.
mardi 18 octobre 2011
Par eau le mardi 18 octobre 2011, 17:50 - geeking
En ces temps de gang bang d'ego généralisé, de benchmarking de performance sur l'échelle Ritchie (RIP) et autre courses a la réussite sociale, il reste des gens dont la carriere et la publication frénétique d'information pour voir son nombre de hits et ses fans augmenter toute en mimant le désintérêt et le detachement n'est pas au centre de leur vie et arrivent a s'amuser et surtout a avoir de l'auto derision, ca m'a fait hurler de rire alors que c'est completement debile, mais c'est pas grave, j'ai ris, ca fait du bien! donc je "share" :)
Sa premiere idee farfelue (hahahaha):
/* ** pam_happy_hour.c - PAM happy hour auth module. Solaris 2.6+ ** During happy hour passwords aren't required, any will do. ** [...]
Allez j'en pioche une autre dans le tas (:~)):
# maybe - companion to /usr/bin/true and /usr/bin/false. # # This should be installed in your system location, eg /usr/bin/maybe. [...]
Et il en a fait pleins d'autre aussi farfelue a voir la:
vendredi 7 octobre 2011
Par poz le vendredi 7 octobre 2011, 15:15 - geeking
Beh voilà, encore un peu d'auto-promotion. Et en fait j'ai un peu menti, ça fait plusieurs mois que je ne commit qu'un bout de code par-ci ou par-là.
Ma société a écrit une bibliothèque en open source pour travailler sur le cloud (différents protocoles supportés, mais je vous laisse découvrir ça). Bref, je me suis basé sur cette lib pour implémenter un filesystem en utilisant FUSE : dropletfs ; c'est lent (car le design est simpliste et pas optimisé), mais rigolo.
Toutes les features d'un FS posix ne sont pas présentes, loin de là (gérer les hardlinks est plutôt compliqué), mais pour un usage basique, ça 'juste marche'.
Une petite démo intéractive (nécessite le package ttyrec) : ici
jeudi 17 février 2011
Par poz le jeudi 17 février 2011, 13:26 - geeking
Yo yo yo.
J'avais une base de code, avec pas mal de fonctions déjà implémentées, et
puis je me suis dit "ooooomm, faudrait que je trace le temps d'exécution de
chacune de ces fonctions, pour savoir où concentrer mes efforts, en faisant
telle et telle stat'". Bon alors je vous entends déjà barir au loin "hey mais
pauvre naze, y'a plein d'outils de profiling", et c'est vrai. Seulement je
voulais faire un truc à ma sauce d'une part (histoire de voir un peu comment ça
fonctionne), et surtout pouvoir ajouter les stats qui m'intéressent, faire des
trucs aux p'tits oignons quoi. Et puis c'est pas comme si ça prenait des jours
à coder.
Alors après avoir cherché un peu, je tombe sur la doc GCC (même le man en parle, à vrai dire) :
void __cyg_profile_func_enter(void *func, void *callsite); void __cyg_profile_func_exit(void *func, void *callsite);
Ces fonctions sont appelées respectivement à l'entrée et la sortie de
chacune des fonctions de votre programme. Il y a une linuxerie ensuite pour
obtenir le nom de l'appelant, ie. passer par dladdr() ou
__build_return_address(0). Ensuite vous stockez les infos comme
vous voulez, perso j'utilise une hashtable dont les clefs sont les symboles
(aka noms de fonctions), avec chaque cellule contenant des stats, sur le nombre
d'appel, le temps d'exécution moyen, etc.
J'ai utilisé ça pour un code sur lequel je passe un peu de temps en ce moment, et la sortie ressemble à (le > correspond à l'entrée dans la fonction, le < à la sortie, faudrait rendre le truc plus joli avec un système de pile pour avoir la profondeur d'appel de chacune en fonction d'un décalage horizontal, mais bon, ça viendra après) :
[...]
1297941768.719531 > dfs_mkdir@0x40f534
1297941768.719607 > dfs_mkdir_timeout@0x41398f
1297941769.416415 < dfs_mkdir_timeout@0x41398f -- 696ms
1297941769.416445 < dfs_mkdir@0x40f534 -- 696ms
1297941769.416469 > dfs_getattr@0x40c16c
1297941769.416684 > dfs_namei_timeout@0x413ef7
1297941769.534098 < dfs_namei_timeout@0x413ef7 -- 117ms
1297941769.534161 > dfs_getattr_timeout@0x413690
1297941770.104592 < dfs_getattr_timeout@0x413690 -- 570ms
1297941770.104874 < dfs_getattr@0x40c16c -- 570ms
-- report --
symbol dfs_getattr_timeout: #calls: 46, average call duration: 266ms
symbol dfs_opendir_timeout: #calls: 1, average call duration: 780ms
symbol dfs_namei_timeout: #calls: 47, average call duration: 299ms
symbol dfs_chdir_timeout: #calls: 1, average call duration: 0ms
symbol dfs_mkdir: #calls: 1, average call duration: 696ms
symbol dfs_getattr: #calls: 48, average call duration: 275ms
symbol dfs_mkdir_timeout: #calls: 1, average call duration: 696ms
Le code (crados, pas encore nettoyé) est visible ici.
Comme je disais, le truc vraiment sympa c'est juste d'avoir à appeler
profile_init() et profile_fini() dans mon code. Et
encore, on peut faire mieux en générant un .so qu'on charge avec
LD_PRELOAD, histoire d'avoir vraiment 0 code impacté. Faut juste
compiler les objets avec -fPIC et
-finstrument-functions. That's all folks.
OK c'est un profiler du pauvre, mais ici à unix4fun, on est prolos. Et on vous emmerde !
mardi 21 décembre 2010
Par poz le mardi 21 décembre 2010, 20:51 - geeking
Un peu de proselytisme ne fait jamais de mal, alors voilà Junkie, un sniffer releasé en Open Source par la société SecurActive.
Pour l'instant il a été programmé pour tourner sur du Linux debian-like, donc...
Un extrait du README:
Compared to previously available tools junkie lies in between tcpdump and wireshark. Unlike tcpdump, its purpose is to parse protocols of any depth; unlike wireshark, through, junkie is designed to analyze traffic in real-time and so cannot parse traffic as completely as wireshark does. In addition, junkie's design encompasses extendability and speed: - plug-in system + high-level extension language that eases the development and combination of new functionalities; - threaded packet capture and analysis for handling of high bandwidth network; - modular architecture to ease the addition of any protocol layer; - based on libpcap for portability; - well tested on professional settings.
Il manque un "IPv6 compliant" je pense, dans ce README.
Seuls les parseurs sont releasés en Open Source, mais c'est déjà bien sympa. Le design est fait de telle sorte qu'il est facile d'ajouter un plugin d'analyse pour un protocole particulier 1. Et pour ceux qui n'aiment pas le C, il y a possibilité d'exercer vos talents de codeurs Scheme (guile plus précisemment), car il est scriptable à l'aide de ce langage ! Ouh ouh !
Un petit exemple d'utilisation ? OK, c'est parti :
$ sudo ./src/junkie -i wlan0 -c config/start-repl.scm 2010-12-22 00:36:45: J-main: log.c/log_set_file: Opening log file.
OK, là on lui a dit de loguer sur stdout, d'écouter l'interface wireless wlan0, et de prendre le fichier de conf par défaut qui active le REPL. Donc, dans un autre terminal, je vais me connecter sur la machine, en tcp/29000 pour ajouter des settings sur la mouche comme disent nos amis anglais (ie. "on the fly"... ok c'est nul).
$ rlwrap telnet localhost 29000 Trying ::1... Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. junkie> (set-iface-filter "wlan0" "icmp") #t junkie> (set-log-level 6) #<unspecified> junkie>
Les valeurs de retour affichées sont celles de guile, à savoir #t pour true, et
#<unspecified> pour dire qu'il n'y a pas de code de retour. C'est un peu
curieux au début, mais ceux qui ont utilisé ce langage ne seront pas
dépaysés.
Là je lui ai demandé de prendre en compte le filtre BPF (tcpdump, vous connaissez, hein ?) "icmp" pour l'interface wlan0.
Hey ouais, c'est ça qui est cool, on peut écouter sur différentes interfaces avec des filtres différents. Bref, dans un autre terminal je tape :
$ ping free.fr -c1 PING free.fr (212.27.48.10) 56(84) bytes of data. 64 bytes from www.free.fr (212.27.48.10): icmp_seq=1 ttl=118 time=37.1 ms --- free.fr ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 37.176/37.176/37.176/0.000 ms
Et si on repasse dans la console de log, on a :
Capture@0x23f0068: head_len=48, payload=60, dev_id=0, tv=1293009623s 788239us Ethernet@0x2413ea8: head_len=14, payload=46, vlan_id=0, source=00:1b:2f:2e:e0:fa, dest=ff:ff:ff:ff:ff:ff, proto=2054 Capture@0x23f0068: head_len=48, payload=74, dev_id=0, tv=1293009880s 139307us Ethernet@0x2413ea8: head_len=14, payload=60, vlan_id=0, source=00:1c:bf:9d:2e:21, dest=00:15:e9:f2:30:67, proto=2048 IPv4@0x2414e38: head_len=20, payload=40, version=4, addr=10.0.63.10->82.237.175.5, proto=6, ttl=64 TCP@0x23bcf08: head_len=40, payload=0, ports=42007->1234, flags=Syn, win=5840, ack=0, seq=902941316 Capture@0x23f0068: head_len=48, payload=98, dev_id=0, tv=1293009631s 741103us Ethernet@0x2413ea8: head_len=14, payload=84, vlan_id=0, source=00:1c:bf:9d:2e:21, dest=00:15:e9:f2:30:67, proto=2048 IPv4@0x2414e38: head_len=20, payload=64, version=4, addr=10.0.63.10->212.27.48.10, proto=1, ttl=64 ICMP@0x23bb198: head_len=64, payload=0, type=EchoRequest, err=NONE Capture@0x23f0068: head_len=48, payload=98, dev_id=0, tv=1293009631s 744391us Ethernet@0x2413ea8: head_len=14, payload=84, vlan_id=0, source=00:15:e9:f2:30:67, dest=00:1c:bf:9d:2e:21, proto=2048 IPv4@0x2414e38: head_len=20, payload=64, version=4, addr=212.27.48.10->10.0.63.10 (hashed the other way), proto=1, ttl=122 ICMP@0x23bb198: head_len=64, payload=0, type=EchoReply, err=NONE
Un lecteur attentif verra qu'il n'y a pas que de l'ICMP qui a été logué (cf. les premières lignes). Il a raison ! Mais comme je l'ai dit plus haut, on a changé la config à chaud, donc Junkie a eu le temps de loguer quelques paquets avant de prendre en compte le filtre BPF.
Et voilà ! Bon, c'est un exemple parmi des tonnes hein, chacun peut y trouver son compte, là c'est vraiment pour expliquer le fonctionnement. Pour plus d'infos :
$ junkie -h
Ou bien pour des détails vraiment poussés, dans le REPL :
junkie> (help) [...] junkie> (help 'commande)
1 Tutorial de codage d'un parseur : parser implementation
jeudi 4 novembre 2010
Par poz le jeudi 4 novembre 2010, 16:31 - geeking
Un billet assez exhaustif, avec des exemples de code et d'output assembleur : c'est ici
jeudi 7 octobre 2010
Par poz le jeudi 7 octobre 2010, 15:26 - geeking
Yo. Dans ce post je vais expliquer comment je me suis battu pour faire un
truc assez simple avec la libpcap sous linux.
Au début était un sniffer, je voulais écouter sur une interface à grands
coups de SOCK_RAW + recvfrom(). À l'ancienne, quoi. L'idée était de ne pas
utiliser de handler pcap (pcap_t *). Au bout d'un moment je me dis "tiens, ça
serait sympa d'ajouter les filtres BPF comme dans tcpdump". Brillante idée,
non ? Non, ok. Bref, le code de départ est le suivant :
// -*- c-basic-offset: 4; indent-tabs-mode: nil -*-
// vim:sw=4 ts=4 sts=4 expandtab
#include <limits.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <netinet/in.h>
#include <linux/if_ether.h>
#include <arpa/inet.h>
#include <netpacket/packet.h>
#include <poll.h>
#include <linux/types.h>
#include <errno.h>
#include <pcap.h>
#include <linux/filter.h>
#define FRAME_SIZE 65536
/* iface_setprom() sets "device" in promiscuous mode */
static int
iface_setprom(int sock_fd, const char *device)
{
struct ifreq ifr;
memset(&ifr, 0, sizeof ifr);
snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", device);
if (ioctl(sock_fd, SIOCGIFFLAGS, &ifr) == -1) {
printf("[%s] ioctl: %s.\n", device, strerror(errno));
return -1;
}
ifr.ifr_flags |= (IFF_PROMISC | IFF_UP);
if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr) == -1) {
printf("[%s] ioctl: %s.\n", device, strerror(errno));
return -1;
}
printf("[%s] enter in promiscuous mode\n", device);
return 0;
}
À partir d'une chaîne de caractère entrée, par exemple "tcp and port 22", on
veut obtenir une structure comprise par pcap_compile*(). Comme dit
précédemment, je ne veux pas de pcap_t* à manipuler, je vais donc utiliser
pcap_compile_nopcap() (non mentionné dans le man de pcap_compile sous linux,
évidemment).
/* iface_setfilter() applies a LSF filter to the file descriptor */
static int
iface_setfilter(int sock_fd, const char * const device, const char * const filter)
{
if (!filter || !*filter) {
printf("[%s] no filter to install\n", device);
return 0;
}
struct bpf_program bpf;
memset(&bpf, 0, sizeof bpf);
char errbuf[PCAP_ERRBUF_SIZE = "";
if (-1 == pcap_compile_nopcap(FRAME_SIZE, DLT_RAW, &bpf, filter, 1, 0)) {
printf("[%s] pcap_compile_nopcap failed for '%s'\n", device, filter);
return -1;
}
if (-1 == setsockopt(sock_fd, SOL_SOCKET, SO_ATTACH_FILTER, &bpf, sizeof bpf)) {
printf("[%s] setsockopt: %s (filter '%s')\n", device, strerror(errno), filter);
return -1;
}
printf("[%s] filter '%s' successfully installed\n", device, filter);
return 0;
}
/* iface_init() is the main device initialization function */
static int
iface_init(struct pollfd *fds, const char * const device, const char * const filter)
{
printf("Initializing interface %s (filter '%s')\n", device, filter);
fds->fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (fds->fd == -1) {
printf("[%s] socket: %s. Exiting...\n", device, strerror(errno));
exit(EXIT_FAILURE);
}
fds->events = POLLIN | POLLPRI;
if (0 != iface_setprom(fds->fd, device)) return -1;
if (0 != iface_bind(fds->fd, device)) return -1;
if (0 != iface_setfilter(fds->fd, device, filter)) return -1;
return 0;
}
static void
frame_manager(const char * const device, struct pollfd *fd, struct timeval const *now)
{
uint32_t i;
if ((fd->revents & (POLLIN | POLLPRI)) == 0)
return;
unsigned char buf[1500] = "";
ssize_t n = recvfrom(fd->fd, buf, sizeof buf, MSG_DONTWAIT, NULL, NULL);
if (n < 0) {
printf("[%s] recvfrom: %s (i=%d, fd=%d)\n", device, strerror(errno), i, fd->fd);
return;
}
printf("[%d,%d] packet received\n", (int)now->tv_sec, (int)now->tv_usec);
}
int main(int ac, char **av)
{
char *filter = "";
char *device = "dummy0";
if (ac > 1) {
filter = av[1];
}
struct pollfd fd;
(void)iface_init(&fd, device, filter);
while (/*CONSTCOND*/ 1) {
if (poll(&fd, 1, -1) > 0) {
struct timeval now;
gettimeofday(&now, NULL);
frame_manager(device, &fd, &now);
}
}
close(fd.fd);
return EXIT_SUCCESS;
}
Tout d'abord, je monte une interface virtuelle pour éviter le bruit généré
par les paquets circulants sur mes vraies interfaces :
$ sudo modprobe dummy $ sudo ifconfig dummy0 mtu 1600 up
Maintenant, si je compile et j'exécute le code, et que je balance du ssh sur
dummy0, j'ai ça :
$ cc -o cap cap.c -lpcap $ sudo ./cap "tcp and port 22" [...]
Et dans un autre terminal :
$ sudo tcpreplay -i dummy0 ssh.pcap
Mais aucun "packet received" ne s'affiche. Damned ! En inspectant un
peu le code, on voit ça :
if (-1 == setsockopt(sock_fd, SOL_SOCKET, SO_ATTACH_FILTER, &bpf, sizeof bpf)) {
Ça a l'air bien comme ça, hein. Malheureusement, le 'struct bpf_program'
n'est pas compris sous linux, qui, ne voulant pas faire comme ses potes *BSD
attend un 'struct sock_fprog *' en avant dernier argument. Bon, ici je me dis
"il doit bien y avoir une fonction qui fait la conversion, cherchons dans le
source de libpcap". En jetant un coup d'oeil rapide, on tombe sur
ça :
libpcap-0.9.8/pcap-linux.c:215 static int fix_program(pcap_t *handle, struct sock_fprog *fcode);
Je suis content, mais visiblement je dois passer par un pcap_t. Du coup, je
reprends le code en l'adaptant pour taper directement dans la structure interne
du handler pcap, et j'écris la fonction suivante :
#define SLL_HDR_LEN 16
static int lcc = 0; // linux cooked capture
static int
fix_offset(struct bpf_insn *p)
{
if (p->k >= SLL_HDR_LEN) {
p->k -= SLL_HDR_LEN;
} else if (p->k == 14) {
p->k = SKF_AD_OFF + SKF_AD_PROTOCOL;
} else {
return -1;
}
return 0;
}
static int
fix_code(struct bpf_program *bpf, struct sock_fprog *fcode)
{
size_t prog_size;
register int i;
register struct bpf_insn *p;
struct bpf_insn *f;
int len;
len = bpf->bf_len;
prog_size = sizeof(bpf->bf_insns) * len;
f = malloc(prog_size);
if (f == NULL) {
printf("malloc: %s\n", strerror(errno));
return -1;
}
memcpy(f, bpf->bf_insns, prog_size);
fcode->len = len;
fcode->filter = (struct sock_filter *)f;
for (i = 0; i < len; ++i) {
p = &f[i];
switch (BPF_CLASS(p->code)) {
case BPF_RET:
if (BPF_MODE(p->code) == BPF_K) {
if (p->k != 0)
p->k = 65535;
}
break;
case BPF_LD:
case BPF_LDX:
switch (BPF_MODE(p->code)) {
case BPF_ABS:
case BPF_IND:
case BPF_MSH:
if (lcc) {
if (fix_offset(p) < 0) {
return 0;
}
}
break;
}
break;
}
}
return 1; /* success! */
}
Maintenant je réécris ma fonction iface_setfilter() pour convertir le code
BPF :
static int
iface_setfilter(int sock_fd, const char * const device, const char * const filter)
{
if (! filter || ! *filter) {
printf("[%s] no filter to install\n", device);
return 0;
}
struct bpf_program bpf;
memset(&bpf, 0, sizeof bpf);
if (-1 == pcap_compile_nopcap(FRAME_SIZE, DLT_RAW, &bpf, filter, 1, 0)) {
printf("[%s] pcap_compile_nopcap failed for '%s'\n", device, filter);
return -1;
}
struct sock_fprog fcode;
memset(&fcode, 0, sizeof fcode);
int ret = fix_code(&bpf, &fcode);
if (1 != ret) {
printf("[%s] fix_code failed (rcode = %d) for filter '%s'\n", device, ret, filter);
return -1;
} else {
printf("[%s] fix_code worked (rcode = %d) for filter '%s'\n", device, ret, filter);
}
if (-1 == setsockopt(sock_fd, SOL_SOCKET, SO_ATTACH_FILTER, &fcode, sizeof fcode)) {
printf("[%s] setsockopt: %s (filter '%s')\n", device, strerror(errno), filter);
return -1;
}
printf("[%s] filter '%s' successfully installed\n", device, filter);
return 0;
}
Là, logiquement je me dis "Youpi les knakis¸ ça va marcher !". Mais si je
reteste, toujours rien. Rien ne s'affiche. La blague est même que si
j'invoque :
$ sudo ./cap "not port 80"
... et que je joue du traffic http (sur le port 80 bien sûr), mon outil
logue qu'il a vu un paquet ! Par contre avec "port 80" il n'affiche rien.
Bon je me suis pas mal gratté la tête ici, j'avoue. Du coup j'appelle mon
copain strace à la rescousse, et je compare le raw des filtres passés à
setsockopt() entre mon code et l'appel tcpdump :
$ sudo strace -s 256 -f -v ./cap "port 80" 2>&1 | grep ATTACH_FILTER setsockopt(3, SOL_SOCKET, SO_ATTACH_FILTER, "\33\0\0\0\0\0\0\0\20\240\363\0\0\0\0\0", 16) = 0 ^C $ sudo strace -s 256 -f -v tcpdump -ni dummy0 port 80 2>&1 | grep ATTACH_FILTER setsockopt(3, SOL_SOCKET, SO_ATTACH_FILTER, "\1\0\0\0\0\0\0\0h\303\315E(\177\0\0", 16) = 0 setsockopt(3, SOL_SOCKET, SO_ATTACH_FILTER, "\30\0\0\0\0\0\0\0\360V1G(\177\0\0", 16) = 0 ^C
Les outputs ne sont pas les mêmes. La génération du filtre est donc
foireuse, je vérifie maintenant comme suit :
$ sudo tcpdump -nd port 80 (000) ldh [12] (001) jeq #0x86dd jt 2 jf 10 (002) ldb [20] (003) jeq #0x84 jt 6 jf 4 (004) jeq #0x6 jt 6 jf 5 (005) jeq #0x11 jt 6 jf 23 (006) ldh [54] (007) jeq #0x50 jt 22 jf 8 (008) ldh [56] (009) jeq #0x50 jt 22 jf 23 (010) jeq #0x800 jt 11 jf 23 (011) ldb [23] (012) jeq #0x84 jt 15 jf 13 (013) jeq #0x6 jt 15 jf 14 (014) jeq #0x11 jt 15 jf 23 (015) ldh [20] (016) jset #0x1fff jt 23 jf 17 (017) ldxb 4*([14]&0xf) (018) ldh [x + 14] (019) jeq #0x50 jt 22 jf 20 (020) ldh [x + 16] (021) jeq #0x50 jt 22 jf 23 (022) ret #96 (023) ret #0
Et j'invoque
if (-1 == pcap_compile_nopcap(FRAME_SIZE, DLT_RAW, &bpf, filter, 1, 0)) {
printf("[%s] pcap_compile_nopcap failed for '%s'\n", device, filter);
return -1;
}
bpf_dump(&bpf, 0);
J'ai en sortie :
Initializing interface dummy0 (filter 'port 80') [dummy0] enter in promiscuous mode [dummy0] bind succeed: index 1634 <--> dummy0 (000) ldb [0] (001) and #0xf0 (002) jeq #0x60 jt 3 jf 11 (003) ldb [6] (004) jeq #0x84 jt 7 jf 5 (005) jeq #0x6 jt 7 jf 6 (006) jeq #0x11 jt 7 jf 26 (007) ldh [40] (008) jeq #0x50 jt 25 jf 9 (009) ldh [42] (010) jeq #0x50 jt 25 jf 26 (011) ldb [0] (012) and #0xf0 (013) jeq #0x40 jt 14 jf 26 (014) ldb [9] (015) jeq #0x84 jt 18 jf 16 (016) jeq #0x6 jt 18 jf 17 (017) jeq #0x11 jt 18 jf 26 (018) ldh [6] (019) jset #0x1fff jt 26 jf 20 (020) ldxb 4*([0]&0xf) (021) ldh [x + 0] (022) jeq #0x50 jt 25 jf 23 (023) ldh [x + 2] (024) jeq #0x50 jt 25 jf 26 (025) ret #65536 (026) ret #0 [dummy0] fix_code worked (rcode = 1) for filter 'port 80' [dummy0] filter 'port 80' successfully installed ^C
On voit bien que c'est différent au début. Le reste est plutôt
cohérent
(016) jeq #0x6 jt 18 jf 17 # 0x06 c'est l'IPPROTO_TCP (6) (017) jeq #0x11 jt 18 jf 26 # 0x11 = 17 = IPPROTO_UDP
Si on n'est dans aucun des deux cas, on saute en 26 (jf 26), soit la fin.
Sinon, on regarde si le port vaut 80 (0x50) :
(022) jeq #0x50 jt 25 jf 23 (023) ldh [x + 2] (024) jeq #0x50 jt 25 jf 26
Le problème est vraiment le prologue. Et là je on me souffle à l'oreille que
c'est peut-être le datalink type. Réaction: "bon dieu de !#@@!#@!# mais c'est
bien sûr, ça doit être mon datalink (DLT) qui est moisi !" Si
j'écris :
if (-1 == pcap_compile_nopcap(FRAME_SIZE, DLT_IEEE802, &bpf, filter, 1, 0)) {
J'obtiens en sortie :
$ cc -o cap cap.c -lpcap && sudo ./cap "port 80" Initializing interface dummy0 (filter 'port 80') [dummy0] enter in promiscuous mode [dummy0] bind succeed: index 1634 <--> dummy0 (000) ldh [20] (001) jeq #0x86dd jt 2 jf 10 # 0x86dd est l'ethertype IPv6 (002) ldb [28] (003) jeq #0x84 jt 6 jf 4 (004) jeq #0x6 jt 6 jf 5 (005) jeq #0x11 jt 6 jf 23 (006) ldh [62] (007) jeq #0x50 jt 22 jf 8 (008) ldh [64] (009) jeq #0x50 jt 22 jf 23 (010) jeq #0x800 jt 11 jf 23 # 0x800 est l'ethertype IPv4 [...]
Mais toujours rien n'est logué si je joue du http ! En remplaçant
DLT_IEEE802 par DLT_EN10MB en revanche...
[...] [dummy0] enter in promiscuous mode [dummy0] bind succeed: index 1634 <--> dummy0 [dummy0] fix_code worked (rcode = 1) for filter 'port 80' [dummy0] filter 'port 80' successfully installed [1286457559,615193] packet received
Hallelujah ! Hosanna hosanna !
Enfin bon, c'est quand même moche d'écrire le DLT en dur dans le code, donc
je l'ai récupéré via la libpcap (mais on est obligé de passer par un handler
pcap_t *, ce que je ne voulais pas trop au début...)
char errbuf[256] = "";
pcap_t *p = pcap_open_live(device, FRAME_SIZE, 1, 0, errbuf);
if (! p) {
printf("[%s] pcap_open_live failed: %s\n", device, errbuf);
return -1;
}
int dlt = pcap_datalink(p);
pcap_close(p);
if (-1 == pcap_compile_nopcap(FRAME_SIZE, dlt, &bpf, filter, 1, 0)) {
printf("[%s] pcap_compile_nopcap failed for '%s'\n", device, filter);
return -1;
}
En fait, comme on dispose du handler pcap_t, on peut même dégager pcap_compile_nopcap() et utiliser pcap_compile(), qui lui n'a même pas besoin d'un DLT en paramètre... Tout ça parce que j'ai voulu me passer de ce foutu handler, en somme. Bref le code est disponible ici
mercredi 15 septembre 2010
Par eau le mercredi 15 septembre 2010, 10:36 - geeking
Pendant ma petite pause lecture du matin, je suis tombé sur ce post concernant les nouvelles updates de la GNU toolchain, et en particulier un nouvel attribut: "ifunc"
Ca permet de définir dynamiquement une fonction qui va "résoudre" vers la fonction de votre choix en fonction de critères que vous pouvez définir, le monsieur @ http://nickclifton.livejournal.com/6612.html donne un exemple très simple et très clair (plus clair que mes explications foireuses) que je reproduirais ici :
void *slow_memcpy (void *dst, const void *src, size_t len)
{
char *d = dst; char *s = src;
while (len--)
*d++ = *s++;
return dst;
}
void *fast_memcpy (void *dst, const void *src, size_t len)
{
__asm("foo %0 %1 %2" : "=m" (dst) : "m" (src), "r" (len) : memory);
return dst;
}
static void (* resolve_memcpy (void)) (void)
{
return __cpu_has_foo () ? fast_memcpy : slow_memcpy;
}
void *memcpy (void *, const void *, size_t) __attribute__ ((ifunc ("resolve_memcpy")));
Les details chez http://nickclifton.livejournal.com/6612.html
lundi 12 avril 2010
Par poz le lundi 12 avril 2010, 10:34 - geeking
Suite à la mise à disponibilité de RE2, je suis tombé sur un article de Russ Cox qui explique en quoi l'algorithme de matching de Ken Thompson (Thompson NFA, pour Non Deterministic Algorithm) poutrait grave sa mère pour la reconnaissance de certaines grammaires (face à PCRE ou Perl), avec moins de 500 lignes de C. C'est intéressant. On a même droit à une implémentation (assez basique) en C. Yummy.
o l'article
vendredi 6 novembre 2009
Par eau le vendredi 6 novembre 2009, 16:02 - geeking
Je rentre dans ma 65 eme annee et je continue encore d'apprendre de nouvelles choses.. Au cours d'une discussion avec un pote sur "l'intrawebz" (tm) j'ai appris l'existence des register_printf_functions.. comme decrit dans les liens suivants:
Et au passage qqqes docs sur les attributes GCC et des ptits examples:
Edit de poz:
mercredi 30 septembre 2009
Par poz le mercredi 30 septembre 2009, 08:38 - geeking
Je ne sais pas pour vous, mais le réseau, je trouve ça assez intéressant. Comment fonctionnent les protocoles, leurs implémentations, etc. Alors voici un petit lien, présentant une implémentation de TCP/IP très légère, mais assez intéressante d'un point de vue didactique. Il s'agit de lwIP (light-weight IP), une stack TCP/IP ne faisant pas de copie de buffer afin de ne pas perdre trop en performances (mais avec une abstraction manquante, car chaque layer peut taper dans la couche sous-jacente), et où les principaux comportements attendus sont implémentés : silly window avoidance, demultiplexage, contrôle de checksum, retransmission rapide, calcul de RTT, contrôle de congestion, etc. La pile propose même une API BSD compliant :) Bon, il s'agit d'un PoC d'universitaire, hein, c'est pas ça qui va remplacer les piles des OS, mais encore une fois, ça se comprend vite et bien.
Ah, oui, le code (C, oeuf corse) tient en moins de 2600 lignes, et le code objet produit pèse 13.5 KiB.
PS : Dernière chose, il n'y a pas de support IPv6. Haaan, la grosse honte.
mercredi 26 août 2009
Par mco le mercredi 26 août 2009, 12:06 - geeking
Ce billet:
Bref une bonne petite leçon d'analyse de code pour testage efficace.
mercredi 12 août 2009
Par poz le mercredi 12 août 2009, 23:40 - geeking
Bon ben je sais pas pour vous, mais j'ai toujours fait des trucs moches genre :
void
sighandler_foo(int nsig)
{
printf("Signal %d caught. Exiting.\n", nsig);
exit(EXIT_SUCCESS);
}
J'ai schématisé, mais l'idée est là. Bah en fait faut surtout pas écrire cette horreur. Là, normalement vous me pointez du doigt en riant très fort, et je deviens rouge de honte. Mais j'ai vaincu ma peur du ridicule, et je le clame : oui ! je suis une bille !
Sinon, pour ceux qui ne savent pas, en fait j'ai appris ça en lisant un post de Solar Designer sur nmap-dev, qui expliquait par le menu pourquoi c'est super crappy :
Après avoir vérifié, rien de tout ça n'est écrit dans signal(2) sur ma machine (Linux), mais c'est très clair dans le man OpenBSD, en revanche.
HTH.
samedi 30 mai 2009
Par eau le samedi 30 mai 2009, 13:37 - geeking
Je me balladais tranquille, en week end et je suis tombe sur le lien suivant:
moi>Intel AES instruction set support?! hu?! depuis quand?!?!
J'ai vite lu la doc et j'ai voulu voir si mon CPU tout recent supportais cette joyeusete, Intel file du code, mais ca compilait pas direct alors j'ai vite refait tout simple..:
#include <stdio.h>
#include <unistd.h>
int chk_cpu_aes_support() {
unsigned int rc;
asm ("mov $0x01, %%eax\n\t"
"cpuid\n\t"
"mov %%ecx, %0\n\t"
:"=r"(rc)
: /* no inputs */
:"%ecx", "%eax"
);
return (rc & 0x2000000);
}
/* ORIGINAL INTEL CODE.
int Check_CPU_support_AES() {
#if defined(__INTEL_COMPILER)
int CPUInfo[4] = { -1 };
__cpuid(CPUInfo, 1);
return (CPUInfo[2] & 0x2000000);
#else
unsigned int a=1,b,c,d;
__cpuid(1, a,b,c,d);
return (c & 0x2000000);
#endif
}
*/
int main(int argc, char ** argv)
{
fprintf(stdout, "%08x(%d)\n", chk_cpu_aes_support(), chk_cpu_aes_support());
return 0;
}
Et tristesse...:
$ ./intelaesdetect 00000000 (0)
si qqun a un resultat "positif" n'hesitez pas a _COMMENTER_ juste que je sache quel series est capable de faire ca..
vendredi 22 mai 2009
Par eau le vendredi 22 mai 2009, 11:31 - geeking
Non, non et non, pas findus, c'est un nouveau (en tout cas pour moi) concept introduit dans NetBSD qui permet d' "externaliser" en userspace des elements kernelspace de maniere (dixit) "simple", en gros RUMP (c'est son nom) vous permet de "runner" certains des call/fonctions/syscalls kernelspace depuis la librump plutot que d'appeler le kernel, ca semble necessiter de recoder le dit appel dans la librump, rump semble donne un access plus direct a certaines partie du kernel vous laissant la liberte de traiter la majorite du code de controle en userland, je vais faire joujou et lire le code pour "tenter" de comprendre le fonctionnement, mais c'est interessant, je me demande si ca sent pas l'envie de faire un microkernel a long terme ca...
« billets précédents - page 1 de 3