Vous êtes sur la page 1sur 29

La programmation reseau.´

Deuxieme`

partie

La programmation reseau.´ Deuxieme` partie v2 Labo-Unix - http://www.labo-unix.net 2001-2002 1
La programmation reseau.´ Deuxieme` partie v2 Labo-Unix - http://www.labo-unix.net 2001-2002 1

v2 Labo-Unix - http://www.labo-unix.net

2001-2002

1

La programmation reseau.´

Deuxieme`

partie

La programmation reseau.´ Deuxieme` partie

Table des matieres`

Droits de ce document

 

3

Introduction

 

4

1 Des applications compatibles IPv4 et IPv6

 

4

1.1 La fonction qui simplifie tout .

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

6

1.2 Les macros

 

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

7

1.3 Exemple .

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

7

2 Changer divers parametres`

.

2.1

Exemple .

.

.

.

.

.

.

des sockets : setsockopt() et getsockopt() ; .

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

9

11

3 Les flags des fonctions send() et recv()

 

11

4 Manipuler les descripteur

 

11

4.1 Entrees/sorties´

non-bloquantes

 

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

12

4.2 Entrees/sorties´

avec SIGIO

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

12

5 Les RAW sockets

 

13

5.1

Manipuler les periph´

eriques´

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

14

6 La bibliotheque`

PCAP (Paquet CAPture)

 

16

6.1

Selectionner un periph´

erique´

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

16

6.2

Obtenir des informations sur le periph´

erique´

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

16

6.3

Capturer les paquets

 

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

16

6.4

Utiliser des filtres

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

17

6.5

Gestion des erreurs

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

17

6.6

Exemple .

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

17

7 Fin

19

8 ANNEXE

 

19

8.1

Les structures utilsees´

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

19

9 GNU Free Documentation License

 

22

9.1 Applicability and Definitions

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

22

9.2 Verbatim Copying .

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

23

9.3 Copying in Quantity

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

23

9.4 Modifications

 

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

24

9.5 Combining Documents

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

25

9.6 Collections of Documents .

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

26

9.7 Aggregation With Independent Works

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

26

9.8 Translation

 

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

26

9.9 Termination

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

27

9.10 Future Revisions of This License .

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

27

La programmation reseau.´

Deuxieme`

partie

La programmation reseau.´ Deuxieme` partie

Ref´ erences´

28

La programmation reseau.´

Deuxieme`

partie

La programmation reseau.´ Deuxieme` partie

Droits de ce document

Copyright (c) 2001 labo-unix.org Permission vous est donnee´ de copier, distribuer et/ou modifier ce document selon les termes de la Licence GNU Free Documentation License, Version 1.1 ou ulterieure´ pu- bliee´ par la Free Software Foundation ; avec les sections inalterables´ suivantes :

- pas de section inalterable`

Une copie de cette Licence est incluse dans la section appelee´ GNU Free Documenta- tion License de ce document.

La programmation reseau.´

Deuxieme`

partie

La programmation reseau.´ Deuxieme` partie

Introduction

Dans la premiere` partie nous avons vu la programmation des sockets, leur utilisation de base. Memeˆ si nous sommes maintenant capables de realiser´ de veritables´ applications utilisant le reseau,´ nous n’avons vu qu’une petite partie de ce que l’on peut faire avec des sockets. Dans ce cours, nous allons voir comment faire des applications qui utilisent differents´ protocoles IP (v4 et v6) de maniere` transparente. Nous allons aussi plonger un peu plus au cœur des sockets afin de modifier leurs comportements. Nous verrons egalement´ comment faire ses propres trames IP (ou TCP) ainsi qu’un petit aperc¸u de la libpcap pour capturer des paquets et les analyser.

1 Des applications compatibles IPv4 et IPv6

Aujourd’hui, la version 4 du protocole IP commence a` montrer ses limites. On a donc

decid´ e´ de la modifier. IPv6 simplifie beaucoup de choses dans la gestion des paquets :

routage simplifie,´ paquets pouvant etreˆ plus petit, plage d’adresse etendues,´ facilement

. cadre de cet article. La plupart des systemes` d’exploitation courant sont maintenant com- patibles IPv6. Le materiel´ compatible est egalement´ disponible. La migration d’IPv4 vers IPv6 est prevues´ mais se fait tres` lentement. C’est notamment duˆ au fait que de nom- breuses applications ne le supportent pas encore.

extensible, authentification prevues.´

.Mais analyser ce protocole ne rentre pas dans le

Evidemment, IPv4 va etreˆ encore present´ pendant un moment. La meilleure fac¸on de migrer petit a` petit d’IPv4 vers IPv6 est de faire des applications compatibles avec les 2 protocoles. Vous vous doutez bien que ce n’est pas si simple. Beaucoup de structures de

donnees´

la seule donnee´ liee´ au

protocole que nous utilisions etait´

sont modifiees´

pour IPv6. En C, dans le cours prec´ edent,´

la structure sockaddr.

pour IPv4 et IPv6. Ainsi si pour les sockets

IPv4 nous utilisions la structure sockaddr in pour stocker l’adresse et le service (port), il existe la structure sockaddr in6 qui est l’equivalent´ pour IPv6. Ce sont deux structures similaires mais incompatibles.

Les structures de donnees´

sont differentes´

Voici les deux structures :

struct sockaddr_in6 {

u_int8_t

sin6_len;

/* length of this struct(sa_family_t)*/

u_int8_t

sin6_family;

/* AF_INET6 (sa_family_t) */

u_int16_t

sin6_port;

/* Transport layer port # (in_port_t)*/

u_int32_t

sin6_flowinfo; /* IP6 flow information */

};

struct in6_addr sin6_addr;

u_int32_t

/* IP6 address */

sin6_scope_id; /* scope zone index */

struct sockaddr_in { u_char sin_len; u_char sin_family; /* la famille du protocole */ u_short sin_port; /* le port au format reseau */ struct in_addr sin_addr; /* l’adresse IP au format reseau */

La programmation reseau.´

Deuxieme`

partie

La programmation reseau.´ Deuxieme` partie

char

sin_zero[8];

};

taille. Ce qui

pose un reel´

ET IPv6, nous devons donc manipuler independamment´ des structures sockaddr in et

sockaddr in6. Dans ce cas, soit nous dupliquons le code afin d’avoir une partie traitant les sockets IPv4 et une autre les sockets IPv6 (ce qui est tres` lourd) soit nous nous basons

sur quelques regles`

En effet, si nous voulons manipuler a` la fois les sockets IPv4

On voit aisement´

que les deux structures n’ont pas du tout la memeˆ

probleme.`

simples du langage C :

– Les structures doivent subir les memesˆ regles` d’alignement en memoire.´

– Le premier champ doit toujours etreˆ aligne´ au debut´ de cette structure.

– Des bytes de separation´ peuvent par contre etreˆ introduits par le compilateur entre deux champs afin d’obtenir un alignement correcte pour le type concerne.´

– L’ordre des el´ ements´ dans une structure doit etreˆ conserve.´

Deux valeurs du memeˆ type ont toujours les memesˆ regles` d’alignement et la memeˆ taille. Pour respecter tout cela on utilise la structure sockaddr storage. Si les structures so- ckaddr in et sockaddr in6 sont incompatibles, il est toutefois envisageable de creer´ une structure plus longue dans laquelle il sera possible de copier aussi bien des objets de type struct sockaddr in que de type struct sockaddr in6. Il serait memeˆ judicieux de

prevoir´ de l’espace supplementaire´ pour de futures versions pouvant necessiter´ des struc- tures plus longues (IPv7 ?). Cette longue structure se nomme sockaddr storage. Elle est censee´ etreˆ capable de stocker n’importe quelle adresse et n’importe quel iden- tifiant de service, pour n’importe quel protocole supporte´ par le systeme` d’exploitation

