Réseaux
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...)
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
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
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
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.
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
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 !!
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 )
for
même si
le code perd peut-être un peu en lisibilité.0x0d
est un caractère "non-imprimable" ( CR = "retour chariot" ); son affichage conduit à une suppression du caractère suivant, on évite donc de le faire.0x0a
( LF = saut de ligne ), caractère lui aussi non-imprimable mais que l'on doit bien afficher pour provoquer un retour à la ligne.