netaddr 1.5.1 → 2.0.4

Sign up to get free protection for your applications and to get access to all the features.
data/lib/ipv4net.rb ADDED
@@ -0,0 +1,262 @@
1
+ module NetAddr
2
+
3
+ #IPv4Net represents an IPv4 network.
4
+ class IPv4Net
5
+
6
+ #arguments:
7
+ #* ip - an IPv4 object
8
+ #* m32 - a Mask32 object. will default to a /32 if nil
9
+ def initialize(ip,m32)
10
+ if (!ip.kind_of?(IPv4))
11
+ raise ArgumentError, "Expected an IPv4 object for 'ip' but got a #{ip.class}."
12
+ elsif (m32 != nil && !m32.kind_of?(Mask32))
13
+ raise ArgumentError, "Expected a Mask32 object for 'm32' but got a #{m32.class}."
14
+ end
15
+
16
+ if (m32 == nil)
17
+ m32 = Mask32.new(32)
18
+ end
19
+ @m32 = m32
20
+ @base = IPv4.new(ip.addr & m32.mask)
21
+ end
22
+
23
+ # parse will create an IPv4Net from its string representation. Will default to a /32 netmask if not specified.
24
+ # Throws ValidationError on error.
25
+ def IPv4Net.parse(net)
26
+ net = net.strip
27
+ m32 = nil
28
+ if (net.include?("/")) # cidr format
29
+ addr,mask = net.split("/")
30
+ m32 = Mask32.parse(mask)
31
+ elsif (net.include?(" ") ) # extended format
32
+ addr,mask = net.split(' ')
33
+ m32 = Mask32.parse(mask)
34
+ else
35
+ addr = net
36
+ end
37
+ ip = IPv4.parse(addr)
38
+ return IPv4Net.new(ip,m32)
39
+ end
40
+
41
+ # extended returns the IPv4Net in extended format (eg. x.x.x.x y.y.y.y)
42
+ def extended()
43
+ return @base.to_s + " " + Util.int_to_IPv4(@m32.mask)
44
+ end
45
+
46
+ # cmp compares equality with another IPv4Net. Return:
47
+ # * 1 if this IPv4Net is numerically greater
48
+ # * 0 if the two are equal
49
+ # * -1 if this IPv4Net is numerically less
50
+ #
51
+ # The comparison is initially performed on using the cmp() method of the network address, however, in cases where the network
52
+ # addresses are identical then the netmasks will be compared with the cmp() method of the netmask.
53
+ def cmp(other)
54
+ if (!other.kind_of?(IPv4Net))
55
+ raise ArgumentError, "Expected an IPv4Net object for 'other' but got a #{other.class}."
56
+ end
57
+ cmp = self.network.cmp(other.network)
58
+ if (cmp != 0)
59
+ return cmp
60
+ end
61
+ return self.netmask.cmp(other.netmask)
62
+ end
63
+
64
+ #contains returns true if the IPv4Net contains the IPv4
65
+ def contains(ip)
66
+ if (!ip.kind_of?(IPv4))
67
+ raise ArgumentError, "Expected an IPv4 object for 'ip' but got a #{ip.class}."
68
+ end
69
+ if (@base.addr == ip.addr & @m32.mask)
70
+ return true
71
+ end
72
+ return false
73
+ end
74
+
75
+ # fill returns a copy of the given Array, stripped of any networks which are not subnets of this IPv4Net
76
+ # and with any missing gaps filled in.
77
+ def fill(list)
78
+ list = Util.filter_IPv4Net(list)
79
+ return Util.fill(self,list)
80
+ end
81
+
82
+ # netmask returns the Mask32 object representing the netmask for this network
83
+ def netmask()
84
+ @m32
85
+ end
86
+
87
+ # network returns the IPv4 object representing the network address
88
+ def network()
89
+ @base
90
+ end
91
+
92
+ #len returns the number of IP addresses in this network. It will return 0 for /0 networks.
93
+ def len()
94
+ return self.netmask.len
95
+ end
96
+
97
+ # next returns the next largest consecutive IP network or nil if the end of the address space is reached.
98
+ def next()
99
+ net = self.nth_next_sib(1)
100
+ if (!net)
101
+ return nil
102
+ end
103
+ return net.grow
104
+ end
105
+
106
+ # next_sib returns the network immediately following this one or nil if the end of the address space is reached.
107
+ def next_sib()
108
+ self.nth_next_sib(1)
109
+ end
110
+
111
+ # nth returns the IPv4 at the given index.
112
+ # The size of the network may be determined with the len() method.
113
+ # If the range is exceeded then return nil.
114
+ def nth(index)
115
+ if (!index.kind_of?(Integer))
116
+ raise ArgumentError, "Expected an Integer for 'index' but got a #{index.class}."
117
+ elsif (index >= self.len)
118
+ return nil
119
+ end
120
+ return IPv4.new(self.network.addr + index)
121
+ end
122
+
123
+ # nth_subnet returns the subnet IPv4Net at the given index.
124
+ # The number of subnets may be determined with the subnet_count() method.
125
+ # If the range is exceeded or an invalid prefix_len is provided then return nil.
126
+ def nth_subnet(prefix_len,index)
127
+ count = self.subnet_count(prefix_len)
128
+ if (count == 0 || index >= count)
129
+ return nil
130
+ end
131
+ sub0 = IPv4Net.new(self.network, Mask32.new(prefix_len))
132
+ return sub0.nth_next_sib(index)
133
+ end
134
+
135
+ # prev returns the previous largest consecutive IP network or nil if this is 0.0.0.0.
136
+ def prev()
137
+ net = self.grow
138
+ return net.prev_sib
139
+ end
140
+
141
+ # prev_sib returns the network immediately preceding this one or nil if this network is 0.0.0.0.
142
+ def prev_sib()
143
+ if (self.network.addr == 0)
144
+ return nil
145
+ end
146
+
147
+ shift = 32 - self.netmask.prefix_len
148
+ addr = ((self.network.addr>>shift) - 1) << shift
149
+ return IPv4Net.new(IPv4.new(addr), self.netmask)
150
+ end
151
+
152
+ # rel determines the relationship to another IPv4Net. Returns:
153
+ # * 1 if this IPv4Net is the supernet of other
154
+ # * 0 if the two are equal
155
+ # * -1 if this IPv4Net is a subnet of other
156
+ # * nil if the networks are unrelated
157
+ def rel(other)
158
+ if (!other.kind_of?(IPv4Net))
159
+ raise ArgumentError, "Expected an IPv4Net object for 'other' but got a #{other.class}."
160
+ end
161
+
162
+ # when networks are equal then we can look exlusively at the netmask
163
+ if (self.network.addr == other.network.addr)
164
+ return self.netmask.cmp(other.netmask)
165
+ end
166
+
167
+ # when networks are not equal we can use hostmask to test if they are
168
+ # related and which is the supernet vs the subnet
169
+ hostmask = self.netmask.mask ^ NetAddr::F32
170
+ otherHostmask = other.netmask.mask ^ NetAddr::F32
171
+ if (self.network.addr|hostmask == other.network.addr|hostmask)
172
+ return 1
173
+ elsif (self.network.addr|otherHostmask == other.network.addr|otherHostmask)
174
+ return -1
175
+ end
176
+ return nil
177
+ end
178
+
179
+ # resize returns a copy of the network with an adjusted netmask.
180
+ # Throws ValidationError on invalid prefix_len.
181
+ def resize(prefix_len)
182
+ m32 = Mask32.new(prefix_len)
183
+ return IPv4Net.new(self.network,m32)
184
+ end
185
+
186
+ # subnet_count returns the number a subnets of a given prefix length that this IPv4Net contains.
187
+ # It will return 0 for invalid requests (ie. bad prefix or prefix is shorter than that of this network).
188
+ # It will also return 0 if the result exceeds the capacity of a 32-bit integer (ie. if you want the # of /32 a /0 will hold)
189
+ def subnet_count(prefix_len)
190
+ if (prefix_len <= self.netmask.prefix_len || prefix_len > 32 || prefix_len - self.netmask.prefix_len >= 32)
191
+ return 0
192
+ end
193
+ return 1 << (prefix_len - self.netmask.prefix_len)
194
+ end
195
+
196
+ # summ creates a summary address from this IPv4Net and another.
197
+ # It returns nil if the two networks are incapable of being summarized.
198
+ def summ(other)
199
+ if (!other.kind_of?(IPv4Net))
200
+ raise ArgumentError, "Expected an IPv4Net object for 'other' but got a #{other.class}."
201
+ end
202
+
203
+ # netmasks must be identical
204
+ if (self.netmask.prefix_len != other.netmask.prefix_len)
205
+ return nil
206
+ end
207
+
208
+ # merge-able networks will be identical if you right shift them by the number of bits in the hostmask + 1
209
+ shift = 32 - self.netmask.prefix_len + 1
210
+ addr = self.network.addr >> shift
211
+ otherAddr = other.network.addr >> shift
212
+ if (addr != otherAddr)
213
+ return nil
214
+ end
215
+ return self.resize(self.netmask.prefix_len - 1)
216
+ end
217
+
218
+ # to_s returns the IPv4Net as a String
219
+ def to_s()
220
+ return @base.to_s + @m32.to_s
221
+ end
222
+
223
+ # version returns "4" for IPv4
224
+ def version()
225
+ return 4
226
+ end
227
+
228
+
229
+ protected
230
+
231
+ # grow decreases the prefix length as much as possible without crossing a bit boundary.
232
+ def grow()
233
+ addr = self.network.addr
234
+ mask = self.netmask.mask
235
+ prefix_len = self.netmask.prefix_len
236
+ self.netmask.prefix_len.downto(0) do
237
+ mask = (mask << 1) & NetAddr::F32
238
+ if addr|mask != mask || prefix_len == 0 # // bit boundary crossed when there are '1' bits in the host portion
239
+ break
240
+ end
241
+ prefix_len -= 1
242
+ end
243
+ return IPv4Net.new(IPv4.new(addr),Mask32.new(prefix_len))
244
+ end
245
+
246
+ # nth_next_sib returns the nth next sibling network or nil if address space exceeded.
247
+ def nth_next_sib(nth)
248
+ if (nth < 0)
249
+ return nil
250
+ end
251
+
252
+ shift = 32 - self.netmask.prefix_len
253
+ addr = ((self.network.addr>>shift) + nth) << shift
254
+ if addr > NetAddr::F32
255
+ return nil
256
+ end
257
+ return IPv4Net.new(IPv4.new(addr), self.netmask)
258
+ end
259
+
260
+ end # end class IPv4Net
261
+
262
+ end # end module
data/lib/ipv6.rb ADDED
@@ -0,0 +1,120 @@
1
+ module NetAddr
2
+
3
+ #IPv6 represents a single IPv6 address.
4
+ class IPv6
5
+ # addr is the Integer representation of this IP address
6
+ attr_reader :addr
7
+
8
+ #Create an IPv6 from an Integer. Must be between 0 and 2**128-1.
9
+ #Throws ValidationError on error.
10
+ def initialize(i)
11
+ if (!i.kind_of?(Integer))
12
+ raise ValidationError, "Expected an Integer for 'i' but got a #{i.class}."
13
+ elsif ( (i < 0) || (i > NetAddr::F128) )
14
+ raise ValidationError, "#{i} is out of bounds for IPv6."
15
+ end
16
+ @addr = i
17
+ end
18
+
19
+ # parse will create an IPv6 from its string representation (ie. "1::").
20
+ # Throws ValidationError on error.
21
+ def IPv6.parse(ip)
22
+ ip = ip.strip
23
+ i = Util.parse_IPv6(ip)
24
+ return IPv6.new(i)
25
+ end
26
+
27
+ # cmp compares equality with another IPv6. Return:
28
+ # * 1 if this IPv6 is numerically greater
29
+ # * 0 if the two are equal
30
+ # * -1 if this IPv6 is numerically less
31
+ def cmp(other)
32
+ if (!other.kind_of?(IPv6))
33
+ raise ArgumentError, "Expected an IPv6 object for 'other' but got a #{other.class}."
34
+ end
35
+ if (self.addr > other.addr)
36
+ return 1
37
+ elsif (self.addr < other.addr)
38
+ return -1
39
+ end
40
+ return 0
41
+ end
42
+
43
+ # long returns the IPv6 as a string in long (uncompressed) format
44
+ def long()
45
+ words = []
46
+ 7.downto(0) do |x|
47
+ word = (@addr >> 16*x) & 0xffff
48
+ words.push( word.to_s(16).rjust(4, "0") )
49
+ end
50
+ return words.join(':')
51
+ end
52
+
53
+ # next returns the next consecutive IPv6 or nil if the address space is exceeded
54
+ def next()
55
+ if (self.addr == NetAddr::F128)
56
+ return nil
57
+ end
58
+ return IPv6.new(self.addr + 1)
59
+ end
60
+
61
+ # prev returns the preceding IPv6 or nil if this is 0.0.0.0
62
+ def prev()
63
+ if (self.addr == 0)
64
+ return nil
65
+ end
66
+ return IPv6.new(self.addr - 1)
67
+ end
68
+
69
+ # to_net returns the IPv6 as a IPv6Net
70
+ def to_net()
71
+ NetAddr::IPv6Net.new(self,nil)
72
+ end
73
+
74
+ # to_s returns the IPv6 as a String in zero-compressed format (per rfc5952).
75
+ def to_s()
76
+ hexStr = ["","","","","","","",""]
77
+ zeroStart, consec0, finalStart, finalLen = -1,0,-1,0
78
+ 8.times do |i|
79
+ # capture 2-byte word
80
+ shift = 112 - 16*i
81
+ wd = (self.addr >> shift) & 0xffff
82
+ hexStr[i] = wd.to_s(16)
83
+
84
+ # capture count of consecutive zeros
85
+ if (wd == 0)
86
+ if (zeroStart == -1)
87
+ zeroStart = i
88
+ end
89
+ consec0 += 1
90
+ end
91
+
92
+ # test for longest consecutive zeros when non-zero encountered or we're at the end
93
+ if (wd != 0 || i == 7)
94
+ if (consec0 > finalStart+finalLen-1)
95
+ finalStart = zeroStart
96
+ finalLen = consec0
97
+ end
98
+ zeroStart = -1
99
+ consec0 = 0
100
+ end
101
+ end
102
+
103
+ # compress if we've found a series of 0 words in a row
104
+ if (finalStart != -1)
105
+ head = hexStr[0,finalStart].join(":")
106
+ tailStart = finalStart + finalLen
107
+ tail = hexStr[tailStart..7].join(":")
108
+ return head + "::" + tail
109
+ end
110
+ return hexStr.join(":")
111
+ end
112
+
113
+ # version returns "6" for IPv6
114
+ def version()
115
+ return 6
116
+ end
117
+
118
+ end # end class IPv6
119
+
120
+ end # end module
data/lib/ipv6net.rb ADDED
@@ -0,0 +1,267 @@
1
+ module NetAddr
2
+
3
+ #IPv6Net represents an IPv6 network.
4
+ class IPv6Net
5
+
6
+ #arguments:
7
+ #* ip - an IPv6 object
8
+ #* m128 - a Mask128 object. will default to a /64 if nil
9
+ def initialize(ip,m128)
10
+ if (!ip.kind_of?(IPv6))
11
+ raise ArgumentError, "Expected an IPv6 object for 'ip' but got a #{ip.class}."
12
+ elsif (m128 != nil && !m128.kind_of?(Mask128))
13
+ raise ArgumentError, "Expected a Mask128 object for 'm128' but got a #{m128.class}."
14
+ end
15
+
16
+ if (m128 == nil)
17
+ if (ip.addr != 0)
18
+ m128 = Mask128.new(64) # use /64 mask per rfc 4291
19
+ else
20
+ m128 = Mask128.new(128) # use /128 mask per rfc 4291
21
+ end
22
+ end
23
+ @m128 = m128
24
+ @base = IPv6.new(ip.addr & m128.mask)
25
+ end
26
+
27
+ # parse will create an IPv6Net from its string representation. A default netmask will be used if not specified.
28
+ # Throws ValidationError on error.
29
+ def IPv6Net.parse(net)
30
+ m128 = nil
31
+ net = net.strip
32
+ if (net.include?("/")) # cidr format
33
+ addr,mask = net.split("/")
34
+ m128 = Mask128.parse(mask)
35
+ else
36
+ addr = net
37
+ end
38
+ ip = IPv6.parse(addr)
39
+ return IPv6Net.new(ip,m128)
40
+ end
41
+
42
+ # cmp compares equality with another IPv6Net. Return:
43
+ # * 1 if this IPv6Net is numerically greater
44
+ # * 0 if the two are equal
45
+ # * -1 if this IPv6Net is numerically less
46
+ #
47
+ # The comparison is initially performed on using the cmp() method of the network address, however, in cases where the network
48
+ # addresses are identical then the netmasks will be compared with the cmp() method of the netmask.
49
+ def cmp(other)
50
+ if (!other.kind_of?(IPv6Net))
51
+ raise ArgumentError, "Expected an IPv6Net object for 'other' but got a #{other.class}."
52
+ end
53
+ cmp = self.network.cmp(other.network)
54
+ if (cmp != 0)
55
+ return cmp
56
+ end
57
+ return self.netmask.cmp(other.netmask)
58
+ end
59
+
60
+ #contains returns true if the IPv6Net contains the IPv6
61
+ def contains(ip)
62
+ if (!ip.kind_of?(IPv6))
63
+ raise ArgumentError, "Expected an IPv6 object for 'ip' but got a #{ip.class}."
64
+ end
65
+ if (@base.addr == ip.addr & @m128.mask)
66
+ return true
67
+ end
68
+ return false
69
+ end
70
+
71
+ # fill returns a copy of the given Array, stripped of any networks which are not subnets of this IPv6Net
72
+ # and with any missing gaps filled in.
73
+ def fill(list)
74
+ list = Util.filter_IPv6Net(list)
75
+ return Util.fill(self,list)
76
+ end
77
+
78
+ #len returns the number of IP addresses in this network. It will return 0 for /0 networks.
79
+ def len()
80
+ return self.netmask.len
81
+ end
82
+
83
+ # long returns the IPv6Net as a string in long (uncompressed) format
84
+ def long()
85
+ return @base.long() + @m128.to_s
86
+ end
87
+
88
+ # netmask returns the Mask128 object representing the netmask for this network
89
+ def netmask()
90
+ @m128
91
+ end
92
+
93
+ # network returns the IPv6 object representing the network address
94
+ def network()
95
+ @base
96
+ end
97
+
98
+ # next returns the next largest consecutive IP network or nil if the end of the address space is reached.
99
+ def next()
100
+ net = self.nth_next_sib(1)
101
+ if (!net)
102
+ return nil
103
+ end
104
+ return net.grow
105
+ end
106
+
107
+ # next_sib returns the network immediately following this one or nil if the end of the address space is reached.
108
+ def next_sib()
109
+ self.nth_next_sib(1)
110
+ end
111
+
112
+ # nth returns the IPv6 at the given index.
113
+ # The size of the network may be determined with the len() method.
114
+ # If the range is exceeded then return nil.
115
+ def nth(index)
116
+ if (!index.kind_of?(Integer))
117
+ raise ArgumentError, "Expected an Integer for 'index' but got a #{index.class}."
118
+ elsif (self.netmask.prefix_len < 64 || (self.netmask.prefix_len > 64 && index >= self.len))
119
+ return nil
120
+ end
121
+ return IPv6.new(self.network.addr + index)
122
+ end
123
+
124
+ # nth_subnet returns the subnet IPv6Net at the given index.
125
+ # The number of subnets may be determined with the subnet_count() method.
126
+ # If the range is exceeded or an invalid prefix_len is provided then return nil.
127
+ def nth_subnet(prefix_len,index)
128
+ count = self.subnet_count(prefix_len)
129
+ if (count == 0 || index >= count)
130
+ return nil
131
+ end
132
+ sub0 = IPv6Net.new(self.network, Mask128.new(prefix_len))
133
+ return sub0.nth_next_sib(index)
134
+ end
135
+
136
+ # prev returns the previous largest consecutive IP network or nil if this is ::.
137
+ def prev()
138
+ net = self.grow
139
+ return net.prev_sib
140
+ end
141
+
142
+ # prev_sib returns the network immediately preceding this one or nil if this network is ::.
143
+ def prev_sib()
144
+ if (self.network.addr == 0)
145
+ return nil
146
+ end
147
+
148
+ shift = 128 - self.netmask.prefix_len
149
+ addr = ((self.network.addr>>shift) - 1) << shift
150
+ if addr < 0
151
+ return nil
152
+ end
153
+ return IPv6Net.new(IPv6.new(addr), self.netmask)
154
+ end
155
+
156
+ # rel determines the relationship to another IPv6Net. Returns:
157
+ # * 1 if this IPv6Net is the supernet of other
158
+ # * 0 if the two are equal
159
+ # * -1 if this IPv6Net is a subnet of other
160
+ # * nil if the networks are unrelated
161
+ def rel(other)
162
+ if (!other.kind_of?(IPv6Net))
163
+ raise ArgumentError, "Expected an IPv6Net object for 'other' but got a #{other.class}."
164
+ end
165
+
166
+ # when networks are equal then we can look exlusively at the netmask
167
+ if (self.network.addr == other.network.addr)
168
+ return self.netmask.cmp(other.netmask)
169
+ end
170
+
171
+ # when networks are not equal we can use hostmask to test if they are
172
+ # related and which is the supernet vs the subnet
173
+ hostmask = self.netmask.mask ^ NetAddr::F128
174
+ otherHostmask = other.netmask.mask ^ NetAddr::F128
175
+ if (self.network.addr|hostmask == other.network.addr|hostmask)
176
+ return 1
177
+ elsif (self.network.addr|otherHostmask == other.network.addr|otherHostmask)
178
+ return -1
179
+ end
180
+ return nil
181
+ end
182
+
183
+ # resize returns a copy of the network with an adjusted netmask.
184
+ # Throws ValidationError on invalid prefix_len.
185
+ def resize(prefix_len)
186
+ m128 = Mask128.new(prefix_len)
187
+ return IPv6Net.new(self.network,m128)
188
+ end
189
+
190
+ # subnet_count returns the number a subnets of a given prefix length that this IPv6Net contains.
191
+ # It will return 0 for invalid requests (ie. bad prefix or prefix is shorter than that of this network).
192
+ # It will also return 0 if the result exceeds the capacity of a 128-bit integer (ie. if you want the # of /128 a /0 will hold)
193
+ def subnet_count(prefix_len)
194
+ if (prefix_len <= self.netmask.prefix_len || prefix_len > 128 || prefix_len - self.netmask.prefix_len >= 128)
195
+ return 0
196
+ end
197
+ return 1 << (prefix_len - self.netmask.prefix_len)
198
+ end
199
+
200
+ # summ creates a summary address from this IPv6Net and another.
201
+ # It returns nil if the two networks are incapable of being summarized.
202
+ def summ(other)
203
+ if (!other.kind_of?(IPv6Net))
204
+ raise ArgumentError, "Expected an IPv6Net object for 'other' but got a #{other.class}."
205
+ end
206
+
207
+ # netmasks must be identical
208
+ if (self.netmask.prefix_len != other.netmask.prefix_len)
209
+ return nil
210
+ end
211
+
212
+ # merge-able networks will be identical if you right shift them by the number of bits in the hostmask + 1
213
+ shift = 128 - self.netmask.prefix_len + 1
214
+ addr = self.network.addr >> shift
215
+ otherAddr = other.network.addr >> shift
216
+ if (addr != otherAddr)
217
+ return nil
218
+ end
219
+ return self.resize(self.netmask.prefix_len - 1)
220
+ end
221
+
222
+ # to_s returns the IPv6Net as a String
223
+ def to_s()
224
+ return @base.to_s + @m128.to_s
225
+ end
226
+
227
+ # version returns "6" for IPv6
228
+ def version()
229
+ return 6
230
+ end
231
+
232
+
233
+ protected
234
+
235
+ # grow decreases the prefix length as much as possible without crossing a bit boundary.
236
+ def grow()
237
+ addr = self.network.addr
238
+ mask = self.netmask.mask
239
+ prefix_len = self.netmask.prefix_len
240
+ self.netmask.prefix_len.downto(0) do
241
+ mask = (mask << 1) & NetAddr::F128
242
+ if addr|mask != mask || prefix_len == 0 # // bit boundary crossed when there are '1' bits in the host portion
243
+ break
244
+ end
245
+ prefix_len -= 1
246
+ end
247
+
248
+ return IPv6Net.new(IPv6.new(addr),Mask128.new(prefix_len))
249
+ end
250
+
251
+ # nth_next_sib returns the nth next sibling network or nil if address space exceeded.
252
+ def nth_next_sib(nth)
253
+ if (nth < 0)
254
+ return nil
255
+ end
256
+
257
+ shift = 128 - self.netmask.prefix_len
258
+ addr = ((self.network.addr>>shift) + nth) << shift
259
+ if addr > NetAddr::F128
260
+ return nil
261
+ end
262
+ return IPv6Net.new(IPv6.new(addr), self.netmask)
263
+ end
264
+
265
+ end # end class IPv6Net
266
+
267
+ end # end module