(IPv4, IPv6, X25,

.).

e´ as-

sez d’espace pour un objet de type struct sockaddr storage, nous pouvons copier a` ce memeˆ endroit une structure sockaddr in ou une structure sockaddr in6. Le tout est

que sizeof(struct sockaddr in) < sizeof(struct sockaddr storage) et que sizeof(struct so- ckaddr in6) < sizeof(struct sockaddr storage) soient verifi´ es.´

L’inter´ etˆ

d’avoir une structure plus (’trop’) grande est que si nous avons reserv´

Si une application utilise la structure gen´ erique´

sockaddr storage au lieu de sockaddr in,

des adresses IPv4 et IPv6. Cepen-

utile de

savoir quelle structure y a reellement´

de port, par exemple, il faudra lire le champ sin port en IPv4 et le champ sin6 port en IPv6. On ne peut pas prendre l’un pour l’autre, car ces donnees´ peuvent etreˆ stockees´ a` des endroits differents´ en memoire,´ et c’est sans evoquer´ les adresses IP dont le format est totalement incompatible. La solution est tres` simple : ajouter au debut´ de chaque structure le memeˆ champ, dont le roleˆ sera de contenir une valeur caracteristique´ du protocole. Ce champ se nomme ss family (ou ss family sous linux) .

il est garanti qu’elle saura manipuler simultanement´

dant, lorsque l’on a un objet de type struct sockaddr storage, il peut etreˆ

Si l’on souhaite connaˆıtre le numero´

tres`

et´ e´ recopiee.´

Cette composition des structures repond´ parfaitement a` tous nos besoins. Il est pos- sible de stocker des objets de type struct sockaddr in ou struct sockaddr in6 dans une

La programmation reseau.´

Deuxieme`

partie

La programmation reseau.´ Deuxieme` partie

structure sockaddr storage. Et lorsque l’on est en presence´ pouvons en connaˆıtre le protocole exact.

d’un objet de ce type, nous

1.1 La fonction qui simplifie tout

les noms avec IPv6, il existe toujours les fonctions gethostbyname(),

getservbyname() mais il existe une fonction (basee´ sur les prec´ edentes)´ beaucoup plus gen´ erique´ : getadddrinfo().

Pour resoudre´

Celle-ci va se baser sur des indices pour essayer de remplir une structure sockaddr storage. Elle se charge des nom de machines et de services, que ce soit IPv4 ou IPv6.

#include <sys/types.h> #include <sys/socket.h> #include <netdb.h>

int getaddrinfo(const char *nodename, const char *servname, const struct addrinfo *hints, struct addrinfo **res);

contenant le nom de la machine (”www.labo-

unix.org”) ou son adresse IP (”212.198.130.1” ou ” : :1”). Il peut etreˆ NULL si on ne souhaite pas resoudre´ l’IP.

servname est une chaˆıne de caractere` contenant le nom du service (”pop3”) ou bien son numero´ de port (”110”). Il peut lui aussi etreˆ NULL si on ne s’interesse´ pas a` la resolution´ du service.

hints est une structure contenant des indices qui vont modifier notre recherche.

res est l’emplacement ou` seront places´ le type struct addrinfo :

struct addrinfo {

nodename est une chaˆıne de caractere`

les resultats.´

int

ai_flags;

/* AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST */

int

ai_family;

/* PF_xxx */

int

ai_socktype; /* SOCK_xxx */

int

ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */

size_t ai_addrlen;

char

struct sockaddr *ai_addr; /* binary address */ struct addrinfo *ai_next; /* next structure in linked list */ };

*ai_canonname; /* canonical name for nodename */

/* length of ai_addr */

Hints va nous permettre de donner quelques indices sur le resultat´

ai flags : 0 ou une combinaison logique des valeurs represent´ ees´ par les macros suivantes : AI PASSIVE, AI CANONNAME et AI NUMERICHOST.

ai family : indique la famille d’adresse : AF INET, AF INET6 ou AF UNSPEC.

ai socktype : le type de connexion : SOCK DGRAM ou SOCK STREAM.

ai protocol : IPPROTO IP, IPPROTO ICMP, IPPROTO TCP

ai addrlen, ai addr, ai canonname et ai next sont a` laisser vides.

a` obtenir :

etc.

Le resultat´ sera stocke´ a` l’adresse ecrite´ dans res. Il s’agit aussi d’une structure addrinfo mais les derniers champs seront remplis :

ai addrlen : la taille de la structure (sizeof(struct sockaddr in) pour IPv4 et si- zeof(struct sockaddr in6) pour IPv6).

ai addr pointe sur une structure sockaddr in ou sockaddr in6.

La programmation reseau.´

Deuxieme`

partie

La programmation reseau.´ Deuxieme` partie

Si AI CANONNAME a et´ e´ specifi´ e,´ ai canonname contient le nom de machine qui a et´ e´ resolu.´ Et comme il peut y avoir plusieur reponse,´ il s’agit d’une liste chaˆınee.´ ai next pointe sur la structure suivante, et vaut NULL lorsqu’on est en fin de liste.

Si getaddrinfo() renvoie une valeur non nulle, c’est qu’il y a eu une erreur. Celle-ci

peut etreˆ

Enfin, il ne faut pas oublier de liberer´

Ceci s’effectue graceˆ

obtenue avec la fonction gai strerror().

la place en memoire´

a` la fonction freeaddrinfo().

prise par la liste chaˆınee´

res.

1.2 Les macros

Pour le type d’adresse :

– AF INET permet de specifier´

– AF INET6 permet de specifier´

– AF UNSPEC permet de ne pas specifier´

une adresse IPv4.

une adresse IPv6.

de type d’adresse.

Pour IPv4 :

– INADDR ANY represente´

– INADDR NONE represente´

– INADDR LOOPBACK represente´

n’importe quelle adresse.

une adresse non-assignee´

ou inconnue.

une adresse locale de la machine (127.x.x.x).

– INADDR BROADCAST represente´ toutes les machines susceptibles de repondre´ a` une diffusion.

– IN MULTICAST() renvoie un valeur non nulle si l’adresse appartient a` la classe multicast.

– IN BADCLASS() renvoie une valeur non nulle si l’adresse fait partie d’une classe reservee.´

– INET ADDRSTRLEN le nombre maximal de caracteres` necessaires´ pour noter une adresse IPv4. Pour IPv6 :

– IN6 IS ADDR MULTICAST renvoie une valeur non nulle si l’adresse represente´ un groupe de machines.

– IN6 IS ADDR UNSPECIFIED renvoie une valeur non nulle si l’adresse n’est pas valide.

– INET6 ADDRSTRLEN la taille maximale d’une chaˆıne contenant la notation chiffree´

d’une adresse IPv6. Il y a aussi une structure globale de 16 octets (in6addr any) representant´

quelle adresse IPv6. Ainsi qu’une structure globale in6addr loopback contenant l’adresse locale ( : :1).

n’importe

1.3 Exemple

/* $Id: Socket2.tex,v 1.5 2002/02/01 00:11:02 danseurfou Exp $

*

*

Il s’agit du meme client que dans la premiere partie

*

du cours mais celui-ci utilise getaddrinfo() au lieu de

*

gethostbyname()

*/

La programmation reseau.´

Deuxieme`

partie

La programmation reseau.´ Deuxieme` partie

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h>

#define PORT "1543" #define HOST "localhost"

int main(int ac, char *av[])

{

int code; struct addrinfo indice, *resultat, *scan;

char *port = PORT; char *hostname = HOST; char *requete = "HEAD / HTTP/1.0\n\n"; char buffer[1024];

switch(ac) { case 3:

port = av[2]; case 2:

hostname = av[1]; case 1:

break;

default:

printf("Usage:\n\t%s [hostname [port]]\n\n", av[0]); return -1;

}

bzero(&indice, sizeof indice);

/* on veut se connecter en TCP que ce soit IPv4 ou IPv6 */ indice.ai_family = AF_UNSPEC; indice.ai_socktype = SOCK_STREAM; indice.ai_protocol = IPPROTO_IP;

if((code = getaddrinfo(hostname, port, &indice, &resultat))) {

printf("*** erreur: %s [%s]\n", hostname, gai_strerror(code)); return -1;

}

scan = resultat;

/* on va essayer tous les resultats jusqu’a ce qu’il y en ait un qui marche */ while(scan != NULL) { int sd;

if((sd = socket(scan->ai_family, scan->ai_socktype, scan->ai_protocol)) < 0) { perror("socket"); goto suivant;

}

if(connect(sd, scan->ai_addr, scan->ai_addrlen) < 0) {

La programmation reseau.´

Deuxieme`

partie

La programmation reseau.´ Deuxieme` partie

perror("connect"); } else { send(sd, requete, strlen(requete));

while(recv(sd, buffer, 1024, 0) > 0) printf(buffer); close(sd); break;

}

close(sd);

suivant:

scan = scan->ai_next;

}

freeaddrinfo(resultat);

return 0;

 

}

2

Changer divers parametres`

des sockets : setsockopt() et getsockopt() ;

Ces deux fonctions permettent de gerer´ certaines options au niveau des protocoles ou bien des sockets. Par exemple, il peut etreˆ utile de changer le timeout sur un socket. En effet, lorsque nous utilisons les fonctions connect() ou recv(), celles-ci se bloquent jusqu’a` ce que l’operation´ desir´ ee´ se realise.´ Ca peut-etreˆ tres` genant.´

On peut aussi par exemple vouloir changer la taille du buffer d’emission´

pour des applications specifiques.´

#include <sys/types.h> #include <sys/socket.h>

Mais voyons :

ou de reception,´

int setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen); int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen);

s est le socket sur lequel operer.´

level permet de situer le niveau de nos operations´

:

– sur le sockets (SOL SOCKET)

– sur le protocole IP (IPPROTO IP)

– sur le protocole TCP (IPPROTO TCP)

– sur le protocole UDP (IPPROTO UDP)

– .(pour les protocoles, voir < netinet/in.h >

optname donne le nom du parametre`

a` changer.

optval donnera la valeur du parametre` (1 => active,´ 0 => desactiv´ e´ ou un chiffre lorsqu’il s’agit d’un tampon ou d’un timeout) et optlen la taille de la valeur (qui est gen´ eralement´ un int). Ces deux fonctions renvoient -1 si il y eu une erreur, 0 sinon.

Les noms de parametres`

au niveau du socket (donc avec level == SOL SOCKET) :

– SO DEBUG : afficher des informations de debuggage

La programmation reseau.´

Deuxieme`

partie

La programmation reseau.´ Deuxieme` partie

– SO ACCEPTCONN : le socket est un socket d’ecoute´

– SO REUSEADDR : on autorise la reutilisation´

– SO REUSEPORT : on autorise la reutilisation´

– SO KEEPALIVE : on garde les connexions ouvertes

– SO DONTROUTE : on n’utilise pas le routage standard

– SO BROADCAST : on peut emettre´

– SO USELOOPBACK : bypass hardware when possible ( ? ? pas teste)´

– SO LINGER : on attend avant de fermer le socket si il reste des donnees´

– SO OOBINLINE : les donnees´

– SO ACCEPTFILTER : on utilise des filtres (pas dispo partout)

– SO SNDBUF : taille du buffer d’envoie

– SO RCVBUF : taille du buffer de reception´

– SO SNDLOWAT : quelle taille minimum est necessaire´

– SO RCVLOWAT : quelle taille minimum est necessaire´

– SO SNDTIMEO : timeout d’envoie

– SO RCVTIMEO : timeout de reception´

– SO ERROR : on recupere´

– SO TYPE : on recup´

(c’est la cas apres`

un listen())

