@@ -82,6 +82,21 @@ class IPAddr
8282 \z
8383 }xi
8484
85+ # Generic IPAddr related error. Exceptions raised in this class should
86+ # inherit from Error.
87+ class Error < ArgumentError ; end
88+
89+ # Raised when the provided IP address is an invalid address.
90+ class InvalidAddressError < Error ; end
91+
92+ # Raised when the address family is invalid such as an address with an
93+ # unsupported family, an address with an inconsistent family, or an address
94+ # who's family cannot be determined.
95+ class AddressFamilyError < Error ; end
96+
97+ # Raised when the address is an invalid length.
98+ class InvalidPrefixError < InvalidAddressError ; end
99+
85100 # Returns the address family of this IP address.
86101 attr_reader :family
87102
@@ -100,7 +115,7 @@ def IPAddr::ntop(addr)
100115 when 16
101116 s = IN6FORMAT % addr . unpack ( 'n8' )
102117 else
103- raise ArgumentError , "unsupported address family"
118+ raise AddressFamilyError , "unsupported address family"
104119 end
105120 return s
106121 end
@@ -226,7 +241,7 @@ def hton
226241 ( @addr >> ( 112 - 16 * i ) ) & 0xffff
227242 } . pack ( 'n8' )
228243 else
229- raise "unsupported address family"
244+ raise AddressFamilyError , "unsupported address family"
230245 end
231246 end
232247
@@ -258,7 +273,7 @@ def ipv4_compat?
258273 # into an IPv4-mapped IPv6 address.
259274 def ipv4_mapped
260275 if !ipv4?
261- raise ArgumentError , "not an IPv4 address"
276+ raise InvalidAddressError , "not an IPv4 address"
262277 end
263278 return self . clone . set ( @addr | 0xffff00000000 , Socket ::AF_INET6 )
264279 end
@@ -267,7 +282,7 @@ def ipv4_mapped
267282 # into an IPv4-compatible IPv6 address.
268283 def ipv4_compat
269284 if !ipv4?
270- raise ArgumentError , "not an IPv4 address"
285+ raise InvalidAddressError , "not an IPv4 address"
271286 end
272287 return self . clone . set ( @addr , Socket ::AF_INET6 )
273288 end
@@ -291,22 +306,22 @@ def reverse
291306 when Socket ::AF_INET6
292307 return ip6_arpa
293308 else
294- raise "unsupported address family"
309+ raise AddressFamilyError , "unsupported address family"
295310 end
296311 end
297312
298313 # Returns a string for DNS reverse lookup compatible with RFC3172.
299314 def ip6_arpa
300315 if !ipv6?
301- raise ArgumentError , "not an IPv6 address"
316+ raise InvalidAddressError , "not an IPv6 address"
302317 end
303318 return _reverse + ".ip6.arpa"
304319 end
305320
306321 # Returns a string for DNS reverse lookup compatible with RFC1886.
307322 def ip6_int
308323 if !ipv6?
309- raise ArgumentError , "not an IPv6 address"
324+ raise InvalidAddressError , "not an IPv6 address"
310325 end
311326 return _reverse + ".ip6.int"
312327 end
@@ -346,7 +361,7 @@ def to_range
346361 when Socket ::AF_INET6
347362 end_addr = ( @addr | ( IN6MASK ^ @mask_addr ) )
348363 else
349- raise "unsupported address family"
364+ raise AddressFamilyError , "unsupported address family"
350365 end
351366
352367 return clone . set ( begin_addr , @family ) ..clone . set ( end_addr , @family )
@@ -361,7 +376,7 @@ def inspect
361376 when Socket ::AF_INET6
362377 af = "IPv6"
363378 else
364- raise "unsupported address family"
379+ raise AddressFamilyError , "unsupported address family"
365380 end
366381 return sprintf ( "#<%s: %s:%s/%s>" , self . class . name ,
367382 af , _to_string ( @addr ) , _to_string ( @mask_addr ) )
@@ -376,14 +391,14 @@ def set(addr, *family)
376391 case family [ 0 ] ? family [ 0 ] : @family
377392 when Socket ::AF_INET
378393 if addr < 0 || addr > IN4MASK
379- raise ArgumentError , "invalid address"
394+ raise InvalidAddressError , "invalid address"
380395 end
381396 when Socket ::AF_INET6
382397 if addr < 0 || addr > IN6MASK
383- raise ArgumentError , "invalid address"
398+ raise InvalidAddressError , "invalid address"
384399 end
385400 else
386- raise ArgumentError , "unsupported address family"
401+ raise AddressFamilyError , "unsupported address family"
387402 end
388403 @addr = addr
389404 if family [ 0 ]
@@ -400,7 +415,7 @@ def mask!(mask)
400415 else
401416 m = IPAddr . new ( mask )
402417 if m . family != @family
403- raise ArgumentError , "address family is not same"
418+ raise InvalidPrefixError , "address family is not same"
404419 end
405420 @mask_addr = m . to_i
406421 @addr &= @mask_addr
@@ -412,18 +427,18 @@ def mask!(mask)
412427 case @family
413428 when Socket ::AF_INET
414429 if prefixlen < 0 || prefixlen > 32
415- raise ArgumentError , "invalid length"
430+ raise InvalidPrefixError , "invalid length"
416431 end
417432 masklen = 32 - prefixlen
418433 @mask_addr = ( ( IN4MASK >> masklen ) << masklen )
419434 when Socket ::AF_INET6
420435 if prefixlen < 0 || prefixlen > 128
421- raise ArgumentError , "invalid length"
436+ raise InvalidPrefixError , "invalid length"
422437 end
423438 masklen = 128 - prefixlen
424439 @mask_addr = ( ( IN6MASK >> masklen ) << masklen )
425440 else
426- raise "unsupported address family"
441+ raise AddressFamilyError , "unsupported address family"
427442 end
428443 @addr = ( ( @addr >> masklen ) << masklen )
429444 return self
@@ -457,9 +472,9 @@ def initialize(addr = '::', family = Socket::AF_UNSPEC)
457472 @mask_addr = ( family == Socket ::AF_INET ) ? IN4MASK : IN6MASK
458473 return
459474 when Socket ::AF_UNSPEC
460- raise ArgumentError , "address family must be specified"
475+ raise AddressFamilyError , "address family must be specified"
461476 else
462- raise ArgumentError , "unsupported address family: #{ family } "
477+ raise AddressFamilyError , "unsupported address family: #{ family } "
463478 end
464479 end
465480 prefix , prefixlen = addr . split ( '/' )
@@ -482,7 +497,7 @@ def initialize(addr = '::', family = Socket::AF_UNSPEC)
482497 @family = Socket ::AF_INET6
483498 end
484499 if family != Socket ::AF_UNSPEC && @family != family
485- raise ArgumentError , "address family mismatch"
500+ raise AddressFamilyError , "address family mismatch"
486501 end
487502 if prefixlen
488503 mask! ( prefixlen )
@@ -511,8 +526,8 @@ def in_addr(addr)
511526 octets = m . captures
512527 end
513528 octets . inject ( 0 ) { |i , s |
514- ( n = s . to_i ) < 256 or raise ArgumentError , "invalid address"
515- s . match ( /\A 0./ ) and raise ArgumentError , "zero-filled number is ambiguous"
529+ ( n = s . to_i ) < 256 or raise InvalidAddressError , "invalid address"
530+ s . match ( /\A 0./ ) and raise InvalidAddressError , "zero-filled number in IPv4 address is ambiguous"
516531 i << 8 | n
517532 }
518533 end
@@ -529,18 +544,18 @@ def in6_addr(left)
529544 right = ''
530545 when RE_IPV6ADDRLIKE_COMPRESSED
531546 if $4
532- left . count ( ':' ) <= 6 or raise ArgumentError , "invalid address"
547+ left . count ( ':' ) <= 6 or raise InvalidAddressError , "invalid address"
533548 addr = in_addr ( $~[ 4 , 4 ] )
534549 left = $1
535550 right = $3 + '0:0'
536551 else
537- left . count ( ':' ) <= 7 or raise ArgumentError , "invalid address"
552+ left . count ( ':' ) <= 7 or raise InvalidAddressError , "invalid address"
538553 left = $1
539554 right = $2
540555 addr = 0
541556 end
542557 else
543- raise ArgumentError , "invalid address"
558+ raise InvalidAddressError , "invalid address"
544559 end
545560 l = left . split ( ':' )
546561 r = right . split ( ':' )
@@ -560,7 +575,7 @@ def addr_mask(addr)
560575 when Socket ::AF_INET6
561576 return addr & IN6MASK
562577 else
563- raise "unsupported address family"
578+ raise AddressFamilyError , "unsupported address family"
564579 end
565580 end
566581
@@ -573,7 +588,7 @@ def _reverse
573588 when Socket ::AF_INET6
574589 return ( "%.32x" % @addr ) . reverse! . gsub! ( /.(?!$)/ , '\&.' )
575590 else
576- raise "unsupported address family"
591+ raise AddressFamilyError , "unsupported address family"
577592 end
578593 end
579594
@@ -586,7 +601,7 @@ def _to_string(addr)
586601 when Socket ::AF_INET6
587602 return ( ( "%.32x" % addr ) . gsub! ( /.{4}(?!$)/ , '\&:' ) )
588603 else
589- raise "unsupported address family"
604+ raise AddressFamilyError , "unsupported address family"
590605 end
591606 end
592607
@@ -713,19 +728,15 @@ def test_s_new
713728
714729 assert_equal("2001:200:300::", IPAddr.new("[2001:200:300::]/48").to_s)
715730
716- [
717- ["192.168.0.256"],
718- ["192.168.0.011"],
719- ["fe80::1%fxp0"],
720- ["::1/255.255.255.0"],
721- [IPAddr.new("::1").to_i],
722- ["::ffff:192.168.1.2/120", Socket::AF_INET],
723- ["[192.168.1.2]/120"],
724- ].each { |args|
725- assert_raises(ArgumentError) {
726- IPAddr.new(*args)
727- }
728- }
731+ assert_raises(IPAddr::InvalidAddressError) { IPAddr.new("192.168.0.256") }
732+ assert_raises(IPAddr::InvalidAddressError) { IPAddr.new("192.168.0.011") }
733+ assert_raises(IPAddr::InvalidAddressError) { IPAddr.new("fe80::1%fxp0") }
734+ assert_raises(IPAddr::InvalidAddressError) { IPAddr.new("[192.168.1.2]/120") }
735+ assert_raises(IPAddr::InvalidPrefixError) { IPAddr.new("::1/255.255.255.0") }
736+ assert_raises(IPAddr::InvalidPrefixError) { IPAddr.new("::1/129") }
737+ assert_raises(IPAddr::InvalidPrefixError) { IPAddr.new("192.168.0.1/33") }
738+ assert_raises(IPAddr::AddressFamilyError) { IPAddr.new(1) }
739+ assert_raises(IPAddr::AddressFamilyError) { IPAddr.new("::ffff:192.168.1.2/120", Socket::AF_INET) }
729740 end
730741
731742 def test_s_new_ntoh
@@ -786,14 +797,14 @@ def test_reverse
786797
787798 def test_ip6_arpa
788799 assert_equal("f.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.2.0.0.0.5.0.5.0.e.f.f.3.ip6.arpa", IPAddr.new("3ffe:505:2::f").ip6_arpa)
789- assert_raises(ArgumentError ) {
800+ assert_raises(IPAddr::InvalidAddressError ) {
790801 IPAddr.new("192.168.2.1").ip6_arpa
791802 }
792803 end
793804
794805 def test_ip6_int
795806 assert_equal("f.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.2.0.0.0.5.0.5.0.e.f.f.3.ip6.int", IPAddr.new("3ffe:505:2::f").ip6_int)
796- assert_raises(ArgumentError ) {
807+ assert_raises(IPAddr::InvalidAddressError ) {
797808 IPAddr.new("192.168.2.1").ip6_int
798809 }
799810 end
0 commit comments