View Full Version : quali funzioni per accedere al datagramma ethernet in linux
BountyKiller
01-05-2003, 09:19
ciao, sto cercando dei link che descrivano le union e le struct che permettono di accedere al pacchetto ethernet...sto cercando da mezz'ora e non ho trovato nulla! :(
Prova a vedere qui dentro:
linux/if_ether.h
BountyKiller
01-05-2003, 17:10
si c'avevo già guardato....in effetti il mio problema è più che altro di "formattazione"...per esempio un indirizzo fisico ethernet ( 6 coppie di cifre esadecimali separate dai : ) lo vorrei stampare così e invece me lo dà in decimale....poi ho anche dei problemi a stampare ( nel senso di cout<< o printf ;) ) gli indirizzi ip quadripuntati..insomma mi incasino con htons inet_toa eccetera... se sapete dove trovare un buon tutorial sulla programmazione di rete oppure un bel sorgente da analizzare ( che per me è la cosa migliore.....)che faccia uso di ethhdr fatemelo sapere ;)...
ps: leggere gli header file non è proprio semplicissimo..... cosa vuol dire #endif ??? :confused:
E' una direttiva al compilatore :
Solitamente comincia così:
#ifndef PIPPO
...
#endif
Se non è definito PIPPO... Per gli include si fa sempre questa cosa:
#ifndef PIPPO_H
#define PIPPO_H
...
#endif
Serve per evitare di includere più volte gli stessi header...
BountyKiller
07-05-2003, 08:43
ho un'altra domanda: se accedo all'header di un pacchettto ip che funzioni devo usare per trasformare l'indirizzo ip ( 32 bit) nella notazione quadripuntata che tutti conosciamo?? (accedo ai cambi s_addr[32] e d_addr[32] tramite un puntatore alla struct iphdr)...sono giorni che cerco questa funzione ma non l'ho trovata...
Io su Win uso inet_ntoa...dovrebbe essere la stessa...
BountyKiller
07-05-2003, 19:16
si ma probabilmente la usi su un puntatore dereferenziato alla struct sockaddr_in..ora sono su win e il sorgente ce l'ho in una partizione linux...inet_ntoa non può essere applicata direttamente ai campi indirizzi dell'header ip.....sto impazzendo...oltretutto non sono ancora riuscito a trovare la funzione che trasforma l'indirizzo mac decimale nella notazione normale....mi ci vorrebbe una enciclopedia con tutte le funzioni del c++ :( :(
Ah...ma te vuoi il dotted decimale dell'indirizzo MAC ?
BountyKiller
08-05-2003, 16:22
no voglio la versione esadecimale saperata da :
per esempio 00:00:e3:99:f4:00
Non te la puoi calcolare da solo ? E' banale ;)
BountyKiller
09-05-2003, 07:50
mmmm...si tratterebbe di prendere 8 bit per volta (= due cifre esadecimali) e stampare un : tra ogni coppia....come faccio però a prendere 8 bit per volta da un numero di 48 bit ?( castarli in hex è facile)...
sto pensando che si potrebbe ottenere questa informazione ( x l'host, non per chi si collega) anche interrogando il dirver della scheda di rete...il guaio è che non ho la minima idea di come si faccia...
Dimmi come sono memorizzati...sia il MAC che l'ip (soprattutto il tipo mi interessa)...
BountyKiller
09-05-2003, 16:03
ho risolto il discorso MAC, avevi ragione, :p si fa prima a farlo che a dirlo...nell'header ethernet gli indirizzi mac di origine e destinazione sono array di 6 elementi di tipo char... nel c standard manca il tipo stringa ma cout e cin possono essere usati per l'input e l'output si array di char ( e solo di char, ovviamente ;) ) quindi pesavo che bastasse una normale cout...ho risolto in modo piuttosto semplice: con un ciclo for prendo ciascuno dei 6 elementi , lo casto in un int e poi gli dico di sputarlo fuori in esadecimale e se l'elemento non è il sesto di affiancare i:...perfetto...
eccoti il codice:
for (int i = 0; i<6 ; i++)
{
cout<<hex<<int(ethernet_datagram->h_dest[i]);
if (i!=5) cout<<":";
}
cout<<endl;
hex lo usi includendo iomanip.h...
per l'indirizzo ip la vedo dura....perchè nell'header IP è un u_int32_t :confused: :confused: probabilmente un unsigned int che i programmatori di ip.h hanno definito da qualche altra parte...inet_ntoa forse va bene però il vi mi dice che non riesce a castare un u_int32_t in un tipo non scalare ( =l'indirizzo ip nella notazione classica):
suggerimenti? ;)
Si faceva bene anche con il C...
char tmp[18];
sprintf(tmp,"%x:%x:%x:%x:%x:%x", e->h_dest[0], e->h_dest[1], ....);
Visto che in_addr è così:
struct in_addr {
union {
struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b;
struct { u_short s_w1,s_w2; } S_un_w;
u_long S_addr;
} S_un;
};
...prova così:
in_addr addr;
addr.S_un.S_addr = (u_long)il_tuo_u_int32_t;
inet_ntoa(addr);
Prova così... Se ti viene visualizzato al contrario dimmile che bisogna convertirlo...
Altrimenti si ricorre al trucco:
unsigned char *ip = (unsigned char *)&il_tuo_u_int32_t;
Dopo accedendo da ip[0] a ip[4] hai le varie parti dell'ip...
BountyKiller
09-05-2003, 19:03
nell'ultimo pezzo di codice che significato ha & ? :confused:
grazie cmq :p domani provo..
forse non è cmq complicato, per esempio basterebbe prendere 8 bit alla volta dei 32 dell'indirizzo ip e castarli a int uno per uno...
Originally posted by "BountyKiller"
nell'ultimo pezzo di codice che significato ha & ? :confused:
L'indirizzo della variabile... Gli faccio un cast ad un puntatore a char e poi mi guardo un byte alla volta...
Originally posted by "BountyKiller"
forse non è cmq complicato, per esempio basterebbe prendere 8 bit alla volta dei 32 dell'indirizzo ip e castarli a in uno per uno...
Certo... Puoi semplicemente fare un AND con le varie maschere e con degli shift riportare i vari byte nella posizione meno significativa...
BountyKiller
10-05-2003, 08:35
scusa domanda scema....è ovvio che è l'operatore address of ....sarà il caldo :cool: ....cmq con i due esempi che mi hai proposto ho dei problemi...il primo mi dice che S_un non è un campo della struct in_addr ( e c'ha ragione..) nel secondo mi dice che è illegale il casting .. :confused: quasi proverei con la mascheratura..un po' rozzo ma semplice...non c'è bisogno di convertire in binario giusto? ( i numeri sono numeri cmq li rappresenti)...piuttosto per fare l'and bit a bit ? non l'ho mai fatto...
BountyKiller
10-05-2003, 11:49
ho risolto come dicevo io...è incredibile come certe volte uno perde tempo a pensare a cose complicate e invece basta scrivere due righe di codice e risolvi il problema in cinque minuti...;)
eccoti la funzione con un main di prova:
//funzione che riceve in input il campo indirizzo ( sorgente e/o destinazione) dell'header IP
#include <iostream.h>
#include <iomanip.h>
void StampaIP(unsigned int indirizzo)
{
unsigned int maschera1=0x000000FF;
unsigned int maschera2=0x0000FF00;
unsigned int maschera3=0x00FF0000;
unsigned int maschera4=0xFF000000;
unsigned int ris1 = indirizzo & maschera1;
unsigned int ris2 = indirizzo & maschera2;
unsigned int ris3 = indirizzo & maschera3;
unsigned int ris4 = indirizzo & maschera4;
ris2 >>= 8;
ris3 >>= 16;
ris4 >>= 24;
cout<<ris4<<"."<<ris3<<"."<<ris2<<"."<<ris1<<endl;
}
void main()
{
unsigned int indirizzo;
cout<<"inserire un numero di 8 cifre esadecimali:"<<endl;
cin>>hex>>indirizzo;
cout<<"l'indirizzo IP e': ";
StampaIP(indirizzo);
}
l'ho provato adesso ed è ok: se indirizzo è effettivemente saddr o daddr va passato in host to network long, non so se è linux (mandrake9.1) che lo vuole così o la cpu del mio portatile ( pentium3 m) o tutti e due....pensandoci bene non è necessaria la mascheratura, basta fare 4 shift e dopo ciascuno shift assegnare i vari pezzi dell'indirizzo IP.
ora grazie alla mia funzione posso levarmi dalle palle la structsockaddr_in e usare solo i campi sadddr e daddr dell'header ip il che mi sembra più chiaro e pulito ...se ci sono altri problemi mi rifaccio vivo in questo thread, per intanto ti saluto e ti ringrazio (mi sembri un programmatore professionista..sbaglio? :))
ciao!!
BK
ps: il programma che sto scrivendo è uno sniffer per rete locale..
BountyKiller
13-05-2003, 12:01
ho un altra domanda> lo sniffer inizialmente chiede quanti pacchetti sniffare e per interromperlo prima che abbia finito devo schiacciare ctrl + c io vorrei che controllasse se, mentre sniffa, l utente ha premuto il tasto ESC, e se si si interrompe e fa vedere quello che ha sniffato...come faccio a fare un monitoraggio del tasto ESC?
BountyKiller
13-05-2003, 17:15
cionci ci sei?? ( ma perchè con konqueror non posso usare le emotincohns????? )
Probabilmente sono problemi con JavaScript...
In molti compilatori esiste la funzione kbhit() che ritorna vero se è stato premuto un tasto, ma non lo legge dallo stdin...
Sinceramente il problema dai tempi in cui non uso più quei compilatori non me lo sono più posto...ora mi informo...
ilsensine
15-05-2003, 10:57
Su linux non esiste kbhit() e altre funzioni di librerie quali la conio. Si possono creare delle funzioni di "emulazione":
Innanzitutto occorre settare stdin come char-buffered (normalmente è line-buffered, ovvero l'input è disponibile solo alla pressione di <invio>):
#include <stdio.h>
#include <unistd.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <ctype.h>
void init_stdin() {
struct termios tty;
int idev = fileno(stdin);
tcgetattr(idev, &tty);
tty.c_lflag &= ~ICANON;
tty.c_lflag &= ~ECHO;
tty.c_cc[VMIN] = 1;
tty.c_cc[VTIME] = 0;
tcsetattr(idev, TCSAFLUSH, &tty);
}
Quindi, per vedere se un tasto è stato premuto, si può chiamare questa funzione:
int key_pressed() {
int cnt;
ioctl(fileno(stdin), FIONREAD, &cnt);
return cnt>0 ? 1 : 0;
}
Infine, possiamo creare l'equivalente per getch(); la propongo in due formati, la prima _bloccante_ e la seconda _non bloccante_ (restituisce -1 se non sono stati premuti tasti);
int do_getch() {
char ch;
read(fileno(stdin), &ch, 1);
return ch;
}
int do_getch_nonblock() {
/* In alternativa si può settare stdin come O_NONBLOCK */
return key_pressed() ? do_getch() : -1;
}
ilsensine
15-05-2003, 11:13
è un "casino" solo la prima funzione (black magic con termios); le altre sono ovvie ;)
BountyKiller
15-05-2003, 22:03
azz ma sei un linux kernel developer??? :eek:
bhè...che dire....provo e vi so dire...porca miseria l'equivalente getch non bloccante mi sarebbe venuta bene per un lavoretto che avevo fatto un po' di mesi fa...erano dei client per la chat....usavo una funzione bloccante per l'input cosicchè finchè non avevi premuto un tasto il client non faceva vedere i messaggi degli altri client...l'avevo risolto lo stesso ma in modo un po' macchinoso...
In alternativa puoi fare due thread... Uno che si occupa dell'input ed un'altro dell'ouput...
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.