de l’adresse locale de l’adresse et du port

en broadcast

a` envoyer

prioritaires sont ajoutees´

au trafic normal

avant d’envoyer avant que read() retourne

la derniere`

erreur

ere`

le type du socket

On peut aussi modifier de nombreux parametres` au niveau IP ou bien TCP. Nous verrons c¸a peut-etreˆ plus tard. C’est dej´ a` utile de savoir qu’ils existent. Les voila` en vrac :

– IP OPTIONS : buf/ip opts ; set/get IP options */

– IP HDRINCL : int ; header is included with data */

– IP TOS : int ; IP type of service and preced. */

– IP TTL : int ; IP time to live */

– IP RECVOPTS : bool ; receive all IP opts w/dgram */

– IP RECVRETOPTS : bool ; receive IP opts for response */

– IP RECVDSTADDR : bool ; receive IP dst addr w/dgram */

– IP RETOPTS : ip opts ; set/get IP options */

– IP MULTICAST IF : u char ; set/get IP multicast i/f */

– IP MULTICAST TTL : u char ; set/get IP multicast ttl */

– IP MULTICAST LOOP : u char ; set/get IP multicast loopback */

– IP ADD MEMBERSHIP : ip mreq ; add an IP group membership */

– IP DROP MEMBERSHIP : ip mreq ; drop an IP group membership */

– IP MULTICAST VIF : set/get IP mcast virt. iface */

– IP RSVP ON : enable RSVP in kernel */

– IP RSVP OFF : disable RSVP in kernel */

– IP RSVP VIF ON : set RSVP per-vif socket */

– IP RSVP VIF OFF : unset RSVP per-vif socket */

– IP PORTRANGE : int ; range to choose for unspec port */

– IP RECVIF : bool ; receive reception if w/dgram */

– TCP NODELAY don’t delay send to coalesce packets */

– TCP MAXSEG : set maximum segment size */

– TCP NOPUSH : don’t push last block of write */

– TCP NOOPT : don’t use TCP options */

La programmation reseau.´

Deuxieme`

partie

La programmation reseau.´ Deuxieme` partie

2.1 Exemple

Lorsque l’on ferme un socket, si des donnees´ ne sont pas envoyees,´ elles sont per- dues. Il y a une option tres` pratique avec setsockopt() qui permet d’attendre l’envoie des donnees´ encore presentes´ avant de fermer le socket : SO LINGER. Nous allons faire une

fonction qui modifie ce parametres`

/* sock est notre socket */ int set_option(int sock)

sur notre socket.

{

int on = 1; if(setsockopt(sock, SOL_SOCKET, SO_LINGER, (void *)&on, sizeof on)) { perror("setsockopt"); return -1; } else

return 0;

}

3

Les flags des fonctions send() et recv()

Dans la premiere` partie du cours, nous avons vu que send() et recv() avait un quatrieme`

parametre` : flags. La majeure partie de ces options peuvent etreˆ changees´ au niveau du socket avec setsockopt(). Mais on peut aussi les gerer´ au cas par cas lorsque l’on envoie ou rec´ eptionne´ des donnees.´ Avec send() :

– MSG OOB : ce sont des donnees´

– MSG DONTROUTE : on utilise directement les interfaces sans se soucier des routes

– MSG EOR : c’est la fin des donnees´

– MSG EOF : c’est la fin de la transaction (utilise´ seulement avec certains protocoles)

prioritaires

(utilise´ seulement avec certains protocoles)

Pour les deux :

– MSG TRUNC : data discarded before delivery ( ? ? ? pas teste)´

– MSG CTRUNC : control data lost before delivery ( ? ? ? pas teste)´

– MSG DONTWAIT : le message sera non-bloquant (voir plus loin) avec recv() :

– MSG OOB : on ne lit que les donnees´

– MSG PEEK : lit les donnees´

prioritaires

sans les retirer du buffer. Une nouvelle lecture renverra

la memeˆ

chose

– MSG WAITALL : attend jusqu’a` la fin de la requeteˆ

