def make_ipv4_header(size, src_addr, dest_addr, dscp=None, ecn=None, identification=None, flags=None, frag_offset=None, ttl=255, proto=None, verify_checksum=False): version = 4 << 4 ihl = IHL vihl = version + ihl if dscp is None: dscp = 0 << 6 if ecn is None: ecn = 0 dscpecn = dscp + ecn total_length = twos_comp(size + 20, 16) if identification is None: identification = twos_comp(randint(0, 2**16), 16) if flags is None: flag_rsv = 0 flag_dtf = 0 flag_mrf = 0 flags = (flag_rsv << 15) | (flag_dtf << 14) | (flag_mrf << 13) if frag_offset is None: frag_offset = 0 flags |= frag_offset ttl = twos_comp(ttl, 8) if proto is None: proto = IPPROTO_TCP checksum = 0 src_addr = str2addr(src_addr) dest_addr = str2addr(dest_addr) header = struct.pack('!bbhhhbbh', vihl, dscpecn, total_length, identification, flags, ttl, proto, checksum) + src_addr + dest_addr if verify_checksum: checksum = twos_comp(calc_checksum(header[:4 * ihl]), 16) header = struct.pack('!bbhhhbbh', vihl, dscpecn, total_length, identification, flags, ttl, proto, checksum) + src_addr + dest_addr return header
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) # TODO: Trate corretamente o campo TTL do datagrama vihl, dscpecn, total_len, identification, flagsfrag, ttl, proto, \ checksum, src_addr, dest_addr = \ struct.unpack('!BBHHHBBHII', datagrama[:20]) ttl -= 1 datagrama2 = struct.pack('!BBHHHBBH', (4 << 4) + 5, 0, len(datagrama[20:]) + 20, 0, 0, ttl, 6, 0) + datagrama[12:16] + datagrama[16:20] data_checksum = mytcputils.calc_checksum(datagrama2) print(ttl) if ttl > 0: datagrama2 = struct.pack( '!BBHHHBBH', (4 << 4) + 5, 0, len(datagrama[20:]) + 20, 0, 0, ttl, 6, data_checksum) + datagrama[12:16] + datagrama[16:20] self.enlace.enviar(datagrama2, next_hop) else: #print(self.meu_endereco) #print(addr2str(datagrama[12:16])) #print(addr2str(datagrama[16:20])) #mytcputils.str2addr(self.meu_endereco) datafake = struct.pack('!BBHHHBBH', (4 << 4) + 5, 0, 20 + 8 + max(28, len(datagrama[20:])), 0, 0, 64, 1, 0) + \ mytcputils.str2addr(self.meu_endereco) + datagrama[12:16] data_checksum = mytcputils.calc_checksum(datafake) outro_checksum = mytcputils.calc_checksum( struct.pack('BBHI', 11, 0, 0, 0) + datagrama[:28]) print(outro_checksum) print(struct.pack('!BBHI', 11, 0, outro_checksum, 0)) datafake = struct.pack('!BBHHHBBH', (4 << 4) + 5, 0, 20 + 8 + max(28, len(datagrama[20:])), 0, 0, 64, 1, data_checksum) + \ mytcputils.str2addr(self.meu_endereco) + datagrama[12:16] + struct.pack('!BBHI', 11, 0, outro_checksum, 0) + datagrama[:28] print(len(datafake)) self.enlace.enviar(datafake, next_hop)
def _rdt_rcv(self, src_addr, dst_addr, segment): src_port, dst_port, seq_no, ack_no, \ flags, _, _, _ = read_header(segment) if dst_port != self.porta: # Ignora segmentos que não são destinados à porta do nosso servidor return try: pseudohdr = str2addr(src_addr) + str2addr(dst_addr) + \ struct.pack('!HH', 0x0006, len(segment)) if calc_checksum(pseudohdr + segment) != 0: print('descartando segmento com checksum incorreto') return
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) print("DEST_ADDR {0} NEXT_HOP {1} MEU_END {2}".format( dest_addr, next_hop, self.meu_endereco)) dest = dest_addr.split('.') destino = [int(dest[0]), int(dest[1]), int(dest[2]), int(dest[3])] val = destino[3] << 24 val += destino[2] << 16 val += destino[1] << 8 val += destino[0] << 0 val_dst = val val_dst = mytcputils.str2addr(dest_addr) dest = self.meu_endereco.split('.') destino = [int(dest[0]), int(dest[1]), int(dest[2]), int(dest[3])] val = destino[3] << 24 val += destino[2] << 16 val += destino[1] << 8 val += destino[0] << 0 val_src = val val_src = mytcputils.str2addr(self.meu_endereco) version = 4 ihl = 5 datagrama = struct.pack('!BBHHHBBH', (version << 4) + ihl, 0, len(segmento) + 20, 0, 0, 64, 6, 0) + val_src + val_dst data_checksum = mytcputils.calc_checksum(datagrama) datagrama = struct.pack('!BBHHHBBH', (version << 4) + ihl, 0, len(segmento) + 20, 0, 0, 64, 6, data_checksum) + val_src + val_dst + segmento #datagrama = ((4 << 4) + 5).to_bytes(1, 'little') + (0).to_bytes(7, 'little') + (64).to_bytes(1, 'little') + (0).to_bytes(7, 'little') + datagrama # 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(datagrama, next_hop)