Réseaux

Réseaux et algortihmique - Correction

1. Calculs dans un sous-réseau

Adresse du sous-réseau

  1. En binaire = 192.168.1.24 = 11000000.10101000.00000001.00011000, et : 255.255.255.0 = 11111111.11111111.11111111.00000000
    → ET logique entre les deux valeurs :
    
    		11000000.10101000.00000001.00011000
    	ET	11111111.11111111.11111111.00000000
    	=	11000000.10101000.00000001.00000000 soit : 192.168.1.0, qui est bien l'adresse du sous-réseau.	
    					
    ( cela s'explique en remarquant que le ET logique ne "conserve" que les bits de l'IP de même position que ceux à 1 du masque; les autres bits de l'IP sont eux "forcés à zéro" par les bits à 0 du masque...)
  2. Proposition de script pour la fonction :
    
    def sous_reseau(ip, masque):
    	"""
    		Fonction pour déterminer l'adresse d'un sous-réseau à partir d'une IP et du masque de sous-réseau
    		
    		Entrée : 2 chaînes de caractères représentant l'IP et le masque sous la forme XXX.XXX.XXX.XXX
    		Sortie : une chaîne de caractère représentant l'adresse du sous-réseau sous la même forme
    	"""
    	
    	ip = ip.split('.') # séparation dans une liste des 4 octets de l'IP
    	masque = masque.split('.') # séparation dans une liste des 4 octets du masque; attention ces deux listes contiennent encore des chaînes, pas des nombres !
    	
    	sr = "" # chaîne vide qui contiendra l'adresse du sous-réseau
    	
    	for i in range(0,4): # pour chacun des 4 octets de l'IP et du masque
    		et = int(ip[i]) & int(masque[i]) # opération ET logique entre les octets de même position après leur transtypage en entier
    		sr += str(et) + '.' # ajout de l'octet calculé ( après transtypage en chaîne ) à la chaîne 'sr'
    	
    	return sr			
    					
  3. Le programme principal ( appel de la fonction et affichage de l'adresse ) peut se faire sous cette forme :
  4. 
    def sous_reseau(ip, masque):
    
    	.............
    	
    	return sr
    	
    ip = input("Entrez l'IPv4 sous la forme : XXX.XXX.XXX.XXX : ")
    masque = input("Entrez le masque sous la même forme : ")
    
    print("L'adresse du sous-réseau est :", sous-reseau(ip,masque)) # apppel de la fonction et affichage du résultat	
    					

Adresse de diffusion

  1. Complément à 1 du masque :
    
    		11111111.11111111.11111111.00000000
    	XOR	11111111.11111111.11111111.11111111
    	=	00000000.00000000.00000000.11111111	qui correspond bien à tous les bits du masque inversés, soit : 0.0.0.255					
    								
    				
  2. OU logique entre l'IP et le complément à 1 du masque :
    
    		11000000.10101000.00000001.00011000
    	OU	00000000.00000000.00000000.11111111
    	=	11000000.10101000.00000001.11111111	 soit 192.168.1.255 qui est bien l'adresse de diffusion.			
    					
    				
  3. Proposition de script pour la fonction :
    
    def diffusion(ip, masque):
    	"""
    		Fonction pour déterminer l'adresse de diffusion à partir d'une IP et du masque de sous-réseau
    		
    		Entrée : 2 chaînes de caractères représentant l'IP et le masque sous la forme XXX.XXX.XXX.XXX
    		Sortie : une chaîne de caractère représentant l'adresse du sous-réseau sous la même forme
    	"""
    	
    	ip = ip.split('.') # séparation dans une liste des 4 octets de l'IP
    	masque = masque.split('.') # séparation dans une liste des 4 octets du masque; attention ces deux listes contiennent encore des chaînes, pas des nombres !
    	
    	for i in range(0,4): # pour chaque octet du masque
       	masque[i] = int(masque[i]) ^ 255 # calcul de son complément à 1 en faisant un OU EXCLUSIF entre l'octet ( transtypé en entier ) et 255
    	
    	diff = "" # chaîne vide qui contiendra l'adresse de diffusion
    	
    	for i in range(0,4): # pour chacun des 4 octets de l'IP et du complément à 1 du masque
    		ou = int(ip[i]) | masque[i] # opération OU logique entre les octets de même position après transtypage en entier ( sauf pour les éléments de la liste masque[], qui ont déja été précédemment transtypés )
    		diff += str(ou) + '.' # ajout de l'octet calculé ( après transtypage en chaîne ) à la chaîne 'sr'
    	
    	return diff			
    					

2. Décodage d'une trame Ethernet

Extraction des données du fichier :

Il fallait suivre les opérations suivantes :


def extraire_octets(fichier) :
	""" extraction des octets depuis un fichier texte représentant une trame
		Dans le fichier, les octets sont organisés en ligne de 8 octets.
	
		Entrée : le chemin vers le fichier .txt
		Sortie : la liste des octets ( un octet par élément de la liste, sous forme de chaîne de caractère)
	"""
	
	f = open(fichier, 'r') # ouverture du fichier
	
	liste_octets = [] # liste qui contiendra les octets
	
	for ligne in f: # pour chaque ligne du fichier
		ligne = ligne.rstrip('\n') # retrait du caractère de fin de ligne
	
		ligne = ligne.split(' ') # séparation des octets; on obtient la liste des 8 octets de la ligne
	
		liste_octets.extend(ligne) # ajout en fin de la liste des 8 octets d'une ligne
	
		f.close()

	return liste_octets		
			

A la ligne 19, c'est bien la fonction extend() ( = extension d'une liste avec une autre liste ) que l'on utilise, et pas append() ( = ajout d'un élément en fin de liste ) : dans ce dernier cas, les 8 octets auraient été ajoutés comme nouvel élément de la liste principale, qui aurait alors été une liste de listes !!

