Project

General

Profile

Feature #10911 ยป ipaddr-ipv6-zone-id-10911.patch

jeremyevans0 (Jeremy Evans), 10/31/2019 04:16 PM

View differences:

lib/ipaddr.rb
226 226
      str = sprintf('::%s%d.%d.%d.%d', $1, $2.hex / 256, $2.hex % 256, $3.hex / 256, $3.hex % 256)
227 227
    end
228 228

  
229
    if @family == Socket::AF_INET6
230
      str << zone_id.to_s
231
    end
232

  
229 233
    str
230 234
  end
231 235

  
......
404 408

  
405 409
  # Returns a hash value used by Hash, Set, and Array classes
406 410
  def hash
407
    return ([@addr, @mask_addr].hash << 1) | (ipv4? ? 0 : 1)
411
    return ([@addr, @mask_addr, @zone_id].hash << 1) | (ipv4? ? 0 : 1)
408 412
  end
409 413

  
410 414
  # Creates a Range object for the network address.
......
460 464
      af = "IPv4"
461 465
    when Socket::AF_INET6
462 466
      af = "IPv6"
467
      zone_id = @zone_id.to_s
463 468
    else
464 469
      raise AddressFamilyError, "unsupported address family"
465 470
    end
466
    return sprintf("#<%s: %s:%s/%s>", self.class.name,
467
                   af, _to_string(@addr), _to_string(@mask_addr))
471
    return sprintf("#<%s: %s:%s%s/%s>", self.class.name,
472
                   af, _to_string(@addr), zone_id, _to_string(@mask_addr))
473
  end
474

  
475
  # Returns the IPv6 zone identifier, if present.
476
  # Raises InvalidAddressError if not an IPv6 address.
477
  def zone_id
478
    if @family == Socket::AF_INET6
479
      @zone_id
480
    else
481
      raise InvalidAddressError, "not an IPv6 address"
482
    end
483
  end
484

  
485
  # Returns the IPv6 zone identifier, if present.
486
  # Raises InvalidAddressError if not an IPv6 address.
487
  def zone_id=(zid)
488
    if @family == Socket::AF_INET6
489
      case zid
490
      when nil, /\A%(\w+)\z/
491
        @zone_id = zid
492
      else
493
        raise InvalidAddressError, "invalid zone identifier for address"
494
      end
495
    else
496
      raise InvalidAddressError, "not an IPv6 address"
497
    end
468 498
  end
469 499

  
470 500
  protected
......
572 602
      prefix = $1
573 603
      family = Socket::AF_INET6
574 604
    end
605
    if prefix =~ /\A(.*)(%\w+)\z/
606
      prefix = $1
607
      zone_id = $2
608
      family = Socket::AF_INET6
609
    end
575 610
    # It seems AI_NUMERICHOST doesn't do the job.
576 611
    #Socket.getaddrinfo(left, nil, Socket::AF_INET6, Socket::SOCK_STREAM, nil,
577 612
    #                  Socket::AI_NUMERICHOST)
......
585 620
    if !@addr && (family == Socket::AF_UNSPEC || family == Socket::AF_INET6)
586 621
      @addr = in6_addr(prefix)
587 622
      @family = Socket::AF_INET6
623
      @zone_id = zone_id
588 624
    end
589 625
    if family != Socket::AF_UNSPEC && @family != family
590 626
      raise AddressFamilyError, "address family mismatch"
test/test_ipaddr.rb
43 43
    assert_equal("3ffe:0505:0002:0000:0000:0000:0000:0000", a.to_string)
44 44
    assert_equal(Socket::AF_INET6, a.family)
45 45
    assert_equal(48, a.prefix)
46
    assert_nil(a.zone_id)
47

  
48
    a = IPAddr.new("fe80::1%ab0")
49
    assert_equal("fe80::1%ab0", a.to_s)
50
    assert_equal("fe80:0000:0000:0000:0000:0000:0000:0001", a.to_string)
51
    assert_equal(Socket::AF_INET6, a.family)
52
    assert_equal(false, a.ipv4?)
53
    assert_equal(true, a.ipv6?)
54
    assert_equal("#<IPAddr: IPv6:fe80:0000:0000:0000:0000:0000:0000:0001%ab0/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff>", a.inspect)
55
    assert_equal(128, a.prefix)
56
    assert_equal('%ab0', a.zone_id)
46 57

  
47 58
    a = IPAddr.new("0.0.0.0")
48 59
    assert_equal("0.0.0.0", a.to_s)
......
87 98

  
88 99
    assert_raise(IPAddr::InvalidAddressError) { IPAddr.new("192.168.0.256") }
89 100
    assert_raise(IPAddr::InvalidAddressError) { IPAddr.new("192.168.0.011") }
90
    assert_raise(IPAddr::InvalidAddressError) { IPAddr.new("fe80::1%fxp0") }
101
    assert_raise(IPAddr::InvalidAddressError) { IPAddr.new("fe80::1%") }
102
    assert_raise(IPAddr::InvalidAddressError) { IPAddr.new("fe80::1%]") }
91 103
    assert_raise(IPAddr::InvalidAddressError) { IPAddr.new("[192.168.1.2]/120") }
92 104
    assert_raise(IPAddr::InvalidAddressError) { IPAddr.new("[2001:200:300::]\nINVALID") }
93 105
    assert_raise(IPAddr::InvalidAddressError) { IPAddr.new("192.168.0.1/32\nINVALID") }
......
200 212
    assert_equal("3ffe:0505:0002:0000:0000:0000:0000:0001", IPAddr.new("3ffe:505:2::1").to_string)
201 213
    assert_equal("3ffe:505:2::1", IPAddr.new("3ffe:505:2::1").to_s)
202 214
  end
215

  
216
  def test_zone_id
217
    a = IPAddr.new("192.168.1.2")
218
    assert_raise(IPAddr::InvalidAddressError) { a.zone_id = '%ab0' }
219
    assert_raise(IPAddr::InvalidAddressError) { a.zone_id }
220

  
221
    a = IPAddr.new("1:2:3:4:5:6:7:8")
222
    a.zone_id = '%ab0'
223
    assert_equal('%ab0', a.zone_id)
224
    assert_equal("1:2:3:4:5:6:7:8%ab0", a.to_s)
225
    assert_raise(IPAddr::InvalidAddressError) { a.zone_id = '%' }
226
  end
203 227
end
204 228

  
205 229
class TC_Operator < Test::Unit::TestCase
206
-