Module: RPSL

Defined in:
lib/rpsl.rb

Overview

Library which provides functions for reading and writing Routing Policy Specification Language (RPSL, RFC2622).

Defined Under Namespace

Classes: DumpError, ParserError, RPSLError

Class Method Summary collapse

Class Method Details

.dump(obj, value_column = nil) ⇒ Object

Converts a hash into the RPSL format.

Examples:

obj = {"route6"=>"fd42:4242:2601:ffff::/64",
       "descr"=>"This is an ROA test object",
       "max-length"=>"112",
       "remarks"=>
       "\n" +
       "This object is designed to test ROA scripts\n" +
       "in a number of ways.\n" +
       "\n" +
       "The expected output for this route should be:\n" +
       "roa fd42:4242:2601:ffff::/64 max 64 as 0;\n" +
       "\n" +
       "This is not a blank line\n" +
       "+ ----- +\n" +
       "\n" +
       "The first test is to include a number of syntax\n" +
       "corner cases, designed to trip up parsers\n" +
       "\n" +
       "The first max-length line should be clamped\n" +
       "to the maximums defined in filter6.txt\n" +
       "\n" +
       "The second max-length is part of the remark\n" +
       "and should be ignored.\n" +
       "\n" +
       "max-length: 48",
       "origin"=>"AS0",
       "mnt-by"=>"BURBLE-MNT",
       "source"=>"DN42"}

RPSL.dump(obj, 20) # => "route6:             fd42:4242:2601:ffff::/64\n" +
                   #    "descr:              This is an ROA test object\n" +
                   #    "max-length:         112\n" +
                   #    "remarks:            \n" +
                   #    "                    This object is designed to test ROA scripts\n" +
                   #    "                    in a number of ways.\n" +
                   #    "+\n" +
                   #    "                    The expected output for this route should be:\n" +
                   #    "                    roa fd42:4242:2601:ffff::/64 max 64 as 0;\n" +
                   #    "+\n" +
                   #    "                    This is not a blank line\n" +
                   #    "                    + ----- +\n" +
                   #    "+\n" +
                   #    "                    The first test is to include a number of syntax\n" +
                   #    "                    corner cases, designed to trip up parsers\n" +
                   #    "+\n" +
                   #    "                    The first max-length line should be clamped\n" +
                   #    "                    to the maximums defined in filter6.txt\n" +
                   #    "+\n" +
                   #    "                    The second max-length is part of the remark\n" +
                   #    "                    and should be ignored.\n" +
                   #    "+\n" +
                   #    "                    max-length: 48\n" +
                   #    "origin:             AS0\n" +
                   #    "mnt-by:             BURBLE-MNT\n" +
                   #    "source:             DN42\n"

Parameters:

  • obj (Hash)

    Hash in which the data to be converted is stored.

  • value_column (Integer, NilClass) (defaults to: nil)

    ‘nil` or the column where the value should start.



162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# File 'lib/rpsl.rb', line 162

def self.dump(obj, value_column = nil)
  rpsl = ''

  obj.each do |key, value|
    lines = value.to_s.lines
    lines.map!(&:chomp)
    first_value = lines.shift

    key = key.to_s

    if value_column
      padding_length = value_column.to_i - 1 - key.length
      raise DumpError, 'Key too long.' if padding_length.negative?

      padding = ' ' * padding_length
    end

    rpsl += "#{key}:#{padding}#{first_value}\n"
    lines.each do |line|
      rpsl += if line.empty?
                "+\n"
              elsif value_column
                "#{' ' * value_column}#{line}\n"
              else
                " #{line}\n"
              end
    end
  end

  return rpsl
end

.load(rpsl) ⇒ Hash

Parses a string as RPSL.

Examples:

rpsl = <<EOF
route6:             fd42:4242:2601:ffff::/64
descr:              This is an ROA test object
max-length:         112
remarks:
                    This object is designed to test ROA scripts
                    in a number of ways.
+
                    The expected output for this route should be:
                    roa fd42:4242:2601:ffff::/64 max 64 as 0;
+
                    This is not a blank line
                    + ----- +
+
                    The first test is to include a number of syntax
                    corner cases, designed to trip up parsers
+
                    The first max-length line should be clamped
                    to the maximums defined in filter6.txt
+
                    The second max-length is part of the remark
                    and should be ignored.
+
                    max-length: 48
+
origin:             AS0
mnt-by:             BURBLE-MNT
source:             DN42
EOF

RPSL.load(rpsl) # => {"route6"=>"fd42:4242:2601:ffff::/64\n",
                #     "descr"=>"This is an ROA test object\n",
                #     "max-length"=>"112\n",
                #     "remarks"=>
                #      "\n" +
                #      "This object is designed to test ROA scripts\n" +
                #      "in a number of ways.\n" +
                #      "\n" +
                #      "The expected output for this route should be:\n" +
                #      "roa fd42:4242:2601:ffff::/64 max 64 as 0;\n" +
                #      "\n" +
                #      "This is not a blank line\n" +
                #      "+ ----- +\n" +
                #      "\n" +
                #      "The first test is to include a number of syntax\n" +
                #      "corner cases, designed to trip up parsers\n" +
                #      "\n" +
                #      "The first max-length line should be clamped\n" +
                #      "to the maximums defined in filter6.txt\n" +
                #      "\n" +
                #      "The second max-length is part of the remark\n" +
                #      "and should be ignored.\n" +
                #      "\n" +
                #      "max-length: 48\n" +
                #      "\n",
                #     "origin"=>"AS0\n",
                #     "mnt-by"=>"BURBLE-MNT\n",
                #     "source"=>"DN42\n"}

Parameters:

  • rpsl (String)

    The RPSL data as an object which can be iterated with each_line.

Returns:

  • (Hash)

    Hash containing the RPSL data.



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/rpsl.rb', line 75

def self.load(rpsl)
  obj = {}
  current_section = nil

  rpsl.to_s.each_line.with_index do |line, lineno|
    line.chomp!

    case line
    when /^([\d\w\-_]+): *(.*)$/
      current_section = $1

      obj[current_section] = "#{obj[current_section]}#{$2}\n"
    when /^[+ \s] *(.+)$/
      raise ParserError, "Value without key in line #{lineno + 1}" unless current_section

      obj[current_section] = "#{obj[current_section]}#{$1}\n"
    when /^\+ *$/
      raise ParserError, "Empty line without key in line #{lineno + 1}" unless current_section

      obj[current_section] = "#{obj[current_section]}\n"
    else
      raise ParserError, "Failed to parse line #{lineno + 1}."
    end
  end

  return obj
end