Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 14 additions & 11 deletions lib/xlat/address_translation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,27 @@

module Xlat
module AddressTranslation
# Translate IPv6 address bytestring into IPv4 address and write to given buffer
# Must return true when translation took place
# Translate IPv6 address in the given IO::Buffer into IPv4 address and write to another IO::Buffer.
# Must return true when translation took place.
#
# @param ipv6_address [IO::Buffer] IPv6 address buffer
# @param buffer [IO::Buffer] Destination packet buffer
# @param offset [Integer] Offset in buffer to write IPv6 address
# @param source [IO::Buffer] Buffer from which IPv6 address is read
# @param source_offset [Integer] Offset in the source IO::Buffer
# @param destination [IO::Buffer] Buffer into which IPv4 address is written
# @param destination_offset [Integer] Offset in the destination IO::Buffer
# @return [Integer, nil] checksum delta value or nil when no translation took place
def translate_address_to_ipv4(ipv6_address,buffer,offset = 0)
def translate_address_to_ipv4(source, source_offset, destination, destination_offset)
raise NotImplementedError
end

# Translate IPv4 address bytestring into IPv6 address and write to given buffer
# Translate IPv4 address in the given IO::Buffer into IPv6 address and write to another IO::Buffer.
# Must return true when translation took place.
#
# @param ipv4_address [IO::Buffer] IPv4 address buffer
# @param buffer [IO::Buffer] Destination packet buffer
# @param offset [Integer] Offset in buffer to write IPv4 address
# @param source [IO::Buffer] Buffer from which IPv4 address is read
# @param source_offset [Integer] Offset in the source IO::Buffer
# @param destination [IO::Buffer] Buffer into which IPv6 address is written
# @param destination_offset [Integer] Offset in the destination IO::Buffer
# @return [Integer, nil] checksum delta value or nil when no translation took place
def translate_address_to_ipv6(ipv4_address,buffer,offset = 0)
def translate_address_to_ipv6(source, source_offset, destination, destination_offset)
raise NotImplementedError
end

Expand Down
15 changes: 9 additions & 6 deletions lib/xlat/address_translators/rfc6052.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# frozen_string_literal: true
require 'xlat/address_translation'
require 'xlat/io_buffer_ext'
require 'xlat/common'
require 'ipaddr'

Expand Down Expand Up @@ -28,16 +29,18 @@ def initialize(pref64n_string)
@negative_cs_delta = -@cs_delta
end

def translate_address_to_ipv4(ipv6_address,buffer,offset = 0)
return unless (ipv6_address.slice(0, @pref64n_prefix.size) <=> @pref64n_prefix) == 0
buffer.copy(ipv6_address, offset, 4, 12)
def translate_address_to_ipv4(source, source_offset, destination, destination_offset)
preflen = @pref64n_prefix.size
return unless (source.slice(source_offset, preflen) <=> @pref64n_prefix) == 0
destination.copy(source, destination_offset, 16 - preflen, source_offset + preflen)

@negative_cs_delta
end

def translate_address_to_ipv6(ipv4_address,buffer,offset = 0)
buffer.copy(@pref64n_prefix, offset, 12)
buffer.copy(ipv4_address, offset + 12, 4)
def translate_address_to_ipv6(source, source_offset, destination, destination_offset)
preflen = @pref64n_prefix.size
destination.copy(@pref64n_prefix, destination_offset, preflen)
destination.copy(source, destination_offset + preflen, 16 - preflen, source_offset)

@cs_delta
end
Expand Down
9 changes: 5 additions & 4 deletions lib/xlat/rfc7915.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# frozen_string_literal: true

require 'xlat/common'
require 'xlat/protocols/ip'

module Xlat
# RFC 7915 based stateless IPv4/IPv6 translator (SIIT). Intentionally not thread-safe.
Expand Down Expand Up @@ -107,8 +108,8 @@ def translate_to_ipv4(ipv6_packet, max_length)
new_header_buffer.set_value(:U8, 9, ipv6_proto)

# Source and Destination address
cs_delta_a = @source_address_translator.translate_address_to_ipv4(ipv6_bytes.slice(ipv6_bytes_offset + 8,16), new_header_buffer, 12) or return return_buffer_ownership()
cs_delta_b = @destination_address_translator.translate_address_to_ipv4(ipv6_bytes.slice(ipv6_bytes_offset + 24,16), new_header_buffer, 16) or return return_buffer_ownership()
cs_delta_a = @source_address_translator.translate_address_to_ipv4(ipv6_bytes, ipv6_bytes_offset + 8, new_header_buffer, 12) or return return_buffer_ownership()
cs_delta_b = @destination_address_translator.translate_address_to_ipv4(ipv6_bytes, ipv6_bytes_offset + 24, new_header_buffer, 16) or return return_buffer_ownership()
cs_delta += cs_delta_a + cs_delta_b

