programmazione di rete in c - webalice.it · 2 dario maggiorini (dario@dico.unimi.it) -...
Post on 15-Feb-2019
218 Views
Preview:
TRANSCRIPT
1
Dario Maggiorinidario@dico.unimi.it
Università degli Studi di MilanoDipartimento di Informatica e Comunicazione
Programmazione di rete in C
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/20032
Obiettivi
Imparare a programmare con le socket Progettare un protocollo applicativoImplementare un sistema client-server
2
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/20033
Prerequisiti
Saper usare un editorSaper usare un compilatoreSaper usare un sistema unix (linux/BSD)Rudimenti di programmazione in C
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/20034
Contenuti
Il modello client-serverI protocolli di comunicazioneLe socket
DominioNamingProtocolli
Programmare client e server con TCPProgrammare client e server con UDP
3
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/20035
Testi consigliati
James F. Kurose Computer Networking: A Top-Down Approach Featuring the InternetAddison Wesley
W. Richard StevensUNIX Network ProgrammingPrentice Hall
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/20036
Il modello client-server
Presuppone l’esistenza di due entitàCLIENTrichiede un servizioSERVEReroga un servizio
CLIENT SERVER
Data flow
4
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/20037
Sono sistemi client-server
voi ed uno sportello bancomat una classe ed il docentevoi e la vostra bancalo sportello bancomat al primo punto ed il vostro istituto di credito
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/20038
Server iterativo
CLIENT SERVER
Coda d’attesa
5
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/20039
Server concorrente
Client 1
Client 2
SERVER
Client 4
Client 3
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200310
Server multiprocesso
Client 1 Client 2
SERVER
Client 4Client 3
Server 1 Server 2 Server 4Server 3
6
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200311
Servizi “a più stadi”
Client SERVER SERVER
Client o Server ?
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200312
Protocollo
1. l’insieme delle norme che regolano lo svolgimento di manifestazioni, visite, ricevimenti ufficiali
2. insieme di regole che governano la successione e lo scambio di informazioni fra due dispositivi comunicanti tra loro
dizionario garzanti
7
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200313
Progettazione di un protocollo
Quando si progetta un protocollo si deve stabilire:
Il formato dei messaggiQuali sono le sequenze di messaggi valideQuando inviare e quando ricevere
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200314
Protocolli applicativiDobbiamo definire dei protocolli per far scambiare
informazioni tra applicazioni
I messaggi sono sequenze di byte il cui formato viene stabilito a priori.I programmi dovranno riconoscere e “reagire” a sequenze di messaggi valide
Tutte le considerazioni viste prima sono ancora valide
Le socket ci forniranno solo l’infrastruttura per lo scambio dei messaggi
8
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200315
Socket
È il punto terminale di un sistema di comunicazione
Due processi distinti possono creare una socket ognuno e connetterle tra loro
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200316
Network protocols
Network interface drivers
hardware
Le socket nel S.O.Application
Kernel interface
socket
Network protocols
Network interface drivers
hardware
9
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200317
E a livello di linguaggio ?
Per il S.O. Una socket è un canale di I/O
In C sarà un file descriptor
In un linguaggio a oggetti un file descriptor con una serie di metodi “attorno”
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200318
Indirizzamento
Abbiamo bisogno di identificare in maniera univoca una socket, in modo tale da poterla raggiungere da un altro punto della rete
Problema:
Tecnologie diverse hanno formalismi diversi per i formati degli indirizzi
10
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200319
Università di Milano, D.I.Co.Via Comelico 3920135 MilanoItaly
University of California, C.S. Dept420 Westwood plazaLos Angeles, CA, 90095U.S.A.
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200320
Soluzione: definizione del dominio
“Informiamo” la socket di quale formalismo intendiamo usare
Equivale a dire al postino la cultura di riferimento in cui è stato scritto l’indirizzo
Il dominio di una socket stabilisce vincoli al suo utilizzo, in quanto la correla al sistema di indirizzamento sottostante
11
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200321
Possibili domini
ATMAppletalkDECNetInternetInternet6
IPXIRDANETBIOSUNIXSNA
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200322
Altro problema: “a chi ?”
Gli indirizzi a livello di rete non bastano:identificano un host, non una entità al suo interno
Dobbiamo usare indirizzi di livello trasporto
12
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200323
Indirizzi transport
Un indirizzo a livello di trasporto unisce all’indirizzo di livello rete un identificativo per indirizzare un’entità all’interno dell’host
Nel caso di TCP/IP vengono ottenuti concatenando l’indirizzo IP con un numero di 16 bit che prende il nome di porta
Alcuni servizi tipici di Internet vengono forniti usando porte standardizzate
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200324
Porte standard
22ssh
23telnet
21ftp
80WWW
25mail
PortaServizio
13
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200325
Naming / Binding
È l’operazione in cui associamo un indirizzo transport ad una socket già creata
In questo modo l’indirizzo diventa noto al sistema operativo ed altre socket sono in grado di stabilire una connessione
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200326
Semantica di comunicazione
È possibile impostare il protocollo a livello rete che verràutilizzato per il trasferimento dei dati
Nel caso delle socket abbiamo due opzioni:
byte-streamI dati vengono trasferiti come una sequenza ordinata ed affidabile di
byte
datagramI dati vengono inviati come messaggi indipendenti ed inaffidabili
14
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200327
Implementazione di un client
Dobbiamo andare a costruire un programma in C che richiede un servizio
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200328
creazione socket
connessione
scambio dati
chiusura canale
15
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200329
socket()
connect()
read()/write()
close()
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200330
socket()
#include <sys/socket.h>
int s;
s = socket (domain, type, protocol)
AF_UNIXAF_INETAF_NS
SOCK_DGRAMSOCK_STREAMSOCK_RAWSOCK_SEQPACKET
“/etc/protocols”
16
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200331
socket()
int s;s = socket(AF_INET, SOCK_STREAM, 0);if ( s < 0 ) {
perror("socket() ");exit(1);
}
?
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200332
## Internet protocols## $FreeBSD: src/etc/protocols,v 1.13.2.1 2000/09/24 11:26:39 asmodai Exp $# from: @(#)protocols 5.1 (Berkeley) 4/17/89## See also http://www.isi.edu/in-notes/iana/assignments/protocol-numbers#ip 0 IP # internet protocol, pseudo protocol numbericmp 1 ICMP # internet control message protocoligmp 2 IGMP # internet group management protocolggp 3 GGP # gateway-gateway protocolipencap 4 IP-ENCAP # IP encapsulated in IP (officially ``IP'')st2 5 ST2 # ST2 datagram mode (RFC 1819)tcp 6 TCP # transmission control protocolcbt 7 CBT # CBT, Tony Ballardie <A.Ballardie@cs.ucl.ac.uk>egp 8 EGP # exterior gateway protocolnvp 11 NVP-II # Network Voice Protocolpup 12 PUP # PARC universal packet protocolargus 13 ARGUS # ARGUSemcon 14 EMCON # EMCONxnet 15 XNET # Cross Net Debuggerchaos 16 CHAOS # Chaosudp 17 UDP # user datagram protocol...
17
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200333
getprotobyname()
#include <sys/socket.h>
struct protoent *p;p = getprotobyname (“name”)
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200334
int s, protocol_number;struct protoent *protocol_entry;
protocol_entry = getprotobyname("tcp");If ( protocol_entry == NULL ) {
perror("getprotobyname() ");exit(1);
}
protocol_number = protocol_entry -> p_proto;
s = socket(AF_INET, SOCK_STREAM, protocol_number);if ( s < 0 ) {
perror("socket() ");exit(2);
}
18
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200335
connect()
#include <sys/socket.h>
int error;
error = connect(socket, addr, len);
socket()
struct sockaddr_instruct sockaddr_un sizeof(addr)
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200336
struct sockaddr_un
sun_familyDominio
sun_pathLocazione della socket nel file system
19
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200337
struct sockaddr_in
sin_familyDominiosin_portPorta (16 bit indirizzo transport)sin_addrIndirizzo IP
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200338
hton / ntoh
Host -> network Short (16 bit) htons(int)Long (32 bit) htonl(int)
Network - > hostShort (16 bit) ntohs(int)Long (32 bit) ntohl(int)
20
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200339
gethostbyname()
#include <sys/socket.h>
struct hostent *server;
server = gethostbyname(“name”);
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200340
struct hostent
gethostbyname()
struct in_addr
h_addr
bcopy()
struct sockaddr_in
assegnamento
htons(porta)
21
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200341
struct hostent *server_host;struct in_addr server_host_addr;struct sockaddr_in server_addr;
server_host = gethostbyname(“www.dsi.unimi.it");if ( server_host == NULL ) {
perror("gethostbyname() ");exit(1);
}
bcopy(server_host->h_addr, &server_host_addr, server_host->h_length);
server_addr.sin_family = AF_INET;server_addr.sin_port = htons(80);bcopy(&server_host_addr, &server_addr.sin_addr,
sizeof(server_host_addr));
if(connect(s, &server_addr, sizeof(server_addr)==-1) {perror("connect() ");exit(1);
}
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200342
inet_addr()
#include <sys/socket.h>
unsigned long addr;addr = inet_addr(“xxx.xxx.xxx.xxx”);
server_addr.sin_addr.s_addr = addr
22
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200343
getservbyname()
Get SERVICE by name
struct servent *service;service = getservbyname(“service”, proto)
/etc/services
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200344
struct servent *service_entry;int service_port;
service_entry = getservbyname("chargen", "tcp");if(service_entry == NULL) {
perror("getservbyname() ");exit(2);
}service_port = service_entry -> s_port;
23
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200345
## Network services, Internet style### $FreeBSD: src/etc/services,v 1.62.2.3 2000/10/05 07:37:37# sheldonh Exp $# From: @(#)services 5.8 (Berkeley) 5/9/91## WELL KNOWN PORT NUMBERS#rtmp 1/ddp #Routing Table Maintenance Protocoltcpmux 1/tcp #TCP Port Service Multiplexertcpmux 1/udp #TCP Port Service Multiplexernbp 2/ddp #Name Binding Protocolecho 4/ddp #AppleTalk Echo Protocolecho 7/tcpecho 7/udpdiscard 9/tcp sink nulldiscard 9/udp sink null
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200346
systat 11/tcp users #Active Userssystat 11/udp users #Active Usersdaytime 13/tcpdaytime 13/udpqotd 17/tcp quote #Quote of the Dayqotd 17/udp quote #Quote of the Daychargen 19/tcp ttytst #Character Generatorchargen 19/udp ttytst #Character Generatorftp-data 20/tcp #File Transfer [Default Data]ftp-data 20/udp #File Transfer [Default Data]ftp 21/tcp #File Transfer [Control]ftp 21/udp #File Transfer [Control]ssh 22/tcp #Secure Shell Loginssh 22/udp #Secure Shell Logintelnet 23/tcptelnet 23/udp...
24
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200347
read / write
int num_bytes;num_bytes = read(socket, buffer, size);
int num_bytes;num_bytes = write(socket, buffer, size);
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200348
close()
int error;error = close(socket);
25
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200349
Implementazione di un server
Dobbiamo scrivere un programma in C che offre un servizio
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200350
Server iterativo
Offro servizio ad un client alla volta
Il sistema operativo tiene gli altri client “in coda”
È la variante più semplice
26
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200351
creazione socket
naming
scambio dati
chiusura canale
messa in attesa
accettazione client
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200352
socket()
bind()
read()/write()
close()
listen()
accept()
27
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200353
socket()
bind()
listen()
close()
read()/write()
accept()
Server
socket()
connect()
close()
Client
read()/write()
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200354
bind()
Associa ad una socket l’indirizzo transport sul quale dovrà attendere i clientViene anche chiamato “naming” della socketAnche in questo caso dobbiamo “riempire”una struttura che contiene un indirizzo transport
28
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200355
bind()
int error;error = bind(socket, localaddr, addrlen);
socket()
sizeof(localaddr)struct sockaddr_instruct sockaddr_un
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200356
Local address
L’indirizzo IP e la porta prendono significati diversi rispetto al client
L’indirizzo IPÈ lindirizzo LOCALE tramite il quale sarà possibile accettare connessioni (ha senso solo nel caso ci siano più schede di rete)
local_addr.sin_addr.s_addr = INADDR_ANY;
La portaÈ la porta sulla quale il server sarà in attesa.Questa è un informazione che interessa al client
29
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200357
Le porte disponibili
Non tutte le porte sono ugualiDa 1 a 1024 sono riservate al sistema
Solo il superuser può fare una bind a quella portaSono quasi tutte standardizzate
Da 1025 a 65535 sono allocabili dagli utentiChiunque può fare bindSe specifichiamo “porta 0” alla bind li sistema alloca il server sulla prima libera maggiore di 1024Alcune sono standardizzate
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200358
int s;struct sockaddr_in local_addr;
s = socket(AF_INET, SOCK_STREAM, 0);if ( s < 0 ) {
perror("socket() ");exit(1);
}
local_addr.sin_family = AF_INET;local_addr.sin_port = htons(0);local_addr.sin_addr.s_addr = INADDR_ANY;
If (bind(s, &local_addr, sizeof(local_addr)) == -1) {perror("bind() ");exit(1);
}
30
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200359
E adesso ?
Ho lasciato scegliere al sistema la porta, e adesso ... come faccio a sapere qual’è ?
int error;error = getsockname(socket, sockaddr, addrlen);
indirizzo da riempire
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200360
struct sockaddr_in query_addr;int query_addrlen;
...
if (bind(s, &local_addr, sizeof(local_addr)) == -1) {perror("bind() ");exit(1);
}
query_addrlen = sizeof(query_addr);if (getsockname(s, &query_addr, &query_addrlen) == -1){
perror("getsockname() ");exit(2);
}
printf(“binded on port %d\n”, ntohs(query_addr.sin_port));
31
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200361
listen()
Abilita la socket a ricevere connessioni dai clientStabilisce la lunghezza massima della coda d’attesaQuando un client si presenta e tutta la coda è giàpiena, allora a questo viene rifiutato il servizioPer motivi non molto chiari la lunghezza massima della coda è 5Dopo che una socket viene abilitata all’attesa, non potrà più essere usata per trasferire dati, ma solo per attendere richieste di connessione
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200362
listen()
int error;error = listen(socket, queuelen);
if (listen(s, 5) == -1) {perror("listen() ");exit(1);
}
32
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200363
accept()
Serve ad “accettare” richieste di connessione da parte di un client
Il processo rimane bloccato fino a che un client non esegue una connectall’indirizzo transport su cui siamo in attesa
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200364
accept()
int data_socket;data_socket = accept(socket, peeraddr, addrlen);
socket()
sizeof(peeraddr)Verrà riempito conl’indirizzo dellasocket del client
33
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200365
struct sockaddr_in accept_addr;int accept_addrlen;char client_host[255];int client_port;
...
accept_addrlen = sizeof(struct sockaddr_in);
data_sock = accept(s, &accept_addr, &accept_addrlen);if (data_sock < 0) {
perror("accept() ");exit(1);
}
strcpy(client_host, inet_ntoa(accept_addr.sin_addr));client_port = ntohs(accept_addr.sin_port);
printf(“client on host %s, port %d\n", client_host, client_port);
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200366
Implementazione di un server concorrente o multiprocesso
Dobbiamo scrivere un programma in C che offre un servizio, ma non vogliamo tenere gente “in coda”
34
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200367
Server multiprocesso
Offro servizio a più client contemporaneamente
È una variante di poco più complicata del server iterativo
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200368
creazione socket
naming
scambio dati
chiusura canale
messa in attesa
accettazione client
35
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200369
creazione socket
naming
creazione processo
messa in attesa
accettazione client
scambio dati
chiusura canale
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200370
socket()
bind()
fork()
listen()
accept()
read()/write()
close()
36
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200371
fork()
int pid;pid = fork();
if (pid == 0)printf(“figlio\n”);
elseprintf(“padre\n”);
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200372
fork()int data_socket;int pid;
while(1) {data_socket = accept(s, &accept_addr,
&accept_addrlen);pid = fork();if (pid == 0)
give_service(data_socket);close(data_socket); /* codice del padre */
}
...
void give_service(int socket) {close(s);...close(socket);exit(0);
}
37
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200373
La morte del processo figlio
Il sistema operativo notifica l’avvenuta morte al padreUn segnale viene messo in coda al PCB del processo padre ed il figlio viene tolto dalla process table solo quando il processo è stato gestitoQuindi, il server deve prendersi cura di gestire il segnale, altrimenti avremmo una proliferazioni di processi “zombie”
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200374
socket()
bind()
fork()
listen()
accept()
read()/write()
close()
exit()signal()
38
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200375
signal()/exit()
int reaper();
void main(int argc, char ** argv) {...signal(SIGCHLD, reaper);...while (1) { ... }
}
int reaper() {int status;while ( wait3 (&status, WNOHANG, NULL) >= 0);(void) signal(SIGCHLD, reaper);
}
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200376
Server concorrente
Offro servizio a più client contemporaneamente
È la variante più complessa da gestire
39
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200377
creazione socket
naming
scambio dati
messa in attesa
attesa multipla
chiusura connessione
accettazione client
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200378
socket()
bind()
read()/write()
listen()
select()
close()
accept()
40
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200379
Maschere di bit
Servono ad elencare dei gruppi di file descriptor
Questo non vuol dire che ci limitiamo alle socketPotremmo voler scrivere un server che gestisce delle socket e contemporaneamente un operatore da tastiera
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200380
select()
Ci permette di stare in attesa su più canali contemporaneamente
La select termina quando è possibile fare una operazione su uno qualunque dei canali, secondo certi criteri di selezione
41
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200381
seletc()
select( maxfd, read_mask, write_mask, error_mask, timeout)
fd_set
struct timeval
FOPEN_MAX
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200382
Maschere di bit
ATTENZIONE
Dopo essere stata usata come parametro per la select, una maschera di bit non è più utilizzabile.
Dentro ci saranno le informazioni su quali canali sono disponibile per effettuare operazioni
42
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200383
Manipolazione delle maschere
FD_ZERO(maschera)Azzeramento della maschera
FD_SET(fd, maschera)Impostazione di un canale
FD_CLR(fd, maschera)De-impostazione di un canale
FD_ISSET(fd, maschera)Controlle se è possibile fare operazioni sul canale
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200384
fd_set fds;fd_set temp_fds;int nfds;...FD_ZERO(&fds);FD_SET(s, &fds);...while(1) {
bcopy((char *)&fds,(char *)&temp_fds, sizeof(fds));if (select(nfds, temp_fds, NULL, NULL, NULL) < 0) {
perror(“select()”);exit(1);
}...
}
43
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200385
int fd;
while(1) {bcopy((char *)&fds,(char *)&temp_fds, sizeof(fds));select(nfds, temp_fds, NULL, NULL, NULL);if(FD_ISSET(s, &temp_fds)) {
data_sock = accept(s, ...);FD_SET(data_sock,&fds);
}else {
for(fd = 0; fd <= nfds; fd += 1) {if(FD_ISSET(fd, &temp_fds)) {
do_read_write(fd);}
}}
}
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200386
int fd;
while(1) {...else {
for(fd = 0; fd <= nfds; fd += 1) {if(FD_ISSET(fd, &temp_fds)) {
do_echo(fd);FD_CLR(fd, &fds);close(fd);
}}
}}
44
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200387
Socket UDP
La differnza tra TCP e UDP è che il secondo non implementa strutture per il controllo di flusso
Ogni singolo blocco di dati viene spedito come un pacchetto indipendente, se viene perso il sistema non si preoccupa di ritrasmetterlo
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200388
creazione socket
connessione
scambio dati
chiusura canale
45
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200389
socket()
connect()
send()/recv()
close()
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200390
socket()
#include <sys/socket.h>
int s;
s = socket (domain, type, protocol)
AF_UNIXAF_INETAF_NS
SOCK_DGRAMSOCK_STREAMSOCK_STREAMSOCK_STREAMSOCK_RAWSOCK_SEQPACKET
“/etc/protocols”
46
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200391
socket()
int s;s = socket(AF_INET, SOCK_DGRAM, 0);If ( s < 0 ) {
perror("socket() ");exit(1);
}
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200392
connect()
#include <sys/socket.h>
int error;
error = connect(socket, addr, len);
socket()
struct sockaddr_instruct sockaddr_un sizeof(addr)
47
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200393
send()
#include <sys/types.h>#include <sys/socket.h>
int size;size = send(socket, buffer, len, flags)
socket()
0MSG_EOF
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200394
recv()
#include <sys/types.h>#include <sys/socket.h>
int size;size = recv(socket, buffer, len, flags)
0MSG_PEEKMSG_WAITALL
48
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200395
creazione socket
naming
scambio dati
chiusura canale
messa in attesa
accettazione client
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200396
socket()
bind()
send()/recv()
close()
49
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200397
bind()
int error;error = bind(socket, localaddr, addrlen);
socket()
sizeof(localaddr)struct sockaddr_instruct sockaddr_un
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200398
socket()
bind()
send()/recv()
close()
?????
50
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/200399
Connectionless !
Non avendo fatto la connect la socket locale NON possiede informazioni sul peer remoto !
Questa cosa può essere risolta a livello applicazione, dall’altra parte anche il client deve fare una binde darci la possibilità di mandare indietro i dati (comunicandoci la porta)
NOTA: lo schema appena visto NON va bene!
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/2003100
Client/Server completamente connectionless
Perchè fare la connect (o accept) se puoi non abbiamo controllo di flusso ?
È possibile usare la socket in maniera connectionless se facciamo uso di altre primitive (specializzate) per inviare/ricevere messaggi a/da indirizzi arbitrari
51
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/2003101
socket()
bind()
sendto()/recvfrom()
close()
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/2003102
sendto()
#include <sys/types.h>#include <sys/socket.h>
int size;size = sendto(socket, buffer, len, flags,
to_addr, addrlen);
struct sockaddr_instruct sockaddr_un sizeof(to_addr)
52
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/2003103
recvfrom()
#include <sys/types.h>#include <sys/socket.h>
int size;size = recvfrom(socket, buffer, len, flags,
from_addr, addrlen);
struct sockaddr_instruct sockaddr_un sizeof(from_addr)
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/2003104
Client/Server completamente connectionless
Anche da parte del client possiamo fare a meno della connect
Però questo ci costringe ad usare una bind, altrimenti il sistema non allocherà una porta alla socket locale ed il server non riusciràcomunque a rispondere
53
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/2003105
creazione socket
connessione
scambio dati
chiusura canale
naming
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/2003106
socket()
bind()
sendto()/recvfrom()
close()
54
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/2003107
Client o Server ?
Lo schema ottenuto risulta identico allo schema che abbiamo visto parlando del server
Siamo di fronte ad una struttura completamente simmetrica
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/2003108
Raw socket
Il sistema compie molte operazioni sui livelli bassi della rete, ma che non sono immediatamente visibili all’utente tramite l’interfaccia delle socket
L’intercettazione di un pacchetto IPAnche se non era indirizzato a noi (sniffing)
La generazione di un pacchetto (IP) partendo da un array di byte
Possiamo creare un header arbitrario (spoofing)
55
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/2003109
Cose certe ...
Java ? No grazie !La programmazione dipende fortemente dal sistema operativo
Gli header con cui interpretiamo/costruiamo i pacchetti sono molto specifici per ogni implementazione (BSD/Linux/SUN/HP)
Dobbiamo essere superuser per poter utilizzare queste funzionalità
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/2003110
PCAP
PCAP (Packet CAPture) è una libreria scritta da Van Jacobson, Craig Leres e Steven McCanne all’università diBerkeleyAttualmente è subito disponibile dopo l’installazione in molte distribibuzioni di UNIX (BSD e Linux-mandrake), in altre occorre installare software aggiuntivo (Linux-redhat e UNIX commerciali)Non è inclusa di default, per farne uso occorre specificare “-lpcal” alla compilazione
cc file.o –o file -lpcap
56
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/2003111
Ricezione di pacchetti
Identificare l’interfaccia da utilizzareInizializzare (aprire) l’interfacciaApplicare dei filtri sui pacchetti da intercettare (opzionale)Intercettare pacchettiChiudere l’interfaccia
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/2003112
Identificazione interfaccia
Abbiamo bisogno di una stringa che identifica la periferica per il sistema operativo (e.g. ”eth0”)
Abbiamo due possibilità:L’utente ce la fornisce (con un parametro)La richiediamo al sistema
I nomi delle interfacce variano da sistema a sistemaLinux: ethXBSD: xlX, deX, edX ...
57
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/2003113
pcap_lookupdev()
#include <pcap.h>
char error_desc[PCAP_ERRBUF_SIZE];char *dev;
dev = pcap_lookupdev(error_desc)
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/2003114
#include <stdio.h>#include <pcap.h>
int main() {char *dev, errbuf[PCAP_ERRBUF_SIZE];dev = pcap_lookupdev(errbuf);if (dev == null)
printf(“Error: %s\n”, errbuf);else
printf("Device: %s\n", dev);}
58
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/2003115
Apertura dell’interfaccia
Usiamo la funzione pcap_open_live() per ottenere un handle dell’interfaccia da cui leggere i pacchetti
L’interfaccia può essere aperta in due modalitàStandard: vedo solo i pacchetti indirizzati alla
mia macchinaPromisqua: vedo tutti i pacchetti sulla mia sottorete
(TUTTI!)
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/2003116
pcap_open_live()
#include <pcap.h>
pcap_t *handle;char *dev;int snaplen, promisc, timeout;char error_desc[PCAP_ERRBUF_SIZE];
handle = pcap_open_live(dev, snaplen, promisc, timeout, errror_desc)
pcap_lookupdev()
True/False
milliseconds
packet snapsize
59
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/2003117
#include <pcap.h>
...
char *dev;char errbuf[PCAP_ERRBUF_SIZE];pcap_t *handle;char packet[PACKET_SIZE];
...
dev = pcap_lookupdev(errbuf);printf("Device: %s\n", dev);
handle = pcap_open_live(dev, PACKET_SIZE, 1, 0, errbuf);
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/2003118
Filtri
Se la rete è molto congestionata potremmo non voler vedere tutto il traffico ma solo una parte (e.g. quello verso il server web)Risulta utile poter scrivere dei filtri in modo che l’interfaccia selezioni “a monte” quello che il programma vedrà
La creazione di un filtro avviene in due passaggi:La “compilazione”, che permette di passare da una rappresentazione tramite stringa ad una binariaL’associazione della rappresentazione binaria all’interfaccia
60
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/2003119
pcap_compile()
#include <pcap.h>
pcap_t *handle;struct bpf_program *binarychar * source;int optimize;unsigned int netmask;int error;
error = pcap_compile(handle, binary, source, optimize, netmask)
pcap_open_live()
True/False
inputtcpdump(1) expression
output
???
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/2003120
pcap_setfilter()
#include <pcap.h>
pcap_t *handle;struct bpf_program *binary;int error;
error = pcap_setfilter(handle, binary)
pcap_open_live()
pcap_compile()
61
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/2003121
L’informazione mancante
A volte è necessario passare parametri relativi alla configurazione della scheda di rete alle funzioni di PCAPPotremmo richiederli all’utente o andare a interpretare i file di configurazioneIn realtà PCAP ci mette a disposizione una funzione per chiedere alla scheda stessa come è configurata (pcap_lookupnet())
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/2003122
pcap_lookupnet()
#include <pcap.h>
char *dev;unsigned int net, mask;char errbuf[PCAP_ERRBUF_SIZE];int error;
error = pcap_lookupnet(dev, &net, &mask, errbuf);
pcap_open_live()non serve
netmask
Identificativo della reteIP & NETMASK
62
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/2003123
#include <pcap.h>
...char *dev = “eth0”;unsigned int net, mask;char errbuf[PCAP_ERRBUF_SIZE];pcap_t *handle;char packet[PACKET_SIZE];struct bpf_program binary;char * source = “port 80”;...pcap_lookupnet(dev, &net, &mask, errbuf);handle = pcap_open_live(dev, PACKET_SIZE, 1, 0, errbuf);pcap_compile(handle, &binary, source, 0, mask);pcap_setfilter(handle, &binary);...
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/2003124
Ricezione dei pacchetti
Abbiamo due possibilità:
Prelevare un pacchetto alla volta
Predisporre una routine che verrà chiamata ogni volta che arriva un pacchetto fino al raggiungimento di un numero prefissato
63
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/2003125
pcap_next()
#include <pcap.h>
pcap_t *handler;struct pcap_pkthdr *header;char packet[PACKET_SIZE];
packet = pcap_next(handler, header)
payload
informazioni
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/2003126
struct pcap_pkthdr {struct timeval ts;
/* time stamp */bpf_u_int32 caplen;
/* length of portion present */bpf_u_int32 len;
/* length this packet (off wire) */};
64
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/2003127
pcap_loop()
#include <pcap.h>
pcap_t *handler;int counter;pcap_handler handler; char * user;int error;
error = pcap_loop(handler, counter, callback, *user)
numeropacchetti
routinedi gestione
dati utente
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/2003128
La routine di gestione
#include <pcap.h>
char * args;struct pcap_pkthdr *header;char packet[PACKET_SIZE];
void got_packet(args, header, packet);
ultimo parametro di pcap_loop()
header
payload
65
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/2003129
Interpretazione di un pacchetto
Quello che otteniamo tramite le routine di PCAP è un array di byte
È compito nostro interpretare il contenuto
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/2003130
DATA
TCPheader
IPheader
Ethernetheader
DATA
DATA
DATATCPheader
TCPheader
IPheader
Ethernet frame
16 bit src TCP port #16 bit dst TCP port #
Protocol TCP32 bit src IP addr32 bit dst IP addr
Frame type IP48 bit src ETH addr48 bit dst ETH addr
66
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/2003131
0 1 2 30 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| Ethernet destination address (first 32 bits) |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| Ethernet dest (last 16 bits) |Ethernet source (first 16 bits)|+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| Ethernet source address (last 32 bits) |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| Type code | |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| data || |
...| || end of data |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| Ethernet Checksum |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
IP, ARP, RARP ...
Ethernet header
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/2003132
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |Version| IHL |Type of Service| Total Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Identification |Flags| Fragment Offset | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Time to Live | Protocol | Header Checksum | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Source Address | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Destination Address | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Options | Padding | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | data || |
TCP, UDP, MPLS ...
IP header
67
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/2003133
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| Source Port | Destination Port |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| Sequence Number |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| Acknowledgment Number |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| Data | |U|A|P|R|S|F| || Offset| Reserved |R|C|S|S|Y|I| Window || | |G|K|H|T|N|N| |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| Checksum | Urgent Pointer |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| Options | Padding |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| data || |
TCP header
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/2003134
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| Source Port | Destination Port |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| Length | Checksum |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| Data || |
UDP header
68
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/2003135
Interpretazione di un pacchetto
L’unica cosa di cui siamo sicuri è che l’inizio dell’array corrisponde ad un header ethernet
Il sistema operativo mette a disposizione delle strutture che interpretano gli header usando i loro campi
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/2003136
char * packet;struct ether_header * eptr; /* net/ethernet.h */struct iphdr * iph; /* netinet/ip.h */struct tcphdr * tcph; /* netinet/tcp.h */struct udphdr * udph; /* netinet/udp.h */
...
eptr = (struct ether_header *) packet;
if (ntohs (eptr -> ether_type) == ETHERTYPE_IP) {printf("IP packet\n“);iph = (struct iphdr *) (packet +
sizeof(struct ether_header));if (ntohs (iph -> ip_p) == IPTYPE_TCP) {
tcph = (struct tcphdr *) ((char *) iph + sizeof(struct iphdr));
69
Dario Maggiorini (dario@dico.unimi.it) - Programmazione di rete in C – Ultima Revisione: 20/11/2003137
printf(“TCP destination port is %x\n”, ntohs(tcph -> th_dport);
}else if (ntohs (iph -> ip_p == IPTYPE_UDP) {
udph = (struct udphdr *) ((char *) iph + sizeof(struct iphdr));
printf(“UDP destination port is %x\n”, ntohs(udph -> uh_dport);
}else {
printf(“IP type not TCP nor UDP“);}
}else if (ntohs (eptr -> ether_type) == ETHERTYPE_ARP) {
printf("ARP packet\n“); else {
printf("Ethernet type %x not IP nor ARP“,ntohs(eptr->ether_type));
}
top related