@@ -82,6 +82,32 @@ class IPAddr
8282 \z
8383 }xi
8484
85+ # Raised when the provided IP address is an invalid address.
86+ class InvalidAddress < ArgumentError ; end
87+
88+ # Raised when the provided IP address is of an unsupported address family.
89+ class UnsupportedAddressFamily < ArgumentError ; end
90+
91+ # Raised when an octet contains a zero-filled number.
92+ # Example: 192.162.022.001
93+ class ZeroFilledNumber < ArgumentError ; end
94+
95+ # Raised when an address is a mix of address families.
96+ class InconsistentAddressFamily < ArgumentError ; end
97+
98+ # Raised when an address family is unspecified and cannot be reliability
99+ # determined (for example: if an Integer is provided instead of a string).
100+ class UnspecifiedAddressFamily < ArgumentError ; end
101+
102+ # Raised when the address is an invalid IPv4 address.
103+ class InvalidIPv4 < ArgumentError ; end
104+
105+ # Raised when the address is an invalid IPv6 address.
106+ class InvalidIPv6 < ArgumentError ; end
107+
108+ # Raised when the address is an invalid length.
109+ class InvalidLength < ArgumentError ; end
110+
85111 # Returns the address family of this IP address.
86112 attr_reader :family
87113
@@ -100,7 +126,7 @@ def IPAddr::ntop(addr)
100126 when 16
101127 s = IN6FORMAT % addr . unpack ( 'n8' )
102128 else
103- raise ArgumentError , "unsupported address family"
129+ raise UnsupportedAddressFamily , "unsupported address family"
104130 end
105131 return s
106132 end
@@ -226,7 +252,7 @@ def hton
226252 ( @addr >> ( 112 - 16 * i ) ) & 0xffff
227253 } . pack ( 'n8' )
228254 else
229- raise "unsupported address family"
255+ raise UnsupportedAddressFamily , "unsupported address family"
230256 end
231257 end
232258
@@ -258,7 +284,7 @@ def ipv4_compat?
258284 # into an IPv4-mapped IPv6 address.
259285 def ipv4_mapped
260286 if !ipv4?
261- raise ArgumentError , "not an IPv4 address"
287+ raise InvalidIPv4 , "not an IPv4 address"
262288 end
263289 return self . clone . set ( @addr | 0xffff00000000 , Socket ::AF_INET6 )
264290 end
@@ -267,7 +293,7 @@ def ipv4_mapped
267293 # into an IPv4-compatible IPv6 address.
268294 def ipv4_compat
269295 if !ipv4?
270- raise ArgumentError , "not an IPv4 address"
296+ raise InvalidIPv4 , "not an IPv4 address"
271297 end
272298 return self . clone . set ( @addr , Socket ::AF_INET6 )
273299 end
@@ -291,22 +317,22 @@ def reverse
291317 when Socket ::AF_INET6
292318 return ip6_arpa
293319 else
294- raise "unsupported address family"
320+ raise UnsupportedAddressFamily , "unsupported address family"
295321 end
296322 end
297323
298324 # Returns a string for DNS reverse lookup compatible with RFC3172.
299325 def ip6_arpa
300326 if !ipv6?
301- raise ArgumentError , "not an IPv6 address"
327+ raise InvalidIPv6 , "not an IPv6 address"
302328 end
303329 return _reverse + ".ip6.arpa"
304330 end
305331
306332 # Returns a string for DNS reverse lookup compatible with RFC1886.
307333 def ip6_int
308334 if !ipv6?
309- raise ArgumentError , "not an IPv6 address"
335+ raise InvalidIPv6 , "not an IPv6 address"
310336 end
311337 return _reverse + ".ip6.int"
312338 end
@@ -346,7 +372,7 @@ def to_range
346372 when Socket ::AF_INET6
347373 end_addr = ( @addr | ( IN6MASK ^ @mask_addr ) )
348374 else
349- raise "unsupported address family"
375+ raise UnsupportedAddressFamily , "unsupported address family"
350376 end
351377
352378 return clone . set ( begin_addr , @family ) ..clone . set ( end_addr , @family )
@@ -361,29 +387,31 @@ def inspect
361387 when Socket ::AF_INET6
362388 af = "IPv6"
363389 else
364- raise "unsupported address family"
390+ raise UnsupportedAddressFamily , "unsupported address family"
365391 end
366392 return sprintf ( "#<%s: %s:%s/%s>" , self . class . name ,
367393 af , _to_string ( @addr ) , _to_string ( @mask_addr ) )
368394 end
369395
370396 protected
371397
398+
399+
372400 # Set +@addr+, the internal stored ip address, to given +addr+. The
373401 # parameter +addr+ is validated using the first +family+ member,
374402 # which is +Socket::AF_INET+ or +Socket::AF_INET6+.
375403 def set ( addr , *family )
376404 case family [ 0 ] ? family [ 0 ] : @family
377405 when Socket ::AF_INET
378406 if addr < 0 || addr > IN4MASK
379- raise ArgumentError , "invalid address"
407+ raise InvalidAddress , "invalid address"
380408 end
381409 when Socket ::AF_INET6
382410 if addr < 0 || addr > IN6MASK
383- raise ArgumentError , "invalid address"
411+ raise InvalidAddress , "invalid address"
384412 end
385413 else
386- raise ArgumentError , "unsupported address family"
414+ raise UnsupportedAddressFamily , "unsupported address family"
387415 end
388416 @addr = addr
389417 if family [ 0 ]
@@ -400,7 +428,7 @@ def mask!(mask)
400428 else
401429 m = IPAddr . new ( mask )
402430 if m . family != @family
403- raise ArgumentError , "address family is not same"
431+ raise InconsistentAddressFamily , "address family is not same"
404432 end
405433 @mask_addr = m . to_i
406434 @addr &= @mask_addr
@@ -412,18 +440,18 @@ def mask!(mask)
412440 case @family
413441 when Socket ::AF_INET
414442 if prefixlen < 0 || prefixlen > 32
415- raise ArgumentError , "invalid length"
443+ raise InvalidLength , "invalid length"
416444 end
417445 masklen = 32 - prefixlen
418446 @mask_addr = ( ( IN4MASK >> masklen ) << masklen )
419447 when Socket ::AF_INET6
420448 if prefixlen < 0 || prefixlen > 128
421- raise ArgumentError , "invalid length"
449+ raise InvalidLength , "invalid length"
422450 end
423451 masklen = 128 - prefixlen
424452 @mask_addr = ( ( IN6MASK >> masklen ) << masklen )
425453 else
426- raise "unsupported address family"
454+ raise UnsupportedAddressFamily , "unsupported address family"
427455 end
428456 @addr = ( ( @addr >> masklen ) << masklen )
429457 return self
@@ -457,9 +485,9 @@ def initialize(addr = '::', family = Socket::AF_UNSPEC)
457485 @mask_addr = ( family == Socket ::AF_INET ) ? IN4MASK : IN6MASK
458486 return
459487 when Socket ::AF_UNSPEC
460- raise ArgumentError , "address family must be specified"
488+ raise UnspecifiedAddressFamily , "address family must be specified"
461489 else
462- raise ArgumentError , "unsupported address family: #{ family } "
490+ raise UnsupportedAddressFamily , "unsupported address family: #{ family } "
463491 end
464492 end
465493 prefix , prefixlen = addr . split ( '/' )
@@ -482,7 +510,7 @@ def initialize(addr = '::', family = Socket::AF_UNSPEC)
482510 @family = Socket ::AF_INET6
483511 end
484512 if family != Socket ::AF_UNSPEC && @family != family
485- raise ArgumentError , "address family mismatch"
513+ raise InconsistentAddressFamily , "address family mismatch"
486514 end
487515 if prefixlen
488516 mask! ( prefixlen )
@@ -511,8 +539,8 @@ def in_addr(addr)
511539 octets = m . captures
512540 end
513541 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"
542+ ( n = s . to_i ) < 256 or raise InvalidAddress , "invalid address"
543+ s . match ( /\A 0./ ) and raise ZeroFilledNumber , "zero-filled number is ambiguous"
516544 i << 8 | n
517545 }
518546 end
@@ -529,18 +557,18 @@ def in6_addr(left)
529557 right = ''
530558 when RE_IPV6ADDRLIKE_COMPRESSED
531559 if $4
532- left . count ( ':' ) <= 6 or raise ArgumentError , "invalid address"
560+ left . count ( ':' ) <= 6 or raise InvalidAddress , "invalid address"
533561 addr = in_addr ( $~[ 4 , 4 ] )
534562 left = $1
535563 right = $3 + '0:0'
536564 else
537- left . count ( ':' ) <= 7 or raise ArgumentError , "invalid address"
565+ left . count ( ':' ) <= 7 or raise InvalidAddress , "invalid address"
538566 left = $1
539567 right = $2
540568 addr = 0
541569 end
542570 else
543- raise ArgumentError , "invalid address"
571+ raise InvalidAddress , "invalid address"
544572 end
545573 l = left . split ( ':' )
546574 r = right . split ( ':' )
@@ -560,7 +588,7 @@ def addr_mask(addr)
560588 when Socket ::AF_INET6
561589 return addr & IN6MASK
562590 else
563- raise "unsupported address family"
591+ raise UnsupportedAddressFamily , "unsupported address family"
564592 end
565593 end
566594
@@ -573,7 +601,7 @@ def _reverse
573601 when Socket ::AF_INET6
574602 return ( "%.32x" % @addr ) . reverse! . gsub! ( /.(?!$)/ , '\&.' )
575603 else
576- raise "unsupported address family"
604+ raise UnsupportedAddressFamily , "unsupported address family"
577605 end
578606 end
579607
@@ -586,7 +614,7 @@ def _to_string(addr)
586614 when Socket ::AF_INET6
587615 return ( ( "%.32x" % addr ) . gsub! ( /.{4}(?!$)/ , '\&:' ) )
588616 else
589- raise "unsupported address family"
617+ raise UnsupportedAddressFamily , "unsupported address family"
590618 end
591619 end
592620
@@ -713,19 +741,13 @@ def test_s_new
713741
714742 assert_equal("2001:200:300::", IPAddr.new("[2001:200:300::]/48").to_s)
715743
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- }
744+ assert_raises(IPAddr::InvalidAddress) { IPAddr.new('192.168.0.256') }
745+ assert_raises(IPAddr::ZeroFilledNumber) { IPAddr.new('192.168.0.011') }
746+ assert_raises(IPAddr::InvalidAddress) { IPAddr.new("fe80::1%fxp0") }
747+ assert_raises(IPAddr::InconsistentAddressFamily) { IPAddr.new("::1/255.255.255.0") }
748+ assert_raises(IPAddr::UnspecifiedAddressFamily) { IPAddr.new(1) }
749+ assert_raises(IPAddr::InconsistentAddressFamily) { IPAddr.new("::ffff:192.168.1.2/120", Socket::AF_INET) }
750+ assert_raises(IPAddr::InvalidAddress) { IPAddr.new("[192.168.1.2]/120") }
729751 end
730752
731753 def test_s_new_ntoh
@@ -786,14 +808,14 @@ def test_reverse
786808
787809 def test_ip6_arpa
788810 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 ) {
811+ assert_raises(IPAddr::InvalidIPv6 ) {
790812 IPAddr.new("192.168.2.1").ip6_arpa
791813 }
792814 end
793815
794816 def test_ip6_int
795817 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 ) {
818+ assert_raises(IPAddr::InvalidIPv6 ) {
797819 IPAddr.new("192.168.2.1").ip6_int
798820 }
799821 end
0 commit comments