source: EcnlProtoTool/trunk/mrbgems/mruby-ipaddr/mrblib/ipaddr.rb@ 331

Last change on this file since 331 was 331, checked in by coas-nagasima, 6 years ago

prototoolに関連するプロジェクトをnewlibからmuslを使うよう変更・更新
ntshellをnewlibの下位の実装から、muslのsyscallの実装に変更・更新
以下のOSSをアップデート
・mruby-1.3.0
・musl-1.1.18
・onigmo-6.1.3
・tcc-0.9.27
以下のOSSを追加
・openssl-1.1.0e
・curl-7.57.0
・zlib-1.2.11
以下のmrbgemsを追加
・iij/mruby-digest
・iij/mruby-env
・iij/mruby-errno
・iij/mruby-iijson
・iij/mruby-ipaddr
・iij/mruby-mock
・iij/mruby-require
・iij/mruby-tls-openssl

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-ruby
File size: 3.8 KB
Line 
1class IPAddr
2 # @family is either AF_INET or AF_INET6.
3 # @addr is a String represents IP address as an octet string.
4 # @mask is a String represents netmask as an octet string.
5
6 def initialize(addr='::', family=Socket::AF_UNSPEC)
7 a, m = addr.split('/', 2)
8 if family == Socket::AF_UNSPEC
9 begin
10 @addr = IPSocket.pton(Socket::AF_INET, a)
11 @family = Socket::AF_INET
12 rescue ArgumentError
13 @addr = IPSocket.pton(Socket::AF_INET6, a)
14 @family = Socket::AF_INET6
15 end
16 else
17 @addr = IPSocket.pton(family, a)
18 @family = family
19 end
20 if m
21 initialize_makemask(m)
22 _applymask
23 else
24 if @family == Socket::AF_INET
25 @mask = "\xff" * 4
26 elsif @family == Socket::AF_INET6
27 @mask = "\xff" * 16
28 end
29 end
30 end
31
32 def initialize_makemask(m)
33 if @family == Socket::AF_INET and m.include?('.')
34 @mask = IPSocket.pton(Socket::AF_INET, m)
35 elsif @family == Socket::AF_INET6 and m.include?(':')
36 @mask = IPSocket.pton(Socket::AF_INET6, m)
37 else
38 ma = []
39 mi = m.to_i
40 mlen = (ipv4?) ? 32 : 128
41 while mlen > 0
42 if mi >= 8
43 ma << 0xff
44 elsif mi <= 0
45 ma << 0
46 else
47 ma << (0xff ^ (0xff >> mi))
48 end
49 mi -= 8
50 mlen -= 8
51 end
52 @mask = ma.pack("C*")
53 end
54 end
55
56 def self.new_ntoh(addr)
57 raise TypeError, "can't convert to String" unless addr.is_a? String
58 if addr.size == 4
59 a = IPAddr.new("0.0.0.0")
60 f = Socket::AF_INET
61 elsif addr.size == 16
62 a = IPAddr.new("::")
63 f = Socket::AF_INET6
64 else
65 raise ArgumentError, "length of addr must be 4 or 16"
66 end
67 a.set2(addr, f)
68 end
69
70 # private
71 def _applymask
72 a = @addr.unpack("C*")
73 m = @mask.unpack("C*")
74 (0...a.size).each { |i| a[i] &= m[i] }
75 @addr = a.pack("C*")
76 end
77
78 # private
79 def _mask
80 @mask
81 end
82
83 #def &(other)
84 #def <<(num)
85
86 def <=>(other)
87 if @family == other.family
88 @addr <=> other.hton
89 else
90 nil
91 end
92 end
93
94 def ==(other)
95 if other.is_a? String
96 self.eql? IPAddr.new(other)
97 else
98 self.eql? other
99 end
100 end
101
102 #def ===(ipaddr)
103 #alias include? ===
104 #def >>(num)
105
106 def eql?(other)
107 @addr == other.hton and @mask == other._mask and @family == other.family
108 end
109
110 def family
111 @family
112 end
113
114 def hash
115 @addr.hash ^ @mask.hash ^ @family.hash
116 end
117
118 def hton
119 @addr
120 end
121
122 def inspect
123 def a2s(a)
124 if @family == Socket::AF_INET
125 return a.unpack("C*").map { |b| format("%u", b) }.join('.')
126 else
127 bytes = a.unpack("C*").map { |x| format "%02x", x }
128 return (0..7).map { |i| bytes[i*2, 2].join }.join(':')
129 end
130 end
131 format "#<%s: %s:%s/%s>",
132 self.class, (ipv4? ? 'IPv4' : 'IPv6'), a2s(@addr), a2s(@mask)
133 end
134
135 def ipv4?
136 @family == Socket::AF_INET
137 end
138
139 def ipv6?
140 @family == Socket::AF_INET6
141 end
142
143 def mask(prefixlen)
144 a = @addr.unpack("C*")
145 i = prefixlen.divmod(8)[0] # mruby 1.0.0 lacks Integer#div
146 if prefixlen % 8 != 0
147 a[i] &= ~(0xff >> (prefixlen % 8))
148 i += 1
149 end
150 (i..a.size-1).each { |i| a[i] = 0 }
151 IPAddr.new('::', Socket::AF_INET6).set2(a.pack("C*"), @family)
152 end
153
154 # private
155 def set2(a, f)
156 @addr = a
157 @family = f
158 if @family == Socket::AF_INET
159 @mask = "\xff" * 4
160 elsif @family == Socket::AF_INET6
161 @mask = "\xff" * 16
162 end
163 self
164 end
165
166 def to_s
167 IPAddr.ntop(@addr)
168 end
169
170 def ~
171 a = @addr.unpack("C*").map { |b| b ^ 0xff }.pack("C*")
172 IPAddr.new('::', Socket::AF_INET6).set2(a, @family)
173 end
174
175 alias to_string to_s
176
177 # mruby extension
178 def is_netaddr?(prefixlen)
179 (self <=> self.mask(prefixlen)) == 0
180 end
181
182 def is_bcastaddr?(prefixlen)
183 i = ~self
184 (i <=> i.mask(prefixlen)) == 0
185 end
186end
Note: See TracBrowser for help on using the repository browser.