65 lines
1.5 KiB
Ruby
65 lines
1.5 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require_relative 'proto_type'
|
|
require_relative 'interface_list'
|
|
require_relative 'ipv4_device'
|
|
|
|
require 'packetfu'
|
|
|
|
# Handles functions common to all TCP sockets
|
|
module TCPLayer
|
|
@sockets = {}
|
|
@packets = []
|
|
|
|
def self.initialize
|
|
IPv4Layer.register_handler('0.0.0.0', ProtoType::IPv4::TCP, self)
|
|
end
|
|
|
|
def self.got_packet(packet)
|
|
socket = @sockets[[packet.ip_daddr, packet.tcp_dport]]
|
|
if socket
|
|
socket.got_packet(packet)
|
|
else
|
|
send_rst_to(packet)
|
|
end
|
|
end
|
|
|
|
def self.send_packet(packet)
|
|
IPv4Layer.send_packet(packet)
|
|
end
|
|
|
|
def self.register_socket(ip, port, socket)
|
|
raise Errno::EADDRINUSE, "bind(2) for \"#{ip}\" port #{port}" if @sockets[[ip, port]]
|
|
|
|
@sockets[[ip, port]] = socket
|
|
end
|
|
|
|
def self.delete_socket(ip, port)
|
|
@sockets.delete [ip, port]
|
|
end
|
|
|
|
def self.close_all
|
|
@sockets.each_value { _1.wait_till_closed }
|
|
end
|
|
|
|
def self.packet_seq_len(packet)
|
|
flags = packet.tcp_flags
|
|
len = packet.payload.length
|
|
len += 1 if flags.syn == 1 || flags.fin == 1
|
|
len
|
|
end
|
|
|
|
# rubocop: disable Metrics/AbcSize
|
|
def self.send_rst_to(packet)
|
|
pkt = PacketFu::TCPPacket.new
|
|
pkt.ip_daddr = packet.ip_saddr
|
|
pkt.tcp_sport = packet.tcp_dport
|
|
pkt.tcp_dport = packet.tcp_sport
|
|
pkt.tcp_flags = PacketFu::TcpFlags.new({ rst: true, ack: true })
|
|
pkt.tcp_seq = packet.tcp_ack
|
|
pkt.tcp_ack = packet.tcp_seq + packet_seq_len(packet)
|
|
send_packet(pkt)
|
|
end
|
|
# rubocop: enable Metrics/AbcSize
|
|
end
|