1 Description générale du projet
1.1 Objectif
L'objectif du projet est de réaliser un micro serveur Web permettant d'afficher des
informations sur les clients qui s'y connectent. Le programme doit être écrit en C.
1.2 Serveur TCP
Commencez par réaliser un serveur TCP double pile IPv4/IPv6. Dans un couple de fichiers
socket.c et socket.h écrivez les fonctions permettant d'implanter un serveur
TCP. Les prototypes de ces fonctions pourraient être les suivants.
int initialisationServeur(short int *port,int connexions);
int boucleServeur(int ecoute,int (*traitement)(int));
int socketVersNom(int ds,char *nom);
Utilisez ces fonctions dans un autre fichier C contenant la fonction principale.
Le but est de réaliser un serveur TCP écoutant sur un port 80XX qui affiche
le nom de la machine à partir de laquelle le client se connecte, qui transmet un
message de bienvenue au client puis qui se deconnecte. Il vous est proposé de nommer
le fichier C de la fonction principale yakari.c (attention double référence
culturelle). Pendant que vous y êtes, écrivez donc un fichier Makefile pour
compiler les deux fichiers et générer l'exécutable yakari.
1.3 Serveur Web
Ecrivez quelques fonctions permettant de gérer le protocole HTTP. C'est à dire
permettant de lire la commande, de lire les entêtes, d'écrire le code de
réponse et d'écrire les entêtes de la réponse. Une fonction permettant de trouver la
valeur d'une entête donnée pourrait aussi être utile. Ces fonctions sont à
coder dans le couple de fichiers http.c et http.h. Utilisez les dans
la fonction de gestion des clients pour réaliser un serveur web avec les caractéristiques
suivantes :
-
Les seules commandes implantées sont GET et HEAD.
- Les protocoles reconnus sont HTTP/1.0 et HTTP/1.1.
- La page retournée est la même quelque soit l'URL utilisée.
- Sur la page donnez simplement le contenu des entêtes User-Agent et X-Forwarded-For.
- Dans les entêtes de réponse fournissez les entêtes Content-type, Date et Server.
1.4 Adresses IP et noms de machines
En vous basant sur le code de la fonction socketVersNom et sur le contenu de l'entête
X-Forwarded-For, récupérez les informations suivantes :
-
Adresse IP du serveur utilisée par le client pour se connecter (voir la fonction getsockname).
- Eventuellement le nom DNS correspondant à l'adresse IP du serveur.
- Adresse IP du client se connectant au serveur. Attention si l'entête X-Forwarded-For est
présente sa valeur donne l'adresse IP du client. Dans le cas contraire l'adresse IP est a récupérer
par la fonction getpeername.
- Eventuellement le nom DNS correspondant à l'adresse IP du client.
- Adresse IP du mandataire Web (proxy web). Attention cette adresse ne peut être récupérée que si
l'entête X-Forwarded-For est présente. Dans ce cas l'adresse IP du mandataire est donnée
par la fonction getpeername.
Vous devez traiter les adresses IPv4 et les adresses IPv6. Les adresses IPv6 de type équivalent IPv4
doivent être affichées comme des adresses IPv4 pures (utilisez la macro IN6_IS_ADDR_V4MAPPED pour
les détecter). Insérez ces adresses et noms sur la page retournée par le serveur Web.
1.5 Bases Whois
Utilisez les bases de données Whois pour trouver des informations sur l'adresse IP du client TCP et sur
le nom de domaine du même client. Pour pouvoir récupérer ces informations il faut rajouter deux fonctions
dans le couple de fichiers socket.c et socket.h. En voici les prototypes :
int connexionServeur(char *hote,int port);
int nomVersAdresse(char *hote,void *adresse,int type);
Les bases Whois écoutent sur le port TCP 43. Commencez par contacter la base whois.iana.org
puis récupérez la valeur du champ refer: qui vous redirige vers un autre serveur Whois. Ainsi de
suite jusqu'à tomber sur une base qui ne vous redirige pas ailleurs. Le protocole Whois ne nécessite
aucune commande, il faut seulement envoyer la chaîne de caractères sur laquelle vous cherchez des
informations. Ecrivez vos fonctions de gestion des bases Whois dans le couple de fichiers whois.c
et whois.h.
Les informations Whois doivent être insérées dans la page retournée par le serveur Web. Comme il n'est
pas évident de trouver le domaine du client, partez du nom complet et lancez une requête sur tous les
suffixes de ce nom.
1.6 Tests
Faites des tests en réalisant des connexions internes et externes, en utilisant des clients IPv6 ou IPv4 et
en utilisant, ou non, un mandataire Web.