Décodage de la trame

Il faut déterminer "où" dans la liste des octets se trouvent les informations recherchées; ceci connu, il suffit d'extraire ces octets :


def analyse_trame(liste_octets):

    #COUCHE LIAISON

    en_tete = [liste_octets[i] for i in range(0,15)] # extraction de l'en-tête dans une sous-liste

    mac_destination = [en_tete[i] for i in range(0,6)] # = octets 0 à 5
    mac_source = [en_tete[i] for i in range(6,12)] # = octets 6 à 11
    type = en_tete[12]+en_tete[13] # = octets 12 et 13

    print("MAC destination", ':'.join(mac_destination))
    print("MAC source : ", ':'.join(mac_source))

    donnees = [liste_octets[i] for i in range(14, len(liste_octets)-4)] # on ne garde que les octets de données de la couche suivante ( retrait des 14 octets d'en-tête + 4 octets à la fin )

    # COUCHE RESEAU

    octet_1 = donnees[0] # extraction 1er octet qui contient l'information sur la vrsion IP ( 4 premiers bits ) et la taille de l'en-tête ( 4 derniers bits )

    ip = octet_1[0] # type IP = 4 premiers bits de l'octet 0, donc 1er caractère de la chaîne représentant l'octet
    blocs = octet_1[1] # nbre de blocs constituant l'en-tête = 4 derniers bits de l'octet 0, donc 2ème caractère de la chaîne représentant l'octet

    taille_entete = (int('0x'+blocs,16)*32)//8 # conversion du nombre de blocs de l'héxadécimal vers la base 10 ( après conversion de l'héxadécimal vers la base 10 et transtypage en entier ), et calcul du nombre d'octets de l'en-tête

    en_tete = [donnees[i] for i in range(0,taille_entete)] # extraction de l'en-tête dans une sous-liste maintenant que l'on connaît la taille de l'en-tête


    ip_source = [str(int('0x'+en_tete[i],16)) for i in range(taille_entete - 8, taille_entete - 4)]
    ip_destination = [str(int('0x'+en_tete[i],16)) for i in range(taille_entete - 4, taille_entete)]

    print() # saut de ligne
    print("Version IP : IPv" + ip)
    print("IP source : ", '.'.join(ip_source))
    print("IP destination : ", '.'.join(ip_destination))

    donnees = [donnees[i] for i in range(taille_entete, len(donnees))] # on ne garde que les données de la couche suivante

    # COUCHE TRANSPORT
	 
	 octet_13 = donnees[12] # extraction 13ème octet contenant l'information sur la taille de l'en-tête 
    blocs = octet_13[0] # nbre de blocs constituant l'en-tête ( 4 premiers bits )

    taille_entete = (int('0x'+blocs,16)*32)//8 # calcul du nombre d'octets de l'en-tête
    
    en_tete = [donnees[i] for i in range(0,taille_entete)] # extraction de l'en-tête dans une sous-liste maintenant que l'on connaît la taille de l'en-tête
    
    port_source = int('0x'+en_tete[0]+en_tete[1],16)
    port_destination = int('0x'+en_tete[2]+en_tete[3],16)

    print()
    print("Port source : ", port_source)
    print("Port destination : ", port_destination)

    donnees = [donnees[i] for i in range(taille_entete, len(donnees))] # on ne garde que les données de la couche suivante

    # COUCHE APPLICATION

    print()
    for octet in donnees :
        if (octet != '0d'):
            print(chr(int('0x'+octet,16)), end = '') # conversion du code ASCII vers le caractère correspondant ( après conversion de l'héxadécimal vers la base 10 et transtypage en entier )