PageRenderTime 113ms CodeModel.GetById 28ms RepoModel.GetById 7ms app.codeStats 0ms

/usr.sbin/faithd/test/faithd.rb

http://github.com/davshao/dflygsocdrm
Ruby | 313 lines | 268 code | 28 blank | 17 comment | 50 complexity | a17773931ec3764707aef9d70afa47a0 MD5 | raw file
Possible License(s): AGPL-1.0, CC-BY-SA-3.0, LGPL-2.0, GPL-3.0, LGPL-2.1, LGPL-3.0, MPL-2.0-no-copyleft-exception, 0BSD, BSD-3-Clause, GPL-2.0
  1. # faithd, ruby version. requires v6-enabled ruby.
  2. #
  3. # highly experimental (not working right at all) and very limited
  4. # functionality.
  5. #
  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 $
  9. require "socket"
  10. require "thread"
  11. # XXX should be derived from system headers
  12. IPPROTO_IPV6 = 41
  13. IPV6_FAITH = 29
  14. DEBUG = true
  15. DEBUG_LOOPBACK = true
  16. # TODO: OOB data handling
  17. def tcpcopy(s1, s2, m)
  18. STDERR.print "tcpcopy #{s1} #{s2}\n" if DEBUG
  19. buf = ""
  20. while TRUE
  21. begin
  22. buf = s1.sysread(100)
  23. s2.syswrite(buf)
  24. rescue EOFError
  25. break
  26. rescue IOError
  27. break
  28. end
  29. end
  30. STDERR.print "tcpcopy #{s1} #{s2} finished\n" if DEBUG
  31. s1.shutdown(0)
  32. s2.shutdown(1)
  33. end
  34. def relay_ftp_passiveconn(s6, s4, dport6, dport4)
  35. Thread.start do
  36. d6 = TCPserver.open("::", dport6).accept
  37. d4 = TCPsocket.open(s4.getpeer[3], dport4)
  38. t = []
  39. t[0] = Thread.start do
  40. tcpcopy(d6, d4)
  41. end
  42. t[1] = Thread.start do
  43. tcpcopy(d4, d6)
  44. end
  45. for i in t
  46. i.join
  47. end
  48. d4.close
  49. d6.close
  50. end
  51. end
  52. def ftp_parse_2428(line)
  53. if (line[0] != line[line.length - 1])
  54. return nil
  55. end
  56. t = line.split(line[0 .. 0]) # as string
  57. if (t.size != 4 || t[1] !~ /^[12]$/ || t[3] !~ /^\d+$/)
  58. return nil
  59. end
  60. return t[1 .. 3]
  61. end
  62. def relay_ftp_command(s6, s4, state)
  63. STDERR.print "relay_ftp_command start\n" if DEBUG
  64. while TRUE
  65. begin
  66. STDERR.print "s6.gets\n" if DEBUG
  67. line = s6.gets
  68. STDERR.print "line is #{line}\n" if DEBUG
  69. if line == nil
  70. return nil
  71. end
  72. # translate then copy
  73. STDERR.print "line is #{line}\n" if DEBUG
  74. if (line =~ /^EPSV\r\n/i)
  75. STDERR.print "EPSV -> PASV\n" if DEBUG
  76. line = "PASV\n"
  77. state = "EPSV"
  78. elsif (line =~ /^EPRT\s+(.+)\r\n/i)
  79. t = ftp_parse_2428($1)
  80. if t == nil
  81. s6.puts "501 illegal parameter to EPRT\r\n"
  82. next
  83. end
  84. # some tricks should be here
  85. s6.puts "501 illegal parameter to EPRT\r\n"
  86. next
  87. end
  88. STDERR.print "fail: send #{line} as is\n" if DEBUG
  89. s4.puts(line)
  90. break
  91. rescue EOFError
  92. return nil
  93. rescue IOError
  94. return nil
  95. end
  96. end
  97. STDERR.print "relay_ftp_command finish\n" if DEBUG
  98. return state
  99. end
  100. def relay_ftp_status(s4, s6, state)
  101. STDERR.print "relay_ftp_status start\n" if DEBUG
  102. while TRUE
  103. begin
  104. line = s4.gets
  105. if line == nil
  106. return nil
  107. end
  108. # translate then copy
  109. s6.puts(line)
  110. next if line =~ /^\d\d\d-/
  111. next if line !~ /^\d/
  112. # special post-processing
  113. case line
  114. when /^221 / # result to QUIT
  115. s4.shutdown(0)
  116. s6.shutdown(1)
  117. end
  118. break if (line =~ /^\d\d\d /)
  119. rescue EOFError
  120. return nil
  121. rescue IOError
  122. return nil
  123. end
  124. end
  125. STDERR.print "relay_ftp_status finish\n" if DEBUG
  126. return state
  127. end
  128. def relay_ftp(sock, name)
  129. STDERR.print "relay_ftp(#{sock}, #{name})\n" if DEBUG
  130. while TRUE
  131. STDERR.print "relay_ftp(#{sock}, #{name}) accepting\n" if DEBUG
  132. s = sock.accept
  133. STDERR.print "relay_ftp(#{sock}, #{name}) accepted #{s}\n" if DEBUG
  134. Thread.start do
  135. threads = []
  136. STDERR.print "accepted #{s} -> #{Thread.current}\n" if DEBUG
  137. s6 = s
  138. dest6 = s.addr[3]
  139. if !DEBUG_LOOPBACK
  140. t = s.getsockname.unpack("x8 x12 C4")
  141. dest4 = "#{t[0]}.#{t[1]}.#{t[2]}.#{t[3]}"
  142. port4 = s.addr[1]
  143. else
  144. dest4 = "127.0.0.1"
  145. port4 = "ftp"
  146. end
  147. if DEBUG
  148. STDERR.print "IPv6 dest: #{dest6} IPv4 dest: #{dest4}\n" if DEBUG
  149. end
  150. STDERR.print "connect to #{dest4} #{port4}\n" if DEBUG
  151. s4 = TCPsocket.open(dest4, port4)
  152. STDERR.print "connected to #{dest4} #{port4}, #{s4.addr[1]}\n" if DEBUG
  153. state = 0
  154. while TRUE
  155. # translate status line
  156. state = relay_ftp_status(s4, s6, state)
  157. break if state == nil
  158. # translate command line
  159. state = relay_ftp_command(s6, s4, state)
  160. break if state == nil
  161. end
  162. STDERR.print "relay_ftp(#{sock}, #{name}) closing s4\n" if DEBUG
  163. s4.close
  164. STDERR.print "relay_ftp(#{sock}, #{name}) closing s6\n" if DEBUG
  165. s6.close
  166. STDERR.print "relay_ftp(#{sock}, #{name}) done\n" if DEBUG
  167. end
  168. end
  169. STDERR.print "relay_ftp(#{sock}, #{name}) finished\n" if DEBUG
  170. end
  171. def relay_tcp(sock, name)
  172. STDERR.print "relay_tcp(#{sock}, #{name})\n" if DEBUG
  173. while TRUE
  174. STDERR.print "relay_tcp(#{sock}, #{name}) accepting\n" if DEBUG
  175. s = sock.accept
  176. STDERR.print "relay_tcp(#{sock}, #{name}) accepted #{s}\n" if DEBUG
  177. Thread.start do
  178. threads = []
  179. STDERR.print "accepted #{s} -> #{Thread.current}\n" if DEBUG
  180. s6 = s
  181. dest6 = s.addr[3]
  182. if !DEBUG_LOOPBACK
  183. t = s.getsockname.unpack("x8 x12 C4")
  184. dest4 = "#{t[0]}.#{t[1]}.#{t[2]}.#{t[3]}"
  185. port4 = s.addr[1]
  186. else
  187. dest4 = "127.0.0.1"
  188. port4 = "telnet"
  189. end
  190. if DEBUG
  191. STDERR.print "IPv6 dest: #{dest6} IPv4 dest: #{dest4}\n" if DEBUG
  192. end
  193. STDERR.print "connect to #{dest4} #{port4}\n" if DEBUG
  194. s4 = TCPsocket.open(dest4, port4)
  195. STDERR.print "connected to #{dest4} #{port4}, #{s4.addr[1]}\n" if DEBUG
  196. [0, 1].each do |i|
  197. threads[i] = Thread.start do
  198. if (i == 0)
  199. tcpcopy(s6, s4)
  200. else
  201. tcpcopy(s4, s6)
  202. end
  203. end
  204. end
  205. STDERR.print "relay_tcp(#{sock}, #{name}) wait\n" if DEBUG
  206. for i in threads
  207. STDERR.print "relay_tcp(#{sock}, #{name}) wait #{i}\n" if DEBUG
  208. i.join
  209. STDERR.print "relay_tcp(#{sock}, #{name}) wait #{i} done\n" if DEBUG
  210. end
  211. STDERR.print "relay_tcp(#{sock}, #{name}) closing s4\n" if DEBUG
  212. s4.close
  213. STDERR.print "relay_tcp(#{sock}, #{name}) closing s6\n" if DEBUG
  214. s6.close
  215. STDERR.print "relay_tcp(#{sock}, #{name}) done\n" if DEBUG
  216. end
  217. end
  218. STDERR.print "relay_tcp(#{sock}, #{name}) finished\n" if DEBUG
  219. end
  220. def usage()
  221. STDERR.print "usage: #{$0} [-f] port...\n"
  222. end
  223. #------------------------------------------------------------
  224. $mode = "tcp"
  225. while ARGV[0] =~ /^-/ do
  226. case ARGV[0]
  227. when /^-f/
  228. $mode = "ftp"
  229. else
  230. usage()
  231. exit 0
  232. end
  233. ARGV.shift
  234. end
  235. if ARGV.length == 0
  236. usage()
  237. exit 1
  238. end
  239. ftpport = Socket.getservbyname("ftp")
  240. res = []
  241. for port in ARGV
  242. t = Socket.getaddrinfo(nil, port, Socket::PF_INET6, Socket::SOCK_STREAM,
  243. nil, Socket::AI_PASSIVE)
  244. if (t.size <= 0)
  245. STDERR.print "FATAL: getaddrinfo failed (port=#{port})\n"
  246. exit 1
  247. end
  248. res += t
  249. end
  250. sockpool = []
  251. names = []
  252. listenthreads = []
  253. res.each do |i|
  254. s = TCPserver.new(i[3], i[1])
  255. n = Socket.getnameinfo(s.getsockname, Socket::NI_NUMERICHOST|Socket::NI_NUMERICSERV).join(" port ")
  256. if i[6] == IPPROTO_IPV6
  257. s.setsockopt(i[6], IPV6_FAITH, 1)
  258. end
  259. s.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1)
  260. sockpool.push s
  261. names.push n
  262. end
  263. if DEBUG
  264. (0 .. sockpool.size - 1).each do |i|
  265. STDERR.print "listen[#{i}]: #{sockpool[i]} #{names[i]}\n" if DEBUG
  266. end
  267. end
  268. (0 .. sockpool.size - 1).each do |i|
  269. listenthreads[i] = Thread.start do
  270. if DEBUG
  271. STDERR.print "listen[#{i}]: thread #{Thread.current}\n" if DEBUG
  272. end
  273. STDERR.print "listen[#{i}]: thread #{Thread.current}\n" if DEBUG
  274. case $mode
  275. when "tcp"
  276. relay_tcp(sockpool[i], names[i])
  277. when "ftp"
  278. relay_ftp(sockpool[i], names[i])
  279. end
  280. end
  281. end
  282. for i in listenthreads
  283. i.join
  284. end
  285. exit 0