Advertisement
Guest User

myip

a guest
Nov 13th, 2019
131
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.33 KB | None | 0 0
  1. from myiputils import *
  2. from ipaddress import ip_address, ip_network
  3.  
  4. class CamadaRede:
  5.  
  6.     def __init__(self, enlace):
  7.         """
  8.        Inicia a camada de rede. Recebe como argumento uma implementação
  9.        de camada de enlace capaz de localizar os next_hop (por exemplo,
  10.        Ethernet com ARP).
  11.        """
  12.         self.callback = None
  13.         self.enlace = enlace
  14.         self.enlace.registrar_recebedor(self.__raw_recv)
  15.         self.meu_endereco = None
  16.         self.tabela_encaminhamento = {}
  17.  
  18.     def get_subnet(self, ip):
  19.         ip = ip_address(ip)
  20.  
  21.         candidatos = []
  22.  
  23.         for v, k in self.tabela_encaminhamento.items():
  24.             net = ip_network(v)
  25.             if ip in net:
  26.                 candidatos.append(net)
  27.  
  28.         while len(candidatos) > 1:
  29.             for c1 in candidatos:
  30.                 for c2 in candidatos:
  31.                     if c1 != c2:
  32.                         if c1.subnet_of(c2):
  33.                             candidatos.remove(c2)
  34.  
  35.         if len(candidatos) == 1:
  36.             return self.tabela_encaminhamento[str(candidatos[0])]
  37.  
  38.         else:
  39.             return None
  40.  
  41.     def __raw_recv(self, datagrama):
  42.         dscp, ecn, identification, flags, frag_offset, ttl, proto, \
  43.            src_addr, dst_addr, payload = read_ipv4_header(datagrama)
  44.         if dst_addr == self.meu_endereco:
  45.             # atua como host
  46.             if proto == IPPROTO_TCP and self.callback:
  47.                 self.callback(src_addr, dst_addr, payload)
  48.         else:
  49.             # atua como roteador
  50.             next_hop = self._next_hop(dst_addr)
  51.  
  52.             #header original
  53.             header = make_ipv4_header( len(payload), src_addr, dst_addr, dscp, ecn, identification, flags, frag_offset, ttl - 1, proto, True )
  54.             datagram = header + payload
  55.  
  56.             if ttl - 1 > 0:
  57.                 self.enlace.enviar(datagram, next_hop)
  58.  
  59.             #ICMP error
  60.             else:
  61.  
  62.                 #construindo novo header
  63.                 if len( payload ) > 8:
  64.                     tam_payload = 8
  65.                 else:
  66.                     tam_payload = len( payload )
  67.  
  68.                 new_header = make_ipv4_header( 28 + tam_payload , self.meu_endereco, src_addr, dscp, ecn, identification, flags, frag_offset, 64, IPPROTO_ICMP, True )
  69.  
  70.  
  71.                 discarded_header = header
  72.                 discarded_payload = payload
  73.  
  74.                 #icmp message containing the header that caused the error + 8 bytes from that message payload
  75.                 #composed of: 8 bytes from standard ICMP + 20 bytes from header that caused the error + 8 bytes from payload
  76.                 icmp_msg = make_icmp_error( discarded_header, discarded_payload )
  77.  
  78.  
  79.                 #56 bytes, 20 from new icmp header, 36 from new payload
  80.                 icmp_datagram = new_header + icmp_msg
  81.                 #icmp_datagram = datagram + icmp
  82.  
  83.                 self.enlace.enviar( icmp_datagram, next_hop )
  84.  
  85.     def _next_hop(self, dest_addr):
  86.         # TODO: Use a tabela de encaminhamento para determinar o próximo salto
  87.         # (next_hop) a partir do endereço de destino do datagrama (dest_addr).
  88.         # Retorne o next_hop para o dest_addr fornecido.
  89.         dest_addr = ip_to_bin(dest_addr)
  90.         candidatos = []
  91.         maior = 0
  92.         for hop in self.tabela:
  93.             tamanho = len(hop[0])
  94.             if dest_addr[0:tamanho] == hop[0][0:tamanho]:
  95.                 candidatos.append(hop)
  96.         for candidato in candidatos:
  97.             tamanho = len(candidato[0])
  98.             if tamanho >= maior:
  99.                 next_hop = candidato[1]
  100.                 maior = tamanho
  101.         if(candidatos):
  102.             return next_hop
  103.         else:
  104.             return None
  105.  
  106.     def definir_endereco_host(self, meu_endereco):
  107.         """
  108.        Define qual o endereço IPv4 (string no formato x.y.z.w) deste host.
  109.        Se recebermos datagramas destinados a outros endereços em vez desse,
  110.        atuaremos como roteador em vez de atuar como host.
  111.        """
  112.         self.meu_endereco = meu_endereco
  113.  
  114.     def definir_tabela_encaminhamento(self, tabela):
  115.         """
  116.        Define a tabela de encaminhamento no formato
  117.        [(cidr0, next_hop0), (cidr1, next_hop1), ...]
  118.  
  119.        Onde os CIDR são fornecidos no formato 'x.y.z.w/n', e os
  120.        next_hop são fornecidos no formato 'x.y.z.w'.
  121.        """
  122.         # TODO: Guarde a tabela de encaminhamento. Se julgar conveniente,
  123.         # converta-a em uma estrutura de dados mais eficiente.
  124.         self.tabela = [(ip_to_bin(item[0]), item[1]) for item in tabela]
  125.  
  126.  
  127.     def registrar_recebedor(self, callback):
  128.         """
  129.        Registra uma função para ser chamada quando dados vierem da camada de rede
  130.        """
  131.         self.callback = callback
  132.  
  133.     def enviar(self, segmento, dest_addr):
  134.         """
  135.        Envia segmento para dest_addr, onde dest_addr é um endereço IPv4
  136.        (string no formato x.y.z.w).
  137.        """
  138.         next_hop = self._next_hop(dest_addr)
  139.         header = make_ipv4_header( len(segmento), self.meu_endereco, dest_addr, None, None, None, None, None, 64, None, True)
  140.         datagram = header + segmento
  141.         # TODO: Assumindo que a camada superior é o protocolo TCP, monte o
  142.         # datagrama com o cabeçalho IP, contendo como payload o segmento.
  143.         self.enlace.enviar(datagram, next_hop)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement