Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- from myiputils import *
- from ipaddress import ip_address, ip_network
- class CamadaRede:
- def __init__(self, enlace):
- """
- Inicia a camada de rede. Recebe como argumento uma implementação
- de camada de enlace capaz de localizar os next_hop (por exemplo,
- Ethernet com ARP).
- """
- self.callback = None
- self.enlace = enlace
- self.enlace.registrar_recebedor(self.__raw_recv)
- self.meu_endereco = None
- self.tabela_encaminhamento = {}
- def get_subnet(self, ip):
- ip = ip_address(ip)
- candidatos = []
- for v, k in self.tabela_encaminhamento.items():
- net = ip_network(v)
- if ip in net:
- candidatos.append(net)
- while len(candidatos) > 1:
- for c1 in candidatos:
- for c2 in candidatos:
- if c1 != c2:
- if c1.subnet_of(c2):
- candidatos.remove(c2)
- if len(candidatos) == 1:
- return self.tabela_encaminhamento[str(candidatos[0])]
- else:
- return None
- def __raw_recv(self, datagrama):
- dscp, ecn, identification, flags, frag_offset, ttl, proto, \
- src_addr, dst_addr, payload = read_ipv4_header(datagrama)
- if dst_addr == self.meu_endereco:
- # atua como host
- if proto == IPPROTO_TCP and self.callback:
- self.callback(src_addr, dst_addr, payload)
- else:
- # atua como roteador
- next_hop = self._next_hop(dst_addr)
- #header original
- header = make_ipv4_header( len(payload), src_addr, dst_addr, dscp, ecn, identification, flags, frag_offset, ttl - 1, proto, True )
- datagram = header + payload
- if ttl - 1 > 0:
- self.enlace.enviar(datagram, next_hop)
- #ICMP error
- else:
- #construindo novo header
- if len( payload ) > 8:
- tam_payload = 8
- else:
- tam_payload = len( payload )
- new_header = make_ipv4_header( 28 + tam_payload , self.meu_endereco, src_addr, dscp, ecn, identification, flags, frag_offset, 64, IPPROTO_ICMP, True )
- discarded_header = header
- discarded_payload = payload
- #icmp message containing the header that caused the error + 8 bytes from that message payload
- #composed of: 8 bytes from standard ICMP + 20 bytes from header that caused the error + 8 bytes from payload
- icmp_msg = make_icmp_error( discarded_header, discarded_payload )
- #56 bytes, 20 from new icmp header, 36 from new payload
- icmp_datagram = new_header + icmp_msg
- #icmp_datagram = datagram + icmp
- self.enlace.enviar( icmp_datagram, next_hop )
- def _next_hop(self, dest_addr):
- # TODO: Use a tabela de encaminhamento para determinar o próximo salto
- # (next_hop) a partir do endereço de destino do datagrama (dest_addr).
- # Retorne o next_hop para o dest_addr fornecido.
- dest_addr = ip_to_bin(dest_addr)
- candidatos = []
- maior = 0
- for hop in self.tabela:
- tamanho = len(hop[0])
- if dest_addr[0:tamanho] == hop[0][0:tamanho]:
- candidatos.append(hop)
- for candidato in candidatos:
- tamanho = len(candidato[0])
- if tamanho >= maior:
- next_hop = candidato[1]
- maior = tamanho
- if(candidatos):
- return next_hop
- else:
- return None
- def definir_endereco_host(self, meu_endereco):
- """
- Define qual o endereço IPv4 (string no formato x.y.z.w) deste host.
- Se recebermos datagramas destinados a outros endereços em vez desse,
- atuaremos como roteador em vez de atuar como host.
- """
- self.meu_endereco = meu_endereco
- def definir_tabela_encaminhamento(self, tabela):
- """
- Define a tabela de encaminhamento no formato
- [(cidr0, next_hop0), (cidr1, next_hop1), ...]
- Onde os CIDR são fornecidos no formato 'x.y.z.w/n', e os
- next_hop são fornecidos no formato 'x.y.z.w'.
- """
- # TODO: Guarde a tabela de encaminhamento. Se julgar conveniente,
- # converta-a em uma estrutura de dados mais eficiente.
- self.tabela = [(ip_to_bin(item[0]), item[1]) for item in tabela]
- def registrar_recebedor(self, callback):
- """
- Registra uma função para ser chamada quando dados vierem da camada de rede
- """
- self.callback = callback
- def enviar(self, segmento, dest_addr):
- """
- Envia segmento para dest_addr, onde dest_addr é um endereço IPv4
- (string no formato x.y.z.w).
- """
- next_hop = self._next_hop(dest_addr)
- header = make_ipv4_header( len(segmento), self.meu_endereco, dest_addr, None, None, None, None, None, 64, None, True)
- datagram = header + segmento
- # TODO: Assumindo que a camada superior é o protocolo TCP, monte o
- # datagrama com o cabeçalho IP, contendo como payload o segmento.
- self.enlace.enviar(datagram, next_hop)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement