Advertisement
Guest User

Untitled

a guest
Jan 22nd, 2020
92
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 12.47 KB | None | 0 0
  1. #! /usr/bin/env  python
  2. # -*- coding: utf-8 -*-
  3.  
  4. """
  5. Script in python for the project in CPL.
  6. Date: 27.12.2019
  7. Last modification: 21.01.2020
  8. Author: Michael da Silva & Nenad Rajic
  9. Version Python: 2.7.15+
  10. Version script: 0.4.3
  11. """
  12.  
  13. from scapy.all import *
  14.  
  15. OWN_ADDR = "0101" #Unicast address of the user
  16. MULTI_ADDR = "1011" #Multicast address of the user
  17. BROADCAST = "1111" #Broadcast address
  18. SIZE_ROW = 7
  19. SIZE_COLUMN = 6
  20. SIZE_ADDR = 4 #Size of destination and source address
  21. MAX_INT_42_BITS = 4398046511103
  22. BITS_FOR_SIZE = 6
  23.  
  24. """
  25. Crée un payload contenant des bits aléatoires (juqu'à 42 bits)
  26. """
  27. def RandomPayload():
  28.     number = random.randint(0, MAX_INT_42_BITS)
  29.     number = "{0:b}".format(number) # Transforme un integer en chiffre binaire
  30.     return number
  31. """
  32. Corrige le bit érroné grâce au numéro de ligne et numéro de colonne
  33. """
  34. def CorrectErrorPayload(bits, row, column):
  35.     bits_corrected = bits
  36.     bits_corrected[(row*(SIZE_ROW+1)) + column] = 0 if bits[(row*(SIZE_ROW+1)) + column] else 1
  37.     print("Error corrected")
  38.     return bits_corrected
  39. """
  40. Ajoute des bits de bourrage au payload s'il n'a pas assez de bits (42 bits de data demandé)
  41. 56 bits -> sans les bits de parité -> 42 bits
  42. retourne une liste (tableau)de int
  43. """
  44. def FillPayload(payload):
  45.     while len(payload) != SIZE_ROW * SIZE_COLUMN:
  46.         payload.append(0)
  47.     return payload
  48. """
  49. Transforme une liste de int en une chaîne de caractère
  50. Prends une string vide puis join des caractères tableau de i (bits) convertits en string [1,2,3,4] -> 1234
  51. """
  52. def BinaryToString(frame):
  53.     s = ''.join([str(i) for i in frame])
  54.     return s
  55. """
  56. Transforme une chaîne de caractère en liste de integer
  57. convertire des strings en map -> conversion en int, transformer en liste car on veut pas de map
  58. """
  59. def StringToBinary(frame):
  60.     int_array = list(map(int, frame))
  61.     return int_array
  62. """
  63. Retourne en binaire la longueur réelle d'un payload (sans bit de bourrage)
  64. """
  65. def PayloadSize(length):
  66.     binary = "{0:b}".format(length)
  67.     while len(binary) != BITS_FOR_SIZE:
  68.         binary = "0" + binary
  69.     return binary
  70. """
  71. Vérifie les parités du payload
  72. """
  73. def HVParityCheck(payload):
  74.     matrix = []
  75.     errors_row = []
  76.     errors_column = []
  77.    
  78.     while payload: # Création d'une matrice pour faciliter la vérification
  79.         matrix.append(payload[:(SIZE_ROW + 1)])
  80.         payload = payload[(SIZE_ROW + 1):]
  81.    
  82.     for i in range(len(matrix)):
  83.         if SimpleParityCheck(matrix[i]): # Vérification des parités horizontales
  84.             errors_row.append(i)
  85.  
  86.     for j in range(len(matrix[0])):
  87.         column = [] # Création d'une colomne pour la vérification des parités verticales
  88.         for i in range(len(matrix)):
  89.             column.append(matrix[i][j])
  90.         if SimpleParityCheck(column):
  91.             errors_column.append(j)
  92.    
  93.     if len(errors_row) > 1 or len(errors_column) > 1:
  94.         print("Error in data. Can't correct it (2-3 bits error or 8 bits burst)")
  95.         return [-1]
  96.     elif len(errors_row) == 1 & len(errors_column) == 1:
  97.         print("1 error to correct")
  98.         return [errors_row[0], errors_column[0]] # Renvoie des numéros de ligne et colomne
  99.     else:
  100.         print("No error detected")
  101.         return []
  102. """
  103. Calcule les parités verticales et horizontales pour le payload
  104.  
  105. """
  106. def HVParityCalculate(payload):
  107.     result = []
  108.     matrix = []
  109.    
  110.     for i in range(SIZE_COLUMN):
  111.         matrix.append(SimpleParityCalculate(payload[i*SIZE_ROW:(i+1)*SIZE_ROW])) # Calcul des parités horizontales i+1 pour prendre toute la ligne
  112.    
  113.  
  114.     parity_line = []
  115.     parity = 0
  116.    
  117.     for i in range(SIZE_ROW):
  118.         for row in matrix:
  119.             parity += row[i] # Calcul de la dernière ligne contenant les parités verticales
  120.         parity_line.append(parity % 2)
  121.         parity = 0
  122.    
  123.     matrix.append(SimpleParityCalculate(parity_line)) # Calcul de la parité de la dernière ligne
  124.     result = [bit for row in matrix for bit in row] # Transformation de la matrice en tableau à une dimension
  125.     return result
  126. """
  127. Enlève les bits de parité du payload et le renvoie nettoyé
  128. """
  129. def CleanPayload(payload):
  130.     payload_cleaned = []
  131.  
  132.     for i in range(SIZE_COLUMN):
  133.         payload_cleaned.append(payload[:(SIZE_ROW)]) # Nouveau payload sans bit de parité
  134.         payload = payload[(SIZE_ROW + 1):]
  135.     result = []
  136.     for i in payload_cleaned: # Nouvelle liste des bits
  137.         for j in i:
  138.             result.append(j)
  139.    
  140.     return result
  141. """
  142. Vérifie la parité d'une trame donnée et renvoie si la parité est juste ou non
  143. """
  144. def SimpleParityCheck(frame):
  145.     parity_to_check = frame[-1]
  146.     parity = 0
  147.    
  148.     for i in frame[:-1]:
  149.         parity += i
  150.  
  151.     parity %= 2
  152.  
  153.     if parity_to_check == parity:
  154.         return 0
  155.     else:
  156.         return -1
  157. """
  158. Calcule la parité d'une trame donnée et renvoie la trame contenant la parité
  159. addition des bits puis ajout d'un bit à la fin du total%2
  160. """
  161. def SimpleParityCalculate(frame):
  162.     frame_with_parity = frame
  163.    
  164.     total = 0
  165.     for i in frame:
  166.         total += i
  167.  
  168.     frame_with_parity.append(total % 2)
  169.     return frame_with_parity
  170. """
  171. Envoie automatiquement une payload avec l'adresse de destination, l'adresse source et la longueur du payload (permet d'enlever les bits de bourrage)
  172. """
  173. def SendFrameAutom(destination, payload):
  174.     length = 0
  175.     destination = StringToBinary(destination)
  176.     source = StringToBinary(OWN_ADDR)
  177.     payload = StringToBinary(payload)
  178.    
  179.     if len(payload) < SIZE_ROW * SIZE_COLUMN:
  180.         length = len(payload)
  181.         print("Payload too small")
  182.         print("Bits filling...")
  183.         payload = FillPayload(payload) # Bourrage du payload si bits manquant (n'atteint pas la taille de 42 bits)
  184.         print("Done!")
  185.     elif len(payload) == (SIZE_ROW * SIZE_COLUMN):
  186.         length = SIZE_ROW * SIZE_COLUMN
  187.  
  188.     length = PayloadSize(length) # Taille du payload en binaire
  189.     length = SimpleParityCalculate(StringToBinary(length))
  190.    
  191.     print("Calculating the parity of destination address...")
  192.     destination = SimpleParityCalculate(destination) # Calcul de la parité de l'adresse de destination
  193.     print("Done!")
  194.     print("Calculating the parity of source address...")
  195.     source = SimpleParityCalculate(source) # Calcul de la parité de l'adresse source
  196.     print("Done!")
  197.     print("Calculating the parity of payload...")
  198.     payload = HVParityCalculate(payload) # Calcul de les parités du payload
  199.     print("Done!")
  200.     # Transformation des informations de binaire à chaîne de caractère (pour la fonction SendFrame)
  201.     destination = BinaryToString(destination)
  202.     source = BinaryToString(source)
  203.     length = BinaryToString(length)
  204.     payload = BinaryToString(payload)
  205.    
  206.     print("Sending packet...")
  207.     SendFrame(destination, source, length, payload)
  208. """
  209. Reçoit un paquet et retire les informations telle que l'adresse de destination, l'adresse source, la longueur du payload et le payload
  210. """
  211. def ReceiveFrameAutom(packet):
  212.     if packet.load[:SIZE_ADDR] == OWN_ADDR or packet.load[:SIZE_ADDR] == MULTI_ADDR or packet.load[:SIZE_ADDR] == BROADCAST: # Vérification de l'adresse de destination
  213.         print("Packet received with one of the valid addresses")
  214.         destination = packet.load[:(SIZE_ADDR+1)]
  215.         source = packet.load[(SIZE_ADDR+1):(SIZE_ADDR+1)*2]
  216.         length = packet.load[(SIZE_ADDR+1)*2:((SIZE_ADDR+1)*2)+(BITS_FOR_SIZE+1)]
  217.         payload = packet.load[((SIZE_ADDR+1)*2)+(BITS_FOR_SIZE+1):]
  218.        
  219.         print("Checking parity of the destination address...")
  220.         test_dst = SimpleParityCheck(StringToBinary(destination)) # Test de la parité de l'adresse de destination
  221.    
  222.         if test_dst:
  223.             print("Error in destination, packet dropped")
  224.             return
  225.         else:
  226.             print("Destination correct!")
  227.             destination = destination[:-1]
  228.  
  229.         test_src = SimpleParityCheck(StringToBinary(source)) # Test de la parité de l'adresse source
  230.         if test_src:
  231.             print("Error in destination, packet dropped")
  232.             return
  233.         else:
  234.             print("Destination correct!")
  235.             source = source[:-1]
  236.  
  237.         test_size = SimpleParityCheck(StringToBinary(length)) # Test de la parité de la taille du payload
  238.         if test_size:
  239.             print("Error in size of payload, packet dropped")
  240.             return
  241.         else:
  242.             length = length[:-1]
  243.  
  244.         print("Checking parity of the payload...")
  245.         test_payload = HVParityCheck(StringToBinary(payload)) # Test des parités du payload
  246.        
  247.         if len(test_payload) == 1: # Rejette le paquet s'il y a plus d'une erreur dans le payload
  248.             return
  249.         elif len(test_payload) == 2:
  250.             payload = CorrectErrorBinary(payload, test_payload[0], test_payload[1])
  251.        
  252.         print("Cleaning the payload from the parity bits...")
  253.         payload = BinaryToString(CleanPayload(payload))
  254.         print("Done!")
  255.  
  256.         payload = payload[:int(length, 2)] # Le payload ne garde que les bits d'information reçu, pas les bits de bourrage
  257.    
  258.         print("\n\n----------Packet received----------\n")
  259.         print("Destination: " + destination)
  260.         print("Source: " + source)
  261.         print("Payload: " + payload)
  262.         print("\n-----------------------------------\n\n")
  263. """
  264. Envoie une trame via le protocole Ethernet en broadcast (notre protocole gère les adresses de destination)
  265. adresse source/dest , logueure payload et payload (longeur pour enlver les bits de bourrage)
  266. """
  267. def SendFrame(destination, source, length, payload):
  268.     data = destination + source + length + payload
  269.     sendp(Ether(dst="ff:ff:ff:ff:ff:ff")/data) # adresse dest et payload = data, on simplfiie en envoyant en broadast
  270.     #On utilise le broadcast afin de simplifier le protocole car addressage sur 4 bits, donc verification des 4 premiers bits pour voir si le paquet nous est destiné
  271. """
  272. Permet de voir les paquets envoyé sur le réseau et de récupérer ceux ayant comme destinataire l'adresse de broadcast
  273. Tout les paquets ethernet a destination de broadcast sont récupéré -> puis envoyer a la fonction ReceiveFrameAutom
  274. """
  275. def Sniff():
  276.     sniff(filter = "ether dst ffffffffffff", prn = ReceiveFrameAutom) # Renvoi du paquet capturé à la fonction ReceiveFrameAutom
  277. """
  278. Fonction main du script avec quelques tests
  279. """
  280. def Main():
  281.     print("Receive(r) or Send(s) ?: ")
  282.     choice = raw_input()
  283.  
  284.     if choice == "s":
  285.         while 1:
  286.             print("Destination: ")
  287.             dest = raw_input()
  288.             print("Data (if you type enter without data, a random one is created): ")
  289.             data = raw_input()
  290.            
  291.             if not len(data):
  292.                 data = RandomPayload()
  293.             SendFrameAutom(dest, data)
  294.     elif choice == "r":
  295.         Sniff()
  296.  
  297.     # Test pour la détection et correction d'erreur
  298.     """
  299.    data = "00000000000000000000000000000000000000000000000000000000"
  300.    data_1error = "00000000000000000000000000000010000000000000000000000000"
  301.    data_2errors = "00000000000000000000000000000000000010100000000000000000"
  302.    data_3errors = "00000000000000000001011000000000000000000000000000000000"
  303.    data_8burst = "00000000000001000000100000000000000000000000000000000000"
  304.  
  305.    print(data_1error)
  306.    test = HVParityCheck(StringToBinary(data_1error))
  307.    if len(test) == 2:
  308.        payload = CorrectErrorPayload(StringToBinary(data_1error), test[0], test[1])
  309.        print(BinaryToString(payload))
  310.    elif len(test) == 1:
  311.        return
  312.    """
  313.     # Test pour le calcul de parité simple et vérification
  314.     """
  315.    data = "10010"
  316.    test = SimpleParityCalculate(StringToBinary(data))
  317.    print(BinaryToString(test))
  318.    if SimpleParityCheck(test) < 0:
  319.        print("Error in parity")
  320.    else:
  321.        print("Parity correct")
  322.    """
  323.     # Test pour le calcul et la vérification des parités d'un payload
  324.     """
  325.    data = RandomPayload()
  326.    print(data)
  327.     data = FillPayload(data)
  328.    test = HVParityCalculate(StringToBinary(data))
  329.    print(BinaryToString(test))
  330.    HVParityCheck(test)
  331.    """
  332.     # Test pour le calcul de la taille réelle d'un payload (aucun bit de bourrage)
  333.     """
  334.    data = "100101"
  335.    length = len(data)
  336.    data = BinaryToString(FillPayload(StringToBinary(data)))
  337.    print(data)
  338.    length = PayloadSize(length)
  339.    data = data[:int(length, 2)]
  340.    print(data)
  341.    """
  342. Main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement