Previous Contents Next

14   Corrigé du DS du 16 janvier 2004

14.1   Auteurs

Les responsables d'une éventuelle hécatombe sont Thomas Vantroys et Xavier Redon.

14.2   Détails pratiques

La durée de ce contrôle sur machine est de deux heures, les communications avec des personnes autres que les surveillants sont interdites.

Le barème probable est de 6 points pour le premier exercice et de 14 points pour le second exercice.

Les résultats (réponses aux questions et programme) doivent être envoyés par messagerie à Xavier.Redon@polytech-lille.fr. Il est conseillé d'envoyer une copie de ce message sur votre compte de messagerie. Utilisez des fichiers au format ASCII si vous souhaitez attacher des documents à votre "copie électronique".

14.3   Questions sur le tutorat

Répondez aux questions suivantes relatives à votre programme de résolution de noms écrit en tutorat réseau et à quelques connaissances de base sur IPv6 :
  1. Lorsque l'on cherche à trouver le nom DNS correspondant à l'adresse IPv6 2001:5c0:0:1::2, quel type d'enregistrement DNS (appelé en anglais Ressource Record ou RR en abrégé) utilise-t-on ?
    On utilise le RR PTR (pour Pointer en patoi) qui "pointe" sur le nom hiérarchique de la machine. On constate que la question comporte comme d'habitude un nom hiérarchique (les niveaux étant séparés par des points) ; ici c'est l'adresse inversée de la machine. Par contre la réponse n'est pas de type adresse IP mais de type chaîne de caractère. Je sais que vous vous moquez de ces précisions mais ça me fait plaisir de les écrire ...
  2. Pourrait-on écrire l'adresse IPv6 de la première question sous une forme encore plus condensée comme 2001:5c0::1::2 ? pourquoi ?
    Non ce n'est pas possible, comme me l'a si bien dit l'un ou l'une d'entre vous "la notation avec plusieurs :: ne garantie pas l'unicité de l'adresse". En effet, dans ce cas, il n'est pas toujours possible de connaitre le nombre de mots de 32 bits à zéro représentés par un "::".
  3. On cherche toujours à trouver le nom correspondant à l'adresse IPv6 de la première question. Donnez le nom hiérarchique, correspondant à cette adresse IPv6, que le client DNS va utiliser pour interroger le serveur DNS (sous la forme d'une chaîne de caractères, pas sous la forme binaire demandée par le protocole DNS).
    Le nom hiérarchique est :
    2.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1.0.0.0.0.0.0.0.0.c.5.0.1.0.0.2.ip6.arpa
    Il est aussi possible d'utiliser
    2.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1.0.0.0.0.0.0.0.0.c.5.0.1.0.0.2.ip6.int
  4. Après ces quelques digressions, revenons à nos moutons : quel est le nom de la machine dont l'adresse IPv6 est donné dans la première question ?
    En utilisant votre client DNS ou la commande host, vous trouvez sonata.hexago.com.
  5. La machine de votre directeur de département bien-aimé s'appelle naiade (à la fois dans l'ancien domaine eudil.fr et dans le nouveau domaine escaut.net). Cette machine dispose d'une adresse IPv6 automatique, donnez-nous son adresse Ethernet (je répète pour les incrédules : son adresse Ethernet).
    Il suffit de trouver l'adresse IPv6 de naiade, pour cela on peut utiliser la commande host -t aaaa naiade.escaut.net. On trouve l'adresse
    2001:660:4401:6003:2b0:d0ff:fe0c:d4f9
    Puisqu'il s'agit d'une adresse IPv6 automatique les 64 bits de poids faible (L'EUI-64) sont construits à partir de l'adresse MAC (Ethernet) de la machine. En remettant le bit d'unicité à 0 (conflit de signification de ce bit entre un EUI-64 et une adresse Ethernet) et en supprimant le mot fffe on obtient : 00:b0:0f:0c:d4:f9. Vous pouvez demander confirmation à votre directeur bien-aimé.

