J'ai besoin de stocker les paquets que composent une communications dans un programme C.
Comme j'ai beaucoup de communications, j'ai commencé par faire un B-Tree dans lequel chaque valeur (associée à une clé) est un GArray qui contient les paquets de la communication.
Le soucis, c'est que ça bug... les 2 premiers paquets de chaque com. sont bien enregistrés et repris, mais pour les suivants j'ai des résultats bizarres...
voilà mon code :
/*!******************************
* *
* search the entry *
* *
* ******************************/
if (
TRUE != g_tree_lookup_extended(Storing_B_Tree, key_one->str, NULL, NULL)
&&
TRUE != g_tree_lookup_extended(Storing_B_Tree, key_two->str, NULL, NULL)
)
{
/*! if doesn't exist, create it and init the GArray
* as a value for this entry
*/
GArray *value;
/*! Creates a new GArray as a B-Tree value to store the packets of this connection
*/
value = g_array_new(FALSE, FALSE, 1500);
g_array_append_val(value, m->payload);
/*! add it to the tree, value contain the address of the pointer to the array in the memory
*/
g_tree_insert(Storing_B_Tree, key_one->str, value);
g_print("STORING FUNCTION : entry created and packet %s stored in memory\n",key_one->str);
}
else {
/*! the tuple exist in the B-Tree, so add the packet at the end of the
* existing GArray table
*/
GString *key;
key = key_one;
GArray *P_to_Array;
/*! get @ of the array in memory */
if (TRUE != g_tree_lookup_extended(Storing_B_Tree, key_one->str, NULL, (gpointer *) &P_to_Array))
{
/*! if key_one is not the good key, try with key_two */
g_tree_lookup_extended(Storing_B_Tree, key_two->str, NULL,(gpointer *) &P_to_Array);
key = key_two;
}
/*! store the value at the end of the GArray table
*/
g_array_append_val(P_to_Array, m->payload);
g_print("STORING FUNCTION : %dst packet of %s stored in memory\n",P_to_Array->len, key->str);
/*! TEST PURPOSE
*
* print all the entries from the corresponding array
*/
int i;
for (i=0; i < P_to_Array->len; i++)
{
struct iphdr *iph2;
iph2 = & g_array_index(P_to_Array, struct iphdr *, i);
g_print("IP table: %s; length : %u\n",(char *) inet_ntoa(iph2->saddr), ntohs(iph2->tot_len));
}
}
et voila ce que donne une exécution, les 2 premières IP sont bien reprises mais les suivantes ne sont pas bonnes
dans le second paquet, la "length" est également fausse...
STORING FUNCTION : 4st packet of 128.8.37.122:56107:130.92.6.40:80 stored in memory
IP table: 128.8.37.122; length : 52
IP table: 130.92.6.40; length : 16384
IP table: 219.43.0.80; length : 52160
IP table: 15.53.67.83; length : 9594
Alors j'essaie de comprendre pourquoi je ne récupère pas bien mes paquets.... Il me semble que GArray attribue un nouvel index pour chaque entrée, je ne devrais donc pas dépasser sur les autres index lorsque je récupère mon entrée...
# g_array_index
Posté par ecyrbe . Évalué à 2.
si c'est un tableau de iphdr tu dois faire ça :
struct iphdr *iph2;
iph2 = & g_array_index(P_to_Array, struct iphdr, i);
si c'est un tableau de iphdr* tu dois faire ça :
struct iphdr *iph2;
iph2 = g_array_index(P_to_Array, struct iphdr*, i);
voilà...
[^] # Re: g_array_index
Posté par jve (site web personnel) . Évalué à 1.
[^] # Re: g_array_index
Posté par ecyrbe . Évalué à 2.
Peux tu donner plus d'infos sur la structure de ta variable m?
[^] # Re: g_array_index
Posté par jve (site web personnel) . Évalué à 1.
iph2 = g_array_index(P_to_Array, struct iphdr*, i);
quand j'utilise :
iph2 = & g_array_index(P_to_Array, struct iphdr *, i);
j'obtiens les résultats erratiques dont je parlais dans mon premier post
la structure "m" est de type ipq_packet_msg_t, elle contient un paquet ramené dans un hook IPQ par netfilter
de fait, "m->payload" contient le paquet raw, le reste de la structure c'est des metadonnées IPQ qui ne m'interesse pas
le GArray semble être fonctionnel car lorsque j'accède à "P_to_Array->len" il me retourne bien le nombre de cases que contient le tableau, et ce dans tous les cas
de fait, je pense que mon problème vient soit de l'ajout dans le tableau, soit dans la définition du tableau avec
value = g_array_new(FALSE, FALSE, 1500);
ou 1500 est censé être la taille en bytes de chaque case
[^] # Re: g_array_index
Posté par ecyrbe . Évalué à 2.
struct iphdr *iph2;
iph2 = & g_array_index(P_to_Array, struct iphdr, i);
je pense que c'est ce cas là qui devrait marcher... et je vais t'expliquer pourquoi...
g_array_index est défini par :
#define g_array_index(a,t,i) (((t*) (a)->data) [(i)])
remarque ce qu'il fait... il cast a->data en t* !!!!
Or, toi tu lui dis de faire un cast en struct iphdr **, ce qui est faux je pense. Si j'ai raison, ça ne devrait marcher que pour le premier index, pour les autres ça devrait induire un décalage des données.
Or chez toi tu obtiens le bon résultat pour le premier index, pas pour les autres. Ce qui semble comfirmer mon hypothèse.
Essaie donc et dis moi si ça corrige quelquechose...
[^] # Re: g_array_index
Posté par jve (site web personnel) . Évalué à 1.
REDIRECTION CHECK : Conn ID 128.8.37.122:13666:128.8.37.121:22 or 128.8.37.121:22:128.8.37.122:13666 is not redirected
NETFILTER_CONNTRACK : Connection check called for 128.8.37.122:13666:128.8.37.121:22 state = activ
PCAP_TOOL : Current packet writed to output pcap file
STORING FUNCTION : 163st packet of 128.8.37.122:13666:128.8.37.121:22 stored in memory
IP table: 128.8.37.122; length : 60
IP table: 160.2.22.208; length : 22
IP table: 0.0.0.0; length : 1460
IP table: 1.0.0.0; length : 0
IP table: 184.22.220.191; length : 61879
IP table: 3.0.0.0; length : 0
IP table: 12.0.0.0; length : 56511
IP table: 232.114.218.183; length : 56511
IP table: 1.0.0.0; length : 65463
IP table: 0.0.0.0; length : 0
Dans la doc de GLib, ils disent de ne pas mettre struct devant :
EDayViewEvent *event;
/* This gets a pointer to the 3rd element in the array of EDayViewEvent
structs. */
event = &g_array_index (events, EDayViewEvent, 3);
mais quand je fais ca
iph2 = & g_array_index(P_to_Array, iphdr, i);
il me dit que iphdr est une variable non déclarée....
# Question:
Posté par liberforce (site web personnel) . Évalué à 2.
[^] # Re: Question:
Posté par liberforce (site web personnel) . Évalué à 2.
[^] # Re: Question:
Posté par jve (site web personnel) . Évalué à 1.
un paquet va être un TCP/SYN, donc tout petit, le suivant va être un PUSH/ACK de 1200 octets.... bref, pas de taille fixe
De fait, j'espérais que GArray s'occuperait de l'indexation proprement, mais on dirait que ce n'est pas le cas. De fait, je vois pas trop de solutions pour stocker mon bazard... si vous avez une idée ...
[^] # Re: C'est simple:
Posté par liberforce (site web personnel) . Évalué à 2.
Conclusion: si tu veux pouvoir accéder à tes données sans risquer d'aller lire en dehors des limites du buffer où elles se trouvent, tu dois utiliser une structure qui contient:
- la taille de ton buffer
- un pointeur vers ton buffer de données
Tu peux le faire à la main, c'est simple, mais si tu n'as pas envie de te prendre la tête, tu utilise une GString, qui le fait à ta place . Si tu la crées avec g_string_new_len, tu peux spécifier la taille de tes données, et dans ce cas là, la chaine à copier est autorisée à contenir des caractères '\0'. Ton code ressemblera alors à :
value = g_string_new_len(m->payload, m->data_len);
g_tree_insert(Storing_B_Tree, key_one->str, value);
Tu accèdes ensuite à ton buffer avec value->str et tu en connais la taille grâce à value->len. Avec ça tu ne consommes juste ce qu'il faut de mémoire, pas plus, et connais toujours la longueur de tes données.
[^] # Re: C'est simple:
Posté par jve (site web personnel) . Évalué à 1.
le soucis, c'est que je n'ai pas qu'un seul élément à stocker dans la valeur de mon B-Tree, mais bien une liste d'élément
je vais me faire une structure du type :
- taille du buffer
- pointeur vers le buffer
- pointeur vers le buffer suivant
à moins que GLib ais un type pour créer des listes chaînées directement ?
[^] # Re: C'est simple:
Posté par liberforce (site web personnel) . Évalué à 2.
Mais qu'est ce que tu essaie de faire au juste ?
[^] # Re: C'est simple:
Posté par jve (site web personnel) . Évalué à 1.
donc pour chaque connexion réseau, je crée une entrée dans le B-Tree. La clé de cette entrée est le tuple Source IP + Source Port + Dest IP + Dest Port.
maintenant, il faut également que je conserve TOUS les paquets de chaque connection, et je veux pouvoir retrouver facilement les paquets d'une connections spécifique
donc, je pensais lier un tableau, ou une liste chaînées, a la valeur de mon entrée dans le B-Tree
ca donne un truc comme ca :
http://jvehent.free.fr/ressources/connerie/Store-connections(...)
De fait, j'ai modifié mon code pour utiliser une GSList mais ca marche pas encore... j'insére et je récupère bien mon pointeur mais j'ai l'impression que les données ne sont plus en mémoire....
[^] # Re: C'est simple:
Posté par liberforce (site web personnel) . Évalué à 2.
http://developer.gnome.org/doc/API/2.0/glib/glib-Hash-Tables(...)
Si l'ordre d'arrivée des paquets est important, tu peux même utiliser les files.
http://developer.gnome.org/doc/API/2.0/glib/glib-Double-ende(...)
L'avantage est que tu peux rajouter un élément à la fin en temps constant. Tu n'as pas besoin de parcourir la liste entière pour rajouter cet élément à la fin. En tout cas vu ce que tu veux faire, c'est la solution que j'adopterais, à moins qu'il n'y ait une bonne raison (que je ne vois pas) pour utiliser un B-tree...
[^] # Re: C'est simple:
Posté par liberforce (site web personnel) . Évalué à 2.
Reposte ton code quand tu auras quelque chose, je te filerai un coup de main.
[^] # Re: C'est simple:
Posté par jve (site web personnel) . Évalué à 1.
et c'était bien la que se trouvais le problème, car je stockais mal l'adresse de mon payload dans ma liste...
maintenant je fait ca :
New_List = g_slist_append(New_List, & m->payload);
et je récup avec ca
struct iphdr *iptest = (struct iphdr *) g_slist_nth_data(P_to_List, index);
et, forcément, ca marche !!!!
Pour ce qui est du design, j'ai choisi les B-Tree car je lit plus que je n'écris, de fait je gagne un peu en rapidité... menfin, B-Tree ou Hash Table, le résultat est le meme : c'est juste un point d'accès pour ma liste chaînée
Merci pour le coup de main, ca m'a bien aidé ! De toute façon, vous risquez de me revoir poster pendant l'été ;)
[^] # Re: Question:
Posté par liberforce (site web personnel) . Évalué à 2.
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.