# TODO: DF bit
Expand Down Expand Up @@ -220,8 +221,8 @@ def translate_to_ipv6(ipv4_packet, max_length)
new_header_buffer.set_value(:U8, 7, ipv4_bytes.get_value(:U8, ipv4_bytes_offset + 8))

# Source and Destination address
cs_delta_a = @destination_address_translator.translate_address_to_ipv6(ipv4_bytes.slice(ipv4_bytes_offset + 12,4), new_header_buffer, 8) or return return_buffer_ownership()
cs_delta_b = @source_address_translator.translate_address_to_ipv6(ipv4_bytes.slice(ipv4_bytes_offset + 16,4), new_header_buffer, 24) or return return_buffer_ownership()
cs_delta_a = @destination_address_translator.translate_address_to_ipv6(ipv4_bytes, ipv4_bytes_offset + 12, new_header_buffer, 8) or return return_buffer_ownership()
cs_delta_b = @source_address_translator.translate_address_to_ipv6(ipv4_bytes, ipv4_bytes_offset + 16, new_header_buffer, 24) or return return_buffer_ownership()
cs_delta += cs_delta_a + cs_delta_b

if ipv4_proto == 1
Expand Down
14 changes: 7 additions & 7 deletions spec/address_translators/rfc6052_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,21 @@
describe "#translate_address_to_ipv4" do
it "translates into ipv4" do
buf = IO::Buffer.new(4)
expect(translator.translate_address_to_ipv4(IO::Buffer.for(IPAddr.new('64:ff9b::192.0.2.33').hton), buf)).to eq(0)
expect(translator.translate_address_to_ipv4(IO::Buffer.for(IPAddr.new('64:ff9b::192.0.2.33').hton), 0, buf, 0)).to eq(0)
expect(buf.get_string).to eq(IPAddr.new('192.0.2.33').hton)
end

context "with invalid ipv6 address" do
it "does nothing" do
buf = IO::Buffer.for('')
expect(translator.translate_address_to_ipv4(IO::Buffer.for(IPAddr.new('2001:db8::192.0.2.33').hton), buf)).to eq(nil)
expect(translator.translate_address_to_ipv4(IO::Buffer.for(IPAddr.new('2001:db8::192.0.2.33').hton), 0, buf, 0)).to eq(nil)
end
end

context "with offset" do
it "writes translated address at specified offset" do
buf = IO::Buffer.for("\xaf".b * 20).dup
expect(translator.translate_address_to_ipv4(IO::Buffer.for(IPAddr.new('64:ff9b::192.0.2.33').hton), buf, 4)).to eq(0)
expect(translator.translate_address_to_ipv4(IO::Buffer.for(IPAddr.new('64:ff9b::192.0.2.33').hton), 0, buf, 4)).to eq(0)
expect(buf.size).to eq(20)
expect(buf.get_string).to eq("\xaf".b * 4 + IPAddr.new('192.0.2.33').hton + "\xaf".b * 12)
end
Expand All @@ -36,7 +36,7 @@

it "translates into ipv4" do
buf = IO::Buffer.new(4)
expect(translator.translate_address_to_ipv4(IO::Buffer.for(IPAddr.new('2001:db8:64::192.0.2.33').hton), buf)).to eq(-11805)
expect(translator.translate_address_to_ipv4(IO::Buffer.for(IPAddr.new('2001:db8:64::192.0.2.33').hton), 0, buf, 0)).to eq(-11805)
expect(buf.get_string).to eq(IPAddr.new('192.0.2.33').hton)
end
end
Expand All @@ -45,14 +45,14 @@
describe "#translate_address_to_ipv6" do
it "translates into ipv6" do
buf = IO::Buffer.new(16)
expect(translator.translate_address_to_ipv6(IO::Buffer.for(IPAddr.new('192.0.2.33').hton), buf)).to eq(0)
expect(translator.translate_address_to_ipv6(IO::Buffer.for(IPAddr.new('192.0.2.33').hton), 0, buf, 0)).to eq(0)
expect(buf.get_string).to eq(IPAddr.new('64:ff9b::192.0.2.33').hton)
end