ou bien jusqu’a` une erreur

4 Manipuler les descripteur

#include <fcntl.h>

int fcntl(int fd, int cmd,

);

La fonction fcntl() (file control) permet de manipuler les descripteurs de fichier (donc aussi de socket). fd est le desripteur de fichier.

cmd est la commande. En fonction de cette commande, fcntl() peut prendre un troisieme`

parametre`

: int arg.

La programmation reseau.´

Deuxieme`

partie

La programmation reseau.´ Deuxieme` partie

les differentes´

commandes qui nous interessent :

– F GETFL : obtenir les flags du descripteur

– F SETFL : changer les flags du descripteur

– F GETOWN : obtenir les PID qui rec¸oive SIGIO

– F SETOWN : changer les PID qui rec¸oive SIGIO

Les flags qui nous interessent pour F GETFL et F SETFL sont les suivants :

– O ASYNC : recevoir SIGIO lorsqu’il y a des donnees´

– O FSYNC : synchroniser les ecritures´

– O NONBLOCK : entrees/sorties´

(n’utilise pas le cache du disque)

non-bloquantes

4.1 Entrees/sorties´

Nous avons vu que connect() se bloque lorsqu’il n’arrive pas a se connecter ou qu’il attends que la connexion s’etablisse´ et que recv() attends d’avoir des donnees´ a` lire avant de les retourner. On peut diminuer le timeout du socket mais c¸a n’empechera pas un certain temps d’attente. D’autant plus que si on diminue trop le timeout du socket, plus aucune connexion ne sera possible (il faut de quelques millisecondes a` quelques secondes pour que les paquets arrivent a` une machine). Il existe une autre solution pour eviter´ cela :

faire des sockets non-bloquants.

non-bloquantes

Pour ceci, il faut d’abord creer´ le socket. Ensuite, graceˆ a` fcntl(), on peut rendre le socket non-bloquant. A partir de la,` si on utilise la fonction connect(), elle ne se bloquera pas en attendant l’etablissement´ de la connexion. Elle va renvoyer une erreur (si les pa- rametres` sont corrects) : EINPROGRESS qui signifie que l’operation´ est en cours mais pas terminee.´ Pour savoir si la connexion s’est correctement passee,´ on pourra utiliser les fonctions poll() ou select() en testant l’ecriture´ sur le socket. Evidemment, on peut toujours bloquer poll() et select() avec un timeout mais on peut aussi leur demander de tester directement sans se bloquer (avec un timeout de 0).

Ensuite, si l’on utilise read() et que la fonction renvoie l’erreur EAGAIN, c’est qu’il n’y a rien a` lire sur le socket. Idem pour send(). On peut ainsi ne pas bloquer l’appli- cation sur une operation´ de lecture ou d’ecriture.´ Si des donnees´ sont presentes,´ read() fonctionne normalement (idem pour send()).

Pour passer le socket en mode non-bloquant, on procede`

ainsi :

/* sock est notre socket */ int set_nonblock(int sock)

{

int flags = fcntl(sock, F_GETFL);

fcntl(sock, F_SETFL, flags | O_NONBLOCK); /* je ne gere pas les codes de retour et il peut y avoir une erreur */

}

4.2 Entrees/sorties´

avec SIGIO

Une autre fac¸on de ne pas bloquer l’application sur une operation´

de lecture ou d’ecriture´

est d’utiliser les signaux. Le principe est de creer´

un socket, puis de demander au systeme`

La programmation reseau.´

Deuxieme`

partie

La programmation reseau.´ Deuxieme` partie

d’envoyer le signal SIGIO a` l’application lorsqu’il y aura des donnees´

notre programme, nous redirigerons le signal SIGIO vers la fonction de lecture du socket.

a` lire dessus. Dans

Pour rediriger le signal SIGIO, nous utiliserons la fonction signal() :

#include <signal.h>

void (*signal(int sig, void (*func)(int)))(int);

Ne fuyez pas devant le prototype barbare. Le premier parametre` est tout simplement le

numero´

est un pointeur sur une fonction qui ne renvoie rien et prend un int comme parametre.`

du signal (definit´

par SIGINT, SIGUSR1, SIGHUP

)

et le deuxieme`

parametre`

Voyons un exemple :

int read_sock(int signal)

{

/* c’est notre fonction de lecture que je ne detaillerai pas.

* Sachez seulement que le param`etre n’est pas le socket mais

* le signal (ici SIGIO). Et n’oubliez pas que l’on utilise pas

* n’importe quelle fonction pendant la gestion d’un signal

*/

}

/* Comme d’hab, sock est notre socket */

int set_sigio(int sock)

{

int flags = fcntl(sock, F_GETFL); signal(SIGIO, read_sock);

/* il ne faut pas oublier de sp´ecifier quel PID recevra

* le signal: */

fcntl(sock, F_SETOWN, getpid());

/* ensuite on demande de recevoir le SIGIO sur ce descripteur: */ fcntl(sock, F_SETFL, flags | O_ASYNC);

/* je n’ai pas gerer le eventuelles erreurs

}

Graceˆ a` ces quelques lignes, le programme recevra SIGIO des` qu’il y aura des donnees´ a` lire sur le socket. Si vous rep´ etez´ l’operation´ avec plusieurs sockets, ce sera a` vous de les differencier´ (graceˆ a` poll() ou select()) pour savoir lequel attends des donnees´ qui sont la cause du signal.

*/

5 Les RAW sockets

Avec UNIX (et maintenant aussi avec WinXP) on peut creer´ soit-memeˆ les paquets qui vont transiter sur le reseau.´ C’est a` dire que l’on va nous-memeˆ creer´ les en-tetesˆ TCP

ou UDP ainsi que IP. Pour cela, il faut creer´

socket(PF_INET, SOCK_RAW, IPPROTO_IP);

ce que l’on appelle un RAW socket :

On peut remplacer IPPROTO IP par un autre protocole. Si vous voulez creer´

memeˆ

les en-tetesˆ

IP, alors il faut le specifier´

au systeme`

graceˆ

a` :

vous

#include <netinet/ip.h> int on = 1; setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (void *)&on, sizeof on);

La programmation reseau.´

Deuxieme`

partie

La programmation reseau.´ Deuxieme` partie

A partir de la,` vous pouvez envoyer les paquets graceˆ a` la fonction sendto(). Le deuxieme` parametre` va etreˆ votre paquet TCP/IP (ou UDP/IP ou ICMP). Vous devez donc allouer une zone memoire´ qui comprendra l’en-teteˆ IP puis l’en-teteˆ TCP puis les donnees.´ Mais il vous faut correctement remplir les en-tetesˆ TCP et IP dont voici les structures (sur un FreeBSD) :

struct ip {

u_int

ip_hl:4,

/* header length */

ip_v:4;

/* version */

u_char ip_tos;

/* type of service */

u_short ip_len;

/* total length */

u_short ip_id;

/* identification */

u_short ip_off;

/* fragment offset field */

u_char

ip_ttl;

/* time to live */

u_char

ip_p;

/* protocol */

u_short ip_sum;

/* checksum */

struct in_addr ip_src,ip_dst; /* source and dest address */

};

struct tcphdr {

 

u_short th_sport; u_short th_dport; tcp_seq th_seq; tcp_seq th_ack;

/* source port */ /* destination port */ /* sequence number */ /* acknowledgement number */

u_int

th_x2:4,

/* (unused) */

th_off:4;

/* data offset */

};

u_char th_flags; u_short th_win; u_short th_sum; u_short th_urp;

/* window */ /* checksum */ /* urgent pointer */

Remarque : avec linux, le nom de la structure pour les en-teteˆ

IP est : struct iphdr.

Vous pouvez aussi tres` bien creer´ des paquets ICMP ou UDP/IP ou tout autre protocole existant, voir memeˆ d’un protocole n’existant pas. Encore une fois le but de ce cours n’est pas de vous expliquer le fonctionnement de TCP/IP. Nous ne rentrerons pas dans les details.´ Vous avez toutes les informations necessaire´ pour faire vos paquets.

Si on peut les creer,´

c’est qu’on peut aussi les analyser. Et c’est beaucoup plus interes-

voir comment

sant. Avec un RAW socket, on peut obtenir les paquets IP, les decortiquer,´

cela

.et faire son propre analyseur de reseau.´

Mais si vous voulez regarder passer tous les paquets qui passent sur le reseau´

cas sur votre cable reseau),´

il va falloir le demander a` la carte reseau.´

(en tout

5.1 Manipuler les periph´

#include <sys/ioctl.h>

eriques´

int ioctl(int d, unsigned long request,

);

Il s’agit d’une fonction permettant de manipuler les parametres` d’un periph´ erique.´ On s’approche dej´ a` nettement plus du materiel.´ Nous n’allons voir cette fonction que pour

La programmation reseau.´

Deuxieme`

partie

La programmation reseau.´ Deuxieme` partie

changer quelques parametres` de la carte reseau,´ notamment le mode promiscuous. Celui- ci permet a` la carte de capturer tous les paquets se trouvant sur le brin. Autrement vous n’auriez que les paquets qui vous sont destines´ (beaucoup moins drole).ˆ

Le premier parametre` de la fonction ioctl() est un descripteur ouvert. Dans notre cas un socket, mais cela` pourrait aussi etreˆ un periph´ erique´ (/dev/dsp par exemple pour mo- difier les parametres` de la carte son). Le deuxieme` parametre` est le nom du parametre` a` modifier. Pour les sockets, ils sont dans le fichier < sys/sockio.h >. Mais si vous vou- lez toucher au frame buffer, il va falloir regarder dans < sys/f bio.h > par exemple (et pour un FreeBSD). Ou bien < sys/soundcard.h > pour la carte son. Tous les periph´ eriques´ peuvent etreˆ acced´ es´ graceˆ a` cette fonction. Le troisieme` parametre` de ioctl() est specifique´ au periph´ erique.´ Dans notre cas, il s’agit d’une structure ifreq (do- cumentee´ en annexe).

Cette structure contient differents´

parametres`

