File: validation_shortcuts.rb

package info (click to toggle)
ruby-netaddr 1.5.1-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 416 kB
  • sloc: ruby: 3,866; makefile: 9
file content (219 lines) | stat: -rwxr-xr-x 8,021 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
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
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
module NetAddr
private

#==============================================================================#
# validate_args()
#==============================================================================#

# validate options hash 
#
def validate_args(to_validate,known_args)
    to_validate.each do |x|
        raise ArgumentError, "Unrecognized argument #{x}. Valid arguments are " +
                             "#{known_args.join(',')}" if (!known_args.include?(x))
    end
end 
module_function :validate_args

#==============================================================================#
# validate_ip_int()
#==============================================================================#

def validate_ip_int(ip,version)
    version = 4 if (!version && ip < 2**32)
    if (version == 4)
        raise ValidationError, "#{ip} is invalid for IPv4 (Integer is out of bounds)." if ( (ip < 0) || (ip > 2**32-1) )
    else
        raise ValidationError, "#{ip} is invalid for both IPv4 and IPv6 (Integer is out of bounds)." if ( (ip < 0) || (ip > 2**128-1) )
        version = 6
    end
    return(version)
end
module_function :validate_ip_int

#==============================================================================#
# validate_ip_str()
#==============================================================================#

def validate_ip_str(ip,version)
    # check validity of charaters
    if (ip =~ /[^0-9a-fA-F\.:]/)
        raise ValidationError, "#{ip} is invalid (contains invalid characters)."
    end

    if (version == 4)
        octets = ip.split('.')
        raise ValidationError, "#{ip} is invalid (IPv4 requires (4) octets)." if (octets.length != 4)

        # are octets in range 0..255?
        octets.each do |octet|
            raise ValidationError, "#{ip} is invalid (IPv4 dotted-decimal format " +
                                   "should not contain non-numeric characters)." if (octet =~ /[\D]/ || octet == '')
            octet = octet.to_i()
            if ( (octet < 0) || (octet >= 256) )
                raise ValidationError, "#{ip} is invalid (IPv4 octets should be between 0 and 255)."
            end
        end

    else
            # make sure we only have at most (2) colons in a row, and then only
            # (1) instance of that
            if ( (ip =~ /:{3,}/) || (ip.split("::").length > 2) )
                raise ValidationError, "#{ip} is invalid (IPv6 field separators (:) are bad)."
            end

            # set flags
            shorthand = false
            if (ip =~ /\./)
                dotted_dec = true 
            else
                dotted_dec = false
            end

            # split up by ':'
            fields = []
            if (ip =~ /::/)
                shorthand = true
                ip.split('::').each do |x|
                    fields.concat( x.split(':') )
                end
            else
               fields.concat( ip.split(':') ) 
            end

            # make sure we have the correct number of fields
            if (shorthand)
                if ( (dotted_dec && fields.length > 6) || (!dotted_dec && fields.length > 7) )
                    raise ValidationError, "#{ip} is invalid (IPv6 shorthand notation has " +
                                           "incorrect number of fields)." 
                end
            else
                if ( (dotted_dec && fields.length != 7 ) || (!dotted_dec && fields.length != 8) )
                    raise ValidationError, "#{ip} is invalid (IPv6 address has " +
                                           "incorrect number of fields)." 
                end
            end

            # if dotted_dec then validate the last field
            if (dotted_dec)
                dotted = fields.pop()
                octets = dotted.split('.')
                raise ValidationError, "#{ip} is invalid (Legacy IPv4 portion of IPv6 " +
                                       "address should contain (4) octets)." if (octets.length != 4)
                octets.each do |x|
                    raise ValidationError, "#{ip} is invalid (egacy IPv4 portion of IPv6 " +
                                           "address should not contain non-numeric characters)." if (x =~ /[^0-9]/ )
                    x = x.to_i
                    if ( (x < 0) || (x >= 256) )
                        raise ValidationError, "#{ip} is invalid (Octets of a legacy IPv4 portion of IPv6 " +
                                               "address should be between 0 and 255)."
                    end
                end
            end

            # validate hex fields
            fields.each do |x|
                if (x =~ /[^0-9a-fA-F]/)
                    raise ValidationError, "#{ip} is invalid (IPv6 address contains invalid hex characters)."
                else
                    x = x.to_i(16)
                    if ( (x < 0) || (x >= 2**16) )
                        raise ValidationError, "#{ip} is invalid (Fields of an IPv6 address " +
                                               "should be between 0x0 and 0xFFFF)."
                    end
                end
            end

    end
    return(true)
end
module_function :validate_ip_str

#==============================================================================#
# validate_netmask_int()
#==============================================================================#
def validate_netmask_int(netmask,version,is_int=false)
    address_len = 32
    address_len = 128 if (version == 6)

    if (!is_int)
        if (netmask > address_len || netmask < 0 )
            raise ValidationError, "Netmask, #{netmask}, is out of bounds for IPv#{version}." 
        end
    else
        if (netmask >= 2**address_len || netmask < 0 )
            raise ValidationError, "netmask (#{netmask}) is out of bounds for IPv#{version}."
        end
    end
    return(true)
end
module_function :validate_netmask_int

#==============================================================================#
# validate_netmask_str()
#==============================================================================#
def validate_netmask_str(netmask,version)
    address_len = 32
    address_len = 128 if (version == 6)

    if(netmask =~ /\./) # extended netmask
        all_f = 2**32-1
        netmask_int = 0

        # validate & pack extended mask
        begin
            netmask_int = NetAddr.ip_to_i(netmask, :Version => 4)
        rescue Exception => error
          raise ValidationError, "#{netmask} is improperly formed: #{error}"
        end

        # cycle through the bits of hostmask and compare
        # with netmask_int. when we hit the firt '1' within
        # netmask_int (our netmask boundary), xor hostmask and
        # netmask_int. the result should be all 1's. this whole
        # process is in place to make sure that we dont have
        # and crazy masks such as 255.254.255.0
        hostmask = 1
         32.times do 
            check = netmask_int & hostmask
            if ( check != 0)
                hostmask = hostmask >> 1
                unless ( (netmask_int ^ hostmask) == all_f)
                    raise ValidationError, "#{netmask} contains '1' bits within the host portion of the netmask." 
                end
                break
            else
                hostmask = hostmask << 1
                hostmask = hostmask | 1
            end
        end

    else # cidr format
        # remove '/' if present
        if (netmask =~ /^\// )
            netmask[0] = " "
            netmask.lstrip!
        end

        # check if we have any non numeric characters
        if (netmask =~ /\D/)
            raise ValidationError, "#{netmask} contains invalid characters."
        end

        netmask = netmask.to_i
        if (netmask > address_len || netmask < 0 )
            raise ValidationError, "Netmask, #{netmask}, is out of bounds for IPv#{version}." 
        end

    end
    return(true)
end
module_function :validate_netmask_str



end # module NetAddr

__END__