From 924a8250ced6a7bf2fb8625f8e4d9a707be5076f Mon Sep 17 00:00:00 2001 From: Dan Carley Date: Fri, 6 Jul 2012 08:22:32 +0100 Subject: [PATCH] (#15556) Support for ICMP6 type code resolutions Add support for IPv6 ICMP code types as strings, which differ in mapping from IPv4. A subset of the currently supported strings for IPv4 are supported where applicable to the IPv6 specification. Currently the only way of determining the protocol family is by whether the provider is :iptables or :ip6tables. This can be changed within the type in the future. --- lib/puppet/type/firewall.rb | 12 +++++- lib/puppet/util/firewall.rb | 18 ++++++++- spec/unit/puppet/type/firewall_spec.rb | 54 ++++++++++++++++--------- spec/unit/puppet/util/firewall_spec.rb | 55 +++++++++++++++++++------- 4 files changed, 104 insertions(+), 35 deletions(-) diff --git a/lib/puppet/type/firewall.rb b/lib/puppet/type/firewall.rb index 47aa992..59234f1 100644 --- a/lib/puppet/type/firewall.rb +++ b/lib/puppet/type/firewall.rb @@ -399,7 +399,17 @@ Puppet::Type.newtype(:firewall) do munge do |value| if value.kind_of?(String) - value = @resource.icmp_name_to_number(value) + # ICMP codes differ between IPv4 and IPv6. + case @resource[:provider] + when :iptables + protocol = 'inet' + when :ip6tables + protocol = 'inet6' + else + self.fail("cannot work out protocol family") + end + + value = @resource.icmp_name_to_number(value, protocol) else value end diff --git a/lib/puppet/util/firewall.rb b/lib/puppet/util/firewall.rb index d6dd90d..e93650c 100644 --- a/lib/puppet/util/firewall.rb +++ b/lib/puppet/util/firewall.rb @@ -5,10 +5,10 @@ require 'puppet/util/ipcidr' # Util module for puppetlabs-firewall module Puppet::Util::Firewall # Translate the symbolic names for icmp packet types to integers - def icmp_name_to_number(value_icmp) + def icmp_name_to_number(value_icmp, protocol) if value_icmp =~ /\d{1,2}$/ value_icmp - else + elsif protocol == 'inet' case value_icmp when "echo-reply" then "0" when "destination-unreachable" then "3" @@ -25,6 +25,20 @@ module Puppet::Util::Firewall when "address-mask-reply" then "18" else nil end + elsif protocol == 'inet6' + case value_icmp + when "destination-unreachable" then "1" + when "time-exceeded" then "3" + when "parameter-problem" then "4" + when "echo-request" then "128" + when "echo-reply" then "129" + when "router-solicitation" then "133" + when "router-advertisement" then "134" + when "redirect" then "137" + else nil + end + else + raise ArgumentError, "unsupported protocol family '#{protocol}'" end end diff --git a/spec/unit/puppet/type/firewall_spec.rb b/spec/unit/puppet/type/firewall_spec.rb index 2704e30..2d1ec0b 100755 --- a/spec/unit/puppet/type/firewall_spec.rb +++ b/spec/unit/puppet/type/firewall_spec.rb @@ -214,25 +214,43 @@ describe firewall do end describe ':icmp' do - values = { - '0' => 'echo-reply', - '3' => 'destination-unreachable', - '4' => 'source-quench', - '6' => 'redirect', - '8' => 'echo-request', - '9' => 'router-advertisement', - '10' => 'router-solicitation', - '11' => 'time-exceeded', - '12' => 'parameter-problem', - '13' => 'timestamp-request', - '14' => 'timestamp-reply', - '17' => 'address-mask-request', - '18' => 'address-mask-reply' + icmp_codes = { + :iptables => { + '0' => 'echo-reply', + '3' => 'destination-unreachable', + '4' => 'source-quench', + '6' => 'redirect', + '8' => 'echo-request', + '9' => 'router-advertisement', + '10' => 'router-solicitation', + '11' => 'time-exceeded', + '12' => 'parameter-problem', + '13' => 'timestamp-request', + '14' => 'timestamp-reply', + '17' => 'address-mask-request', + '18' => 'address-mask-reply' + }, + :ip6tables => { + '1' => 'destination-unreachable', + '3' => 'time-exceeded', + '4' => 'parameter-problem', + '128' => 'echo-request', + '129' => 'echo-reply', + '133' => 'router-solicitation', + '134' => 'router-advertisement', + '137' => 'redirect' + } } - values.each do |k,v| - it 'should convert icmp string to number' do - @resource[:icmp] = v - @resource[:icmp].should == k + icmp_codes.each do |provider, values| + describe provider do + values.each do |k,v| + it 'should convert icmp string to number' do + @resource[:provider] = provider + @resource[:provider].should == provider + @resource[:icmp] = v + @resource[:icmp].should == k + end + end end end diff --git a/spec/unit/puppet/util/firewall_spec.rb b/spec/unit/puppet/util/firewall_spec.rb index e847b3c..c5ab12c 100644 --- a/spec/unit/puppet/util/firewall_spec.rb +++ b/spec/unit/puppet/util/firewall_spec.rb @@ -23,20 +23,47 @@ describe 'Puppet::Util::Firewall' do end describe '#icmp_name_to_number' do - subject { resource } - specify { subject.icmp_name_to_number('echo-reply').should == '0' } - specify { subject.icmp_name_to_number('destination-unreachable').should == '3' } - specify { subject.icmp_name_to_number('source-quench').should == '4' } - specify { subject.icmp_name_to_number('redirect').should == '6' } - specify { subject.icmp_name_to_number('echo-request').should == '8' } - specify { subject.icmp_name_to_number('router-advertisement').should == '9' } - specify { subject.icmp_name_to_number('router-solicitation').should == '10' } - specify { subject.icmp_name_to_number('time-exceeded').should == '11' } - specify { subject.icmp_name_to_number('parameter-problem').should == '12' } - specify { subject.icmp_name_to_number('timestamp-request').should == '13' } - specify { subject.icmp_name_to_number('timestamp-reply').should == '14' } - specify { subject.icmp_name_to_number('address-mask-request').should == '17' } - specify { subject.icmp_name_to_number('address-mask-reply').should == '18' } + describe 'proto unsupported' do + subject { resource } + + %w{inet5 inet8 foo}.each do |proto| + it "should reject invalid proto #{proto}" do + expect { subject.icmp_name_to_number('echo-reply', proto) }.should + raise_error(ArgumentError, "unsupported protocol family '#{proto}'") + end + end + end + + describe 'proto IPv4' do + proto = 'inet' + subject { resource } + specify { subject.icmp_name_to_number('echo-reply', proto).should == '0' } + specify { subject.icmp_name_to_number('destination-unreachable', proto).should == '3' } + specify { subject.icmp_name_to_number('source-quench', proto).should == '4' } + specify { subject.icmp_name_to_number('redirect', proto).should == '6' } + specify { subject.icmp_name_to_number('echo-request', proto).should == '8' } + specify { subject.icmp_name_to_number('router-advertisement', proto).should == '9' } + specify { subject.icmp_name_to_number('router-solicitation', proto).should == '10' } + specify { subject.icmp_name_to_number('time-exceeded', proto).should == '11' } + specify { subject.icmp_name_to_number('parameter-problem', proto).should == '12' } + specify { subject.icmp_name_to_number('timestamp-request', proto).should == '13' } + specify { subject.icmp_name_to_number('timestamp-reply', proto).should == '14' } + specify { subject.icmp_name_to_number('address-mask-request', proto).should == '17' } + specify { subject.icmp_name_to_number('address-mask-reply', proto).should == '18' } + end + + describe 'proto IPv6' do + proto = 'inet6' + subject { resource } + specify { subject.icmp_name_to_number('destination-unreachable', proto).should == '1' } + specify { subject.icmp_name_to_number('time-exceeded', proto).should == '3' } + specify { subject.icmp_name_to_number('parameter-problem', proto).should == '4' } + specify { subject.icmp_name_to_number('echo-request', proto).should == '128' } + specify { subject.icmp_name_to_number('echo-reply', proto).should == '129' } + specify { subject.icmp_name_to_number('router-solicitation', proto).should == '133' } + specify { subject.icmp_name_to_number('router-advertisement', proto).should == '134' } + specify { subject.icmp_name_to_number('redirect', proto).should == '137' } + end end describe '#string_to_port' do -- 2.45.2