de la carte reseau.´

On va d’abord recuperer´

les parametres`

les droits administrateur (root). Un exemple veut mieux qu’un long discours :

/* interface est le nom de la carte r´eseau:

courants, puis les modifier. Pour passer en mode promiscuous, il vous faut

* eth0, eth1

ed0, xl0

* ou autre pour BSD

pour linux.

*/ #include <sys/sockio.h> #include <sys/ioctl.h> #include <net/if.h>

int set_promisc(char *interface, int sock)

{

struct ifreq ifr;

bzero(&ifr, sizeof ifr);

strncpy(ifr.ifr_name, interface, sizeof(ifr.ifr_name));

/* on r´ecupere les param`etres courants */ if(ioctl(sd, SIOCGIFFLAGS, &ifr) == -1) { perror("ioctl get"); return -1;

}

/* on modifie les flags pour que la carte soit en mode promiscuous */ ifr.ifr_flags |= IFF_PROMISC;

/* et on change les param`etres */ if(ioctl(sd, SIOCSIFFLAGS, &ifr) == -1) { perror("ioctl set promisc"); return -1; } else

puts("promiscuous mode enable for %s\n", interface);

}

Maintenant vous pouvez analyser tous les paquets passant sur votre brin : vous pouvez

les trames.

les recevoir avec la fonction recvfrom() et regarder comment sont constituees´ N’oubliez pas de remettre la carte en mode normal a` la fin du programme.

La programmation reseau.´

Deuxieme`

partie

La programmation reseau.´ Deuxieme` partie

6 La bibliotheque`

PCAP (Paquet CAPture)

Memeˆ si la methode´ prec´ edente´ marche tres` bien, elle n’est pas portable sur tous les unix. Surtout que certains implementent´ des facilites´ pour capturer les paquets. Pour

simplifier l’ecriture´ d’utilitaires d’analyse reseau,´ il existe une bibliotheque` : la libpcap.

Elle permet memeˆ

de capturer les paquets ethernet

Voici les fonctions les plus utiles. N’oubliez pas d’inclure < pcap.h > et de lier avec la libpcap (-lpcap) lors de la compilation.

6.1 Selectionner un periph´

erique´

char *pcap_lookupdev(char *errbuf);

que l’on peut scruter. errbuf est un tampon

de taille minimum PCAP ERRBUF SIZE.

pcap_t *pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf);

Permet d’ouvrir un periph´ erique´ pour capturer les paquets. device est ce que nous a renvoye´ la fonction prec´ edentes.´ snaplen est la taille maximum des paquets que l’on veut. promisc determine´ si la carte doit etreˆ en mode promiscuous. to ms est le temps d’attente d’un paquet en millisecondes avant de renvoyer une erreur. ebuf est le memeˆ tampon d’erreur que prec´ edemment.´ La structure pcap t renvoyee´ sera passee´ en parametre` a` toutes les fonctions qui vont suivre. Renvoie NULL en cas d’erreur.

Va nous renvoyer le nom d’un p eriph´

erique´

6.2 Obtenir des informations sur le periph´

erique´

int pcap_lookupnet(char *device, bpf_u_int32 *netp, bpf_u_int32 *maskp, char *errbuf);

Permet d’obtenir le masque de reseau´

et l’adresse de reseau´

de l’interface. Retourne

-1 si erreur (et errbuf contient le message d’erreur).

int pcap_datalink(pcap_t *p);

Renvoie le type de media´

utilise.´

int pcap_stats(pcap_t *p, struct pcap_stat *ps);

Permet d’obtenir des statistiques sur l’interface.

6.3 Capturer les paquets

int pcap_dispatch(pcap_t *p, int cnt, pcap_handler callback, u_char *user);

Collecte et passe les paquets a` la fonction callback. La fonction callback va recevoir trois parametres` : le premier est user, le deuxieme` est de type u char * et contient les donnees´ du paquet, le dernier est de type pcap pkthdr et contient diverses informations

dans l’annexe). cnt est la nombre maximum de paquets a`

s’il y a une erreur ou si elle arrive au nombre maximum de