14.4   Exercice de programmation UDP

Polytech'Lille vient de mettre en place un service révolutionnaire de calculatrice deux fonctions à l'adresse picardie:4000. Ce service, qui fonctionne en UDP, utilise le format de trame présenté à la figure ci-dessous :


Le champ Type de message sur un octet indique si le message est une demande de calcul (type = 0) ou une réponse à une demande de calcul (type = 1). Le champ opération, sur un octet, permet d'indiquer le type de calcul à réaliser. Pour l'instant, le service ne dispose que de l'addition (opération = 0) et la multiplication (opération = 1). Nous trouvons ensuite le premier nombre sur deux octets, puis le second nombre sur deux octets également. Enfin, nous avons le résultat sur quatre octets.

Votre mission est de réaliser un client permettant d'envoyer des demandes de calculs puis ensuite d'afficher le résultat.

Exemple de fonctionnement:
$> superCalculatrice multiplication 12 27
   Le résultat est 324
$> superCalculatrice addition 1 34
   Le résultat est 35
Voici un exemple de client acceptable :
/** Client de la calculatrice à deux opérations **/

/* Fichiers d'inclusion */

#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>

/* Constantes */

#define SERVEUR        "172.26.16.11"
#define PORT           4000
#define TAILLE_PAQUET  10

/* Fonctions */

int initSocket(int port, char *adresse, struct sockaddr_in *addr)
{
int sd;

if ( (sd=socket(PF_INET, SOCK_DGRAM, 0)) < 0 )
{ perror("initSocket.socket\n"); return -1; }
bzero(addr, sizeof(*addr));
addr->sin_family = AF_INET;
addr->sin_port = htons(port);
if ( inet_aton(adresse, &addr->sin_addr) == 0 )
{ perror("initSocket.inet_aton\n"); return -1; }

return sd;
}

/* Fonction principale */

int main(int argc, char* argv[])
{
int sd;                                /* Descripteur de socket */
struct sockaddr_in adresse;            /* Adresse au sens socket du serveur */
int taille=sizeof adresse; 
char *operation;                       /* Opération à effectuer */
int op1,op2;                           /* Opérandes */
unsigned char question[TAILLE_PAQUET]; /* Paquet à envoyer au serveur */
unsigned char reponse[TAILLE_PAQUET];  /* Paquet reçu du serveur */

/* Analyse des arguments */
if(argc!=4){
  fprintf(stderr,"Syntaxe : %s addition|multiplication op1 op2\n",argv[0]);
  exit(-1);
  }
operation=argv[1];
if(strcmp(operation,"multiplication")!=0 && strcmp(operation,"addition")!=0){
  fprintf(stderr,"Opération non implantée pour l'instant\n");
  exit(-1);
  }
op1=atoi(argv[2]);
op2=atoi(argv[3]);

/* Préparation de l'adresse du serveur */
if((sd=initSocket(PORT,SERVEUR,&adresse))<0){
  fprintf(stderr,"Impossible de contacter le serveur %s\n",SERVEUR);
  exit(-1);
  }

/* Préparation de la question */
question[0]=0x0;
question[1]=strcmp(operation,"addition")==0?0x0:0x1;
question[2]=op1>>8;
question[3]=op1&0xff;
question[4]=op2>>8;
question[5]=op2&0xff;

/* Envoi du paquet au serveur */
if(sendto(sd,question,TAILLE_PAQUET,0,(struct sockaddr*)&adresse,taille)<0){
  perror("main.sendto\n");
  return -1;
  }

/* Réception de la réponse */
if(recvfrom(sd,reponse,TAILLE_PAQUET,0,NULL,0)<0){
  perror("main.recvfrom\n");
  return -1;
  }

/* Affichage du résultat */
fprintf(stdout,"Le résultat est : %lu\n",
               reponse[6]<<24|reponse[7]<<16|reponse[8]<<8|reponse[9]);

exit(0);
}

Previous Contents Next