1 # faithd, ruby version. requires v6-enabled ruby.
3 # highly experimental (not working right at all) and very limited
6 # $Id: faithd.rb,v 1.1.1.1 1999/08/08 23:29:31 itojun Exp $
7 # $FreeBSD: src/usr.sbin/faithd/test/faithd.rb,v 1.1 2000/01/27 09:28:38 shin Exp $
8 # $DragonFly: src/usr.sbin/faithd/test/faithd.rb,v 1.2 2003/06/17 04:29:53 dillon Exp $
13 # XXX should be derived from system headers
19 # TODO: OOB data handling
20 def tcpcopy(s1, s2, m)
21 STDERR.print "tcpcopy #{s1} #{s2}\n" if DEBUG
33 STDERR.print "tcpcopy #{s1} #{s2} finished\n" if DEBUG
38 def relay_ftp_passiveconn(s6, s4, dport6, dport4)
40 d6 = TCPserver.open("::", dport6).accept
41 d4 = TCPsocket.open(s4.getpeer[3], dport4)
43 t[0] = Thread.start do
46 t[1] = Thread.start do
57 def ftp_parse_2428(line)
58 if (line[0] != line[line.length - 1])
61 t = line.split(line[0 .. 0]) # as string
62 if (t.size != 4 || t[1] !~ /^[12]$/ || t[3] !~ /^\d+$/)
68 def relay_ftp_command(s6, s4, state)
69 STDERR.print "relay_ftp_command start\n" if DEBUG
72 STDERR.print "s6.gets\n" if DEBUG
74 STDERR.print "line is #{line}\n" if DEBUG
80 STDERR.print "line is #{line}\n" if DEBUG
81 if (line =~ /^EPSV\r\n/i)
82 STDERR.print "EPSV -> PASV\n" if DEBUG
85 elsif (line =~ /^EPRT\s+(.+)\r\n/i)
86 t = ftp_parse_2428($1)
88 s6.puts "501 illegal parameter to EPRT\r\n"
92 # some tricks should be here
93 s6.puts "501 illegal parameter to EPRT\r\n"
96 STDERR.print "fail: send #{line} as is\n" if DEBUG
105 STDERR.print "relay_ftp_command finish\n" if DEBUG
109 def relay_ftp_status(s4, s6, state)
110 STDERR.print "relay_ftp_status start\n" if DEBUG
118 # translate then copy
121 next if line =~ /^\d\d\d-/
122 next if line !~ /^\d/
124 # special post-processing
126 when /^221 / # result to QUIT
131 break if (line =~ /^\d\d\d /)
138 STDERR.print "relay_ftp_status finish\n" if DEBUG
142 def relay_ftp(sock, name)
143 STDERR.print "relay_ftp(#{sock}, #{name})\n" if DEBUG
145 STDERR.print "relay_ftp(#{sock}, #{name}) accepting\n" if DEBUG
147 STDERR.print "relay_ftp(#{sock}, #{name}) accepted #{s}\n" if DEBUG
150 STDERR.print "accepted #{s} -> #{Thread.current}\n" if DEBUG
154 t = s.getsockname.unpack("x8 x12 C4")
155 dest4 = "#{t[0]}.#{t[1]}.#{t[2]}.#{t[3]}"
162 STDERR.print "IPv6 dest: #{dest6} IPv4 dest: #{dest4}\n" if DEBUG
164 STDERR.print "connect to #{dest4} #{port4}\n" if DEBUG
165 s4 = TCPsocket.open(dest4, port4)
166 STDERR.print "connected to #{dest4} #{port4}, #{s4.addr[1]}\n" if DEBUG
169 # translate status line
170 state = relay_ftp_status(s4, s6, state)
171 break if state == nil
172 # translate command line
173 state = relay_ftp_command(s6, s4, state)
174 break if state == nil
176 STDERR.print "relay_ftp(#{sock}, #{name}) closing s4\n" if DEBUG
178 STDERR.print "relay_ftp(#{sock}, #{name}) closing s6\n" if DEBUG
180 STDERR.print "relay_ftp(#{sock}, #{name}) done\n" if DEBUG
183 STDERR.print "relay_ftp(#{sock}, #{name}) finished\n" if DEBUG
186 def relay_tcp(sock, name)
187 STDERR.print "relay_tcp(#{sock}, #{name})\n" if DEBUG
189 STDERR.print "relay_tcp(#{sock}, #{name}) accepting\n" if DEBUG
191 STDERR.print "relay_tcp(#{sock}, #{name}) accepted #{s}\n" if DEBUG
194 STDERR.print "accepted #{s} -> #{Thread.current}\n" if DEBUG
198 t = s.getsockname.unpack("x8 x12 C4")
199 dest4 = "#{t[0]}.#{t[1]}.#{t[2]}.#{t[3]}"
206 STDERR.print "IPv6 dest: #{dest6} IPv4 dest: #{dest4}\n" if DEBUG
208 STDERR.print "connect to #{dest4} #{port4}\n" if DEBUG
209 s4 = TCPsocket.open(dest4, port4)
210 STDERR.print "connected to #{dest4} #{port4}, #{s4.addr[1]}\n" if DEBUG
212 threads[i] = Thread.start do
220 STDERR.print "relay_tcp(#{sock}, #{name}) wait\n" if DEBUG
222 STDERR.print "relay_tcp(#{sock}, #{name}) wait #{i}\n" if DEBUG
224 STDERR.print "relay_tcp(#{sock}, #{name}) wait #{i} done\n" if DEBUG
226 STDERR.print "relay_tcp(#{sock}, #{name}) closing s4\n" if DEBUG
228 STDERR.print "relay_tcp(#{sock}, #{name}) closing s6\n" if DEBUG
230 STDERR.print "relay_tcp(#{sock}, #{name}) done\n" if DEBUG
233 STDERR.print "relay_tcp(#{sock}, #{name}) finished\n" if DEBUG
237 STDERR.print "usage: #{$0} [-f] port...\n"
240 #------------------------------------------------------------
244 while ARGV[0] =~ /^-/ do
260 ftpport = Socket.getservbyname("ftp")
264 t = Socket.getaddrinfo(nil, port, Socket::PF_INET6, Socket::SOCK_STREAM,
265 nil, Socket::AI_PASSIVE)
267 STDERR.print "FATAL: getaddrinfo failed (port=#{port})\n"
278 s = TCPserver.new(i[3], i[1])
279 n = Socket.getnameinfo(s.getsockname, Socket::NI_NUMERICHOST|Socket::NI_NUMERICSERV).join(" port ")
280 if i[6] == IPPROTO_IPV6
281 s.setsockopt(i[6], IPV6_FAITH, 1)
283 s.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1)
289 (0 .. sockpool.size - 1).each do |i|
290 STDERR.print "listen[#{i}]: #{sockpool[i]} #{names[i]}\n" if DEBUG
294 (0 .. sockpool.size - 1).each do |i|
295 listenthreads[i] = Thread.start do
297 STDERR.print "listen[#{i}]: thread #{Thread.current}\n" if DEBUG
299 STDERR.print "listen[#{i}]: thread #{Thread.current}\n" if DEBUG
302 relay_tcp(sockpool[i], names[i])
304 relay_ftp(sockpool[i], names[i])
309 for i in listenthreads