sur le paquet (structure definie´ traiter. La fonction s’arreteraˆ paquets a` traiter.

int pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user);

La programmation reseau.´

Deuxieme`

partie

La programmation reseau.´ Deuxieme` partie

Fait exactement la memeˆ

chose mais ne s’arreteraˆ

que lorsqu’elle arrivera au nombre

de paquets a` traiter (parametre`

cnt, si -1 alors elle boucle a` l’infini).

u_char *pcap_next(pcap_t *p, struct pcap_pkthdr *h);

Renvoie seulement le prochain paquet. Les donnees´ pcap pkthdr est remplie.

sont renvoyees´

et la structure

6.4 Utiliser des filtres

Pour savoir comment utiliser les filtres, reportez vous a` BPF (Berkeley Paquet Filter).

int pcap_compile(pcap_t *p, struct bpf_program *fp, char *str, int optimize, bpf_u_int32 netmask);

Permet de compiler la regle`

doit etreˆ

effectuee.´

str dans le filtre fp. optimize controleˆ

si une optimisation

de l’interface.

sur le resultat´

netmask est le masque de sous-reseau´

int pcap_setfilter(pcap_t *p, struct bpf_program *fp);

Permet de specifier´

quels filtres seront utilises´

pour capturer les paquets.

void pcap_freecode(struct bpf_program *);

Permet de liberer´

la memoire´

utilisee´

par une structure bpf program.

6.5 Gestion des erreurs

void pcap_perror(pcap_t *p, char *prefix) : Permet d’afficher le mes- sage d’erreur. char *pcap_geterr(pcap_t *p) : Permet d’obtenir le message d’erreur. char *pcap_strerror(int error) : C’est la memeˆ chose que la fonction de la libc strerror().

6.6 Exemple

/* Un petit exemple de capture de paquet */

#include <stdio.h> #include <stdlib.h> #include <pcap.h> #include <errno.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netinet/if_ether.h>

int main(int argc, char **argv)

{

int i; char *dev; char errbuf[PCAP_ERRBUF_SIZE]; pcap_t* descr; const u_char *packet; struct pcap_pkthdr hdr; struct ether_header *eptr; u_char *ptr;

La programmation reseau.´

Deuxieme`

partie

La programmation reseau.´ Deuxieme` partie

/* trouver un p´eriph´erique */ if((dev = pcap_lookupdev(errbuf)) == NULL) { printf("%s\n",errbuf); return -1;

}

printf("peripherique: %s\n",dev);

if((descr = pcap_open_live(dev, BUFSIZ, 0, 0, errbuf)) == NULL) { printf("pcap_open_live(): %s\n", errbuf); return -1;

}

/* on va recupere le prochain paquet */

if((packet = pcap_next(descr, &hdr)) == NULL) { puts("Impossible de recuperer un paquet"); return -1;

}

printf("Capture paquet de taille %d\n", hdr.len); printf("Recu a: %s\n",ctime((const time_t*)&hdr.ts.tv_sec));

eptr = (struct ether_header *)packet;

/* quel type de paquet on a ? */ if (ntohs(eptr->ether_type) == ETHERTYPE_IP) {

printf("Type 0x%x => IP\n", ntohs(eptr->ether_type));

} else if (ntohs(eptr->ether_type) == ETHERTYPE_ARP) {

printf("Type 0x%x => ARP\n", ntohs(eptr->ether_type));

} else {

printf("Type 0x%x not IP", ntohs(eptr->ether_type)); return -1;

}

ptr = eptr->ether_dhost;

i = ETHER_ADDR_LEN;

printf(" Destination Adresse: ");

do{

printf("%s%x",(i == ETHER_ADDR_LEN) ? " " : ":",*ptr++);

} while(--i > 0); puts("");

ptr = eptr->ether_shost;

i = ETHER_ADDR_LEN;

printf(" Source Adresse: ");

do{

printf("%s%x",(i == ETHER_ADDR_LEN) ? " " : ":",*ptr++);

} while(--i > 0); puts("");

return 0;

}

La programmation reseau.´

Deuxieme`

partie

La programmation reseau.´ Deuxieme` partie

7 Fin

J’espere` que ces quelques informations vous aurons interess´ ees.´ Et que maintenant vous etesˆ capables de faire des applications reseau´ consequentes.´ La programmation C n’est pas evidente´ mais lorsque l’on connait suffisamment le domaine, c’est un reel´ plai- sir car il n’y a que tres` peu de limites. Seulement votre

Pour finir un grand merci a` Jedi (www.jedi.claranet.fr) pour la partie IPv4/IPv6.

8 ANNEXE

8.1 Les structures utilsees´

Attention il s’agit des structures extrait d’un FreeBSD. Sur linux, il se peut qu’il y ait des changements.

struct sockaddr_in6 {

u_int8_t

sin6_len;

/* length of this struct(sa_family_t)*/

u_int8_t

sin6_family;

/* AF_INET6 (sa_family_t) */

u_int16_t

sin6_port;

/* Transport layer port # (in_port_t)*/

u_int32_t

sin6_flowinfo; /* IP6 flow information */

};

struct in6_addr sin6_addr;

u_int32_t

/* IP6 address */

sin6_scope_id; /* scope zone index */

struct addrinfo {

int

ai_flags;

/* AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST */

int

ai_family;

/* PF_xxx */

int

ai_socktype; /* SOCK_xxx */

int

ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */

size_t ai_addrlen;

char

struct sockaddr *ai_addr; /* binary address */ struct addrinfo *ai_next; /* next structure in linked list */ };

*ai_canonname; /* canonical name for nodename */

/* length of ai_addr */

struct ip {

u_int

ip_hl:4,

/* header length */

ip_v:4;

/* version */

u_char ip_tos;

/* type of service */

u_short ip_len;

/* total length */

u_short ip_id;

/* identification */

u_short ip_off;

/* fragment offset field */

u_char

ip_ttl;

/* time to live */

u_char

ip_p;

/* protocol */

u_short ip_sum;

/* checksum */

struct in_addr ip_src,ip_dst; /* source and dest address */

};

struct tcphdr { u_short th_sport; u_short th_dport;

/* source port */ /* destination port */

La programmation reseau.´

Deuxieme`

partie

La programmation reseau.´ Deuxieme` partie

tcp_seq th_seq;

/* sequence number */

tcp_seq th_ack;

/* acknowledgement number */

u_int

th_x2:4,

/* (unused) */

th_off:4;

/* data offset */

u_char th_flags; u_short th_win; u_short th_sum; u_short th_urp;

};

struct udphdr { u_short uh_sport; u_short uh_dport; u_short uh_ulen; u_short uh_sum;

/* window */ /* checksum */ /* urgent pointer */

/* source port */ /* destination port */ /* udp length */ /* udp checksum */

};

struct icmp { u_char

icmp_type;

u_char

icmp_code;

/* type of message, see below */ /* type sub code */

u_short icmp_cksum;

/* ones complement cksum of struct */

union {

u_char ih_pptr; struct in_addr ih_gwaddr; struct ih_idseq { n_short icd_id; n_short icd_seq;

} ih_idseq; int ih_void; struct ih_pmtu { n_short ipm_void; n_short ipm_nextmtu;

} ih_pmtu;

/* ICMP_PARAMPROB */ /* ICMP_REDIRECT */

struct ih_rtradv { u_char irt_num_addrs; u_char irt_wpa;

u_int16_t irt_lifetime;

} ih_rtradv; } icmp_hun;

#define icmp_pptr #define icmp_gwaddr #define icmp_id #define icmp_seq #define icmp_void #define icmp_pmvoid #define icmp_nextmtu

#define icmp_num_addrs icmp_hun.ih_rtradv.irt_num_addrs

#define icmp_wpa #define icmp_lifetime union {

icmp_hun.ih_pptr

icmp_hun.ih_gwaddr

icmp_hun.ih_idseq.icd_id

icmp_hun.ih_idseq.icd_seq

icmp_hun.ih_void

icmp_hun.ih_pmtu.ipm_void

icmp_hun.ih_pmtu.ipm_nextmtu

icmp_hun.ih_rtradv.irt_wpa

icmp_hun.ih_rtradv.irt_lifetime

struct id_ts { n_time its_otime; n_time its_rtime; n_time its_ttime;

} id_ts;

La programmation reseau.´

Deuxieme`

partie

La programmation reseau.´ Deuxieme` partie

struct id_ip

{

struct ip idi_ip;

} id_ip;

struct icmp_ra_addr id_radv; u_int32_t id_mask;

char } icmp_dun; #define icmp_otime #define icmp_rtime #define icmp_ttime #define icmp_ip #define icmp_radv #define icmp_mask #define icmp_data };

struct ifreq {

id_data[1];

icmp_dun.id_ts.its_otime

icmp_dun.id_ts.its_rtime

icmp_dun.id_ts.its_ttime

icmp_dun.id_ip.idi_ip

icmp_dun.id_radv

icmp_dun.id_mask

icmp_dun.id_data

char

ifr_name[IFNAMSIZ];

/* if name, e.g. "en0" */

union {

struct sockaddr ifru_addr; struct sockaddr ifru_dstaddr; struct sockaddr ifru_broadaddr; short ifru_flags[2]; int ifru_metric; int ifru_mtu; int ifru_phys; int ifru_media; caddr_t ifru_data; int ifru_cap[2]; } ifr_ifru;

#define ifr_addr #define ifr_dstaddr #define ifr_broadaddr #define ifr_flags #define ifr_prevflags #define ifr_metric #define ifr_mtu #define ifr_phys #define ifr_media #define ifr_data #define ifr_reqcap #define ifr_curcap };

ifr_ifru.ifru_addr

ifr_ifru.ifru_dstaddr

/* address */ /* other end of p-to-p link */

/* metric */ /* mtu */ /* physical wire */ /* physical media */ /* for use by interface */ /* requested capabilities */ /* current capabilities */

ifr_ifru.ifru_broadaddr /* broadcast address */ ifr_ifru.ifru_flags[0] /* flags */ ifr_ifru.ifru_flags[1] /* flags */

ifr_ifru.ifru_metric ifr_ifru.ifru_mtu ifr_ifru.ifru_phys ifr_ifru.ifru_media ifr_ifru.ifru_data

ifr_ifru.ifru_cap[0]

ifr_ifru.ifru_cap[1]

struct pcap_pkthdr { struct timeval ts;

bpf_u_int32 caplen; /* length of portion present */

bpf_u_int32 len;

/* time stamp */

/* lebgth this packet (off wire) */

}

La programmation reseau.´

Deuxieme`

partie

La programmation reseau.´ Deuxieme` partie

9 GNU Free Documentation License

Version 1.1, March 2000

Copyright copyright 2000 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.

Preamble

The purpose of this License is to make a manual, textbook, or other written document “free” in the sense of freedom : to assure everyone the effective freedom to copy and redistribute it, with or without modifying it, either commercially or noncommercially. Secondarily, this License preserves for the author and publisher a way to get credit for their work, while not being considered responsible for modifications made by others. This License is a kind of “copyleft”, which means that derivative works of the docu- ment must themselves be free in the same sense. It complements the GNU General Public License, which is a copyleft license designed for free software. We have designed this License in order to use it for manuals for free software, because free software needs free documentation : a free program should come with manuals provi- ding the same freedoms that the software does. But this License is not limited to software manuals ; it can be used for any textual work, regardless of subject matter or whether it is published as a printed book. We recommend this License principally for works whose purpose is instruction or reference.

9.1 Applicability and Definitions

This License applies to any manual or other work that contains a notice placed by the copyright holder saying it can be distributed under the terms of this License. The “Document”, below, refers to any such manual or work. Any member of the public is a licensee, and is addressed as “you”.

A “Modified Version” of the Document means any work containing the Document or a

portion of it, either copied verbatim, or with modifications and/or translated into another language.

A “Secondary Section” is a named appendix or a front-matter section of the Document

that deals exclusively with the relationship of the publishers or authors of the Document to the Document’s overall subject (or to related matters) and contains nothing that could fall directly within that overall subject. (For example, if the Document is in part a textbook of mathematics, a Secondary Section may not explain any mathematics.) The relationship could be a matter of historical connection with the subject or with related matters, or of legal, commercial, philosophical, ethical or political position regarding them. The “Invariant Sections” are certain Secondary Sections whose titles are designated, as being those of Invariant Sections, in the notice that says that the Document is released under this License.

La programmation reseau.´

Deuxieme`

partie

La programmation reseau.´ Deuxieme` partie

The “Cover Texts” are certain short passages of text that are listed, as Front-Cover

Texts or Back-Cover Texts, in the notice that says that the Document is released under this License.

A “Transparent” copy of the Document means a machine-readable copy, represented

in a format whose specification is available to the general public, whose contents can be viewed and edited directly and straightforwardly with generic text editors or (for images composed of pixels) generic paint programs or (for drawings) some widely available dra- wing editor, and that is suitable for input to text formatters or for automatic translation to a variety of formats suitable for input to text formatters. A copy made in an otherwise Transparent file format whose markup has been designed to thwart or discourage sub- sequent modification by readers is not Transparent. A copy that is not “Transparent” is called “Opaque”. Examples of suitable formats for Transparent copies include plain ASCII without mar- kup, Texinfo input format, L A T E X input format, SGML or XML using a publicly available DTD, and standard-conforming simple HTML designed for human modification. Opaque formats include PostScript, PDF, proprietary formats that can be read and edited only by proprietary word processors, SGML or XML for which the DTD and/or processing tools are not generally available, and the machine-generated HTML produced by some word processors for output purposes only. The “Title Page” means, for a printed book, the title page itself, plus such following pages as are needed to hold, legibly, the material this License requires to appear in the title page. For works in formats which do not have any title page as such, “Title Page” means the text near the most prominent appearance of the work’s title, preceding the beginning of the body of the text.

9.2 Verbatim Copying

You may copy and distribute the Document in any medium, either commercially or

noncommercially, provided that this License, the copyright notices, and the license notice saying this License applies to the Document are reproduced in all copies, and that you add no other conditions whatsoever to those of this License. You may not use technical measures to obstruct or control the reading or further copying of the copies you make or distribute. However, you may accept compensation in exchange for copies. If you distribute a large enough number of copies you must also follow the conditions in section

3.

You may also lend copies, under the same conditions stated above, and you may pu- blicly display copies.

9.3 Copying in Quantity

If you publish printed copies of the Document numbering more than 100, and the

Document’s license notice requires Cover Texts, you must enclose the copies in covers that carry, clearly and legibly, all these Cover Texts : Front-Cover Texts on the front cover, and Back-Cover Texts on the back cover. Both covers must also clearly and legibly identify you as the publisher of these copies. The front cover must present the full title with all words of the title equally prominent and visible. You may add other material

La programmation reseau.´

Deuxieme`

partie

La programmation reseau.´ Deuxieme` partie

on the covers in addition. Copying with changes limited to the covers, as long as they preserve the title of the Document and satisfy these conditions, can be treated as verbatim copying in other respects. If the required texts for either cover are too voluminous to fit legibly, you should put the first ones listed (as many as fit reasonably) on the actual cover, and continue the rest onto adjacent pages. If you publish or distribute Opaque copies of the Document numbering more than 100, you must either include a machine-readable Transparent copy along with each Opaque copy, or state in or with each Opaque copy a publicly-accessible computer-network lo- cation containing a complete Transparent copy of the Document, free of added mate- rial, which the general network-using public has access to download anonymously at no charge using public-standard network protocols. If you use the latter option, you must take reasonably prudent steps, when you begin distribution of Opaque copies in quantity, to ensure that this Transparent copy will remain thus accessible at the stated location until at least one year after the last time you distribute an Opaque copy (directly or through your agents or retailers) of that edition to the public. It is requested, but not required, that you contact the authors of the Document well before redistributing any large number of copies, to give them a chance to provide you with an updated version of the Document.

9.4

You may copy and distribute a Modified Version of the Document under the conditions

of sections 2 and 3 above, provided that you release the Modified Version under precisely this License, with the Modified Version filling the role of the Document, thus licensing distribution and modification of the Modified Version to whoever possesses a copy of it. In addition, you must do these things in the Modified Version :

– Use in the Title Page (and on the covers, if any) a title distinct from that of the Document, and from those of previous versions (which should, if there were any, be listed in the History section of the Document). You may use the same title as a previous version if the original publisher of that version gives permission.

– List on the Title Page, as authors, one or more persons or entities responsible for authorship of the modifications in the Modified Version, together with at least five of the principal authors of the Document (all of its principal authors, if it has less than five).

– State on the Title page the name of the publisher of the Modified Version, as the publisher.

Modifications

– Preserve all the copyright notices of the Document.

– Add an appropriate copyright notice for your modifications adjacent to the other copyright notices.

– Include, immediately after the copyright notices, a license notice giving the public permission to use the Modified Version under the terms of this License, in the form shown in the Addendum below.

– Preserve in that license notice the full lists of Invariant Sections and required Cover Texts given in the Document’s license notice.

– Include an unaltered copy of this License.

La programmation reseau.´

Deuxieme`

partie

La programmation reseau.´ Deuxieme` partie

– Preserve the section entitled “History”, and its title, and add to it an item stating at least the title, year, new authors, and publisher of the Modified Version as given on the Title Page. If there is no section entitled “History” in the Document, create one stating the title, year, authors, and publisher of the Document as given on its Title Page, then add an item describing the Modified Version as stated in the previous sentence.

– Preserve the network location, if any, given in the Document for public access to a Transparent copy of the Document, and likewise the network locations given in the Document for previous versions it was based on. These may be placed in the “History” section. You may omit a network location for a work that was published at least four years before the Document itself, or if the original publisher of the version it refers to gives permission.

– In any section entitled “Acknowledgements” or “Dedications”, preserve the sec- tion’s title, and preserve in the section all the substance and tone of each of the contributor acknowledgements and/or dedications given therein.

– Preserve all the Invariant Sections of the Document, unaltered in their text and in their titles. Section numbers or the equivalent are not considered part of the section titles.

– Delete any section entitled “Endorsements”. Such a section may not be included in the Modified Version.

– Do not retitle any existing section as “Endorsements” or to conflict in title with any Invariant Section. If the Modified Version includes new front-matter sections or appendices that qualify as Secondary Sections and contain no material copied from the Document, you may at your option designate some or all of these sections as invariant. To do this, add their titles to the list of Invariant Sections in the Modified Version’s license notice. These titles must be distinct from any other section titles. You may add a section entitled “Endorsements”, provided it contains nothing but en- dorsements of your Modified Version by various parties – for example, statements of peer review or that the text has been approved by an organization as the authoritative definition of a standard. You may add a passage of up to five words as a Front-Cover Text, and a passage of up to 25 words as a Back-Cover Text, to the end of the list of Cover Texts in the Modified Version. Only one passage of Front-Cover Text and one of Back-Cover Text may be added by (or through arrangements made by) any one entity. If the Document already includes a cover text for the same cover, previously added by you or by arrangement made by the same entity you are acting on behalf of, you may not add another ; but you may replace the old one, on explicit permission from the previous publisher that added the old one. The author(s) and publisher(s) of the Document do not by this License give permission to use their names for publicity for or to assert or imply endorsement of any Modified Version.

9.5 Combining Documents

You may combine the Document with other documents released under this License, under the terms defined in section 4 above for modified versions, provided that you in-

La programmation reseau.´

Deuxieme`

partie

La programmation reseau.´ Deuxieme` partie

clude in the combination all of the Invariant Sections of all of the original documents, unmodified, and list them all as Invariant Sections of your combined work in its license notice. The combined work need only contain one copy of this License, and multiple identical Invariant Sections may be replaced with a single copy. If there are multiple Invariant Sections with the same name but different contents, make the title of each such section unique by adding at the end of it, in parentheses, the name of the original author or

publisher of that section if known, or else a unique number. Make the same adjustment to the section titles in the list of Invariant Sections in the license notice of the combined work.

In the combination, you must combine any sections entitled “History” in the various

original documents, forming one section entitled “History” ; likewise combine any sec-

tions entitled “Acknowledgements”, and any sections entitled “Dedications”. You must delete all sections entitled “Endorsements.”

9.6 Collections of Documents

You may make a collection consisting of the Document and other documents released under this License, and replace the individual copies of this License in the various docu- ments with a single copy that is included in the collection, provided that you follow the rules of this License for verbatim copying of each of the documents in all other respects. You may extract a single document from such a collection, and distribute it indivi- dually under this License, provided you insert a copy of this License into the extracted document, and follow this License in all other respects regarding verbatim copying of that document.

9.7 Aggregation With Independent Works

A compilation of the Document or its derivatives with other separate and independent

documents or works, in or on a volume of a storage or distribution medium, does not as a whole count as a Modified Version of the Document, provided no compilation copyright

is claimed for the compilation. Such a compilation is called an “aggregate”, and this Li- cense does not apply to the other self-contained works thus compiled with the Document, on account of their being thus compiled, if they are not themselves derivative works of the Document.

If the Cover Text requirement of section 3 is applicable to these copies of the Docu-

ment, then if the Document is less than one quarter of the entire aggregate, the Docu- ment’s Cover Texts may be placed on covers that surround only the Document within the aggregate. Otherwise they must appear on covers around the whole aggregate.

9.8 Translation

Translation is considered a kind of modification, so you may distribute translations of the Document under the terms of section 4. Replacing Invariant Sections with translations requires special permission from their copyright holders, but you may include translations of some or all Invariant Sections in addition to the original versions of these Invariant Sections. You may include a translation of this License provided that you also include the

La programmation reseau.´

Deuxieme`

partie

La programmation reseau.´ Deuxieme` partie

original English version of this License. In case of a disagreement between the translation and the original English version of this License, the original English version will prevail.

9.9 Termination

You may not copy, modify, sublicense, or distribute the Document except as expressly provided for under this License. Any other attempt to copy, modify, sublicense or distri- bute the Document is void, and will automatically terminate your rights under this Li- cense. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.

9.10 Future Revisions of This License

The Free Software Foundation may publish new, revised versions of the GNU Free Documentation License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. See http ://www.gnu.org/copyleft/. Each version of the License is given a distinguishing version number. If the Document specifies that a particular numbered version of this License ”or any later version” applies to it, you have the option of following the terms and conditions either of that specified version or of any later version that has been published (not as a draft) by the Free Software Foundation. If the Document does not specify a version number of this License, you may choose any version ever published (not as a draft) by the Free Software Foundation.

ADDENDUM : How to use this License for your documents

To use this License in a document you have written, include a copy of the License in the document and put the following copyright and license notices just after the title page :

Copyright c YEAR YOUR NAME. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documenta- tion License, Version 1.1 or any later version published by the Free Software Foundation ; with the Invariant Sections being LIST THEIR TITLES, with the Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST. A copy of the license is included in the section entitled “GNU Free Documenta- tion License”.

If you have no Invariant Sections, write “with no Invariant Sections” instead of saying which ones are invariant. If you have no Front-Cover Texts, write “no Front-Cover Texts” instead of “Front-Cover Texts being LIST” ; likewise for Back-Cover Texts. If your document contains nontrivial examples of program code, we recommend re- leasing these examples in parallel under your choice of free software license, such as the GNU General Public License, to permit their use in free software.

La programmation reseau.´

Deuxieme`

partie

La programmation reseau.´ Deuxieme` partie

Ref´ erences´

[1] http ://www.whitefang.com/rin/