context "with offset" do
it "writes translated address at specified offset" do
buf = IO::Buffer.for("\xaf".b * 21).dup
expect(translator.translate_address_to_ipv6(IO::Buffer.for(IPAddr.new('192.0.2.33').hton), buf, 4)).to eq(0)
expect(translator.translate_address_to_ipv6(IO::Buffer.for(IPAddr.new('192.0.2.33').hton), 0, buf, 4)).to eq(0)
expect(buf.size).to eq(21)
expect(buf.get_string).to eq("\xaf".b * 4 + IPAddr.new('64:ff9b::192.0.2.33').hton + "\xaf".b)
end
Expand All @@ -63,7 +63,7 @@

it "translates into ipv4" do
buf = IO::Buffer.new(16)
expect(translator.translate_address_to_ipv6(IO::Buffer.for(IPAddr.new('192.0.2.33').hton), buf)).to eq(11805)
expect(translator.translate_address_to_ipv6(IO::Buffer.for(IPAddr.new('192.0.2.33').hton), 0, buf, 0)).to eq(11805)
expect(buf.get_string).to eq(IPAddr.new('2001:db8:64::192.0.2.33').hton)
end
end
Expand Down
24 changes: 12 additions & 12 deletions spec/rfc7915_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,36 +7,36 @@

RSpec.describe Xlat::Rfc7915 do
module MockAddrTranslator
def self.translate_address_to_ipv4(ipv6_address,buffer,offset = 0)
case IPAddr.new_ntoh(ipv6_address.get_string).to_s
def self.translate_address_to_ipv4(source, source_offset, destination, destination_offset)
case IPAddr.new_ntoh(source.get_string(source_offset, 16)).to_s
when IPAddr.new('64:ff9b:1:fffe::192.0.2.2').to_s
buffer.copy(IO::Buffer.for(IPAddr.new('192.0.2.2').hton), offset)
destination.copy(IO::Buffer.for(IPAddr.new('192.0.2.2').hton), destination_offset)
0
when IPAddr.new('64:ff9b::192.0.2.3').to_s
buffer.copy(IO::Buffer.for(IPAddr.new('192.0.2.3').hton), offset)
destination.copy(IO::Buffer.for(IPAddr.new('192.0.2.3').hton), destination_offset)
0
when IPAddr.new('2001:db8:60::192.0.2.7').to_s
buffer.copy(IO::Buffer.for(IPAddr.new('192.0.2.7').hton), offset)
destination.copy(IO::Buffer.for(IPAddr.new('192.0.2.7').hton), destination_offset)
-(0x2001 + 0x0db8 + 0x0060)
when IPAddr.new('2001:db8:64::192.0.2.8').to_s
buffer.copy(IO::Buffer.for(IPAddr.new('192.0.2.8').hton), offset)
destination.copy(IO::Buffer.for(IPAddr.new('192.0.2.8').hton), destination_offset)
-(0x2001 + 0x0db8 + 0x0064)
end
end

def self.translate_address_to_ipv6(ipv4_address,buffer,offset = 0)
case IPAddr.new_ntoh(ipv4_address.get_string).to_s
def self.translate_address_to_ipv6(source, source_offset, destination, destination_offset)
case IPAddr.new_ntoh(source.get_string(source_offset, 4)).to_s
when '192.0.2.2'
buffer.copy(IO::Buffer.for(IPAddr.new('64:ff9b:1:fffe::192.0.2.2').hton), offset)
destination.copy(IO::Buffer.for(IPAddr.new('64:ff9b:1:fffe::192.0.2.2').hton), destination_offset)
0
when '192.0.2.3'
buffer.copy(IO::Buffer.for(IPAddr.new('64:ff9b::192.0.2.3').hton), offset)
destination.copy(IO::Buffer.for(IPAddr.new('64:ff9b::192.0.2.3').hton), destination_offset)
0
when '192.0.2.7'
buffer.copy(IO::Buffer.for(IPAddr.new('2001:db8:60::192.0.2.7').hton), offset)
destination.copy(IO::Buffer.for(IPAddr.new('2001:db8:60::192.0.2.7').hton), destination_offset)
(0x2001 + 0x0db8 + 0x0060)
when '192.0.2.8'
buffer.copy(IO::Buffer.for(IPAddr.new('2001:db8:64::192.0.2.8').hton), offset)
destination.copy(IO::Buffer.for(IPAddr.new('2001:db8:64::192.0.2.8').hton), destination_offset)
(0x2001 + 0x0db8 + 0x0064)
end
end
Expand Down