This file is indexed.

/usr/lib/ruby/vendor_ruby/em/resolver.rb is in ruby-eventmachine 1.0.3-4.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
module EventMachine
  module DNS
    class Resolver

      def self.resolve(hostname)
        Request.new(socket, hostname)
      end

      @socket = @nameservers = nil

      def self.socket
        if !@socket || (@socket && @socket.error?)
          @socket = Socket.open

          @hosts  = {}
          IO.readlines('/etc/hosts').each do |line|
            next if line =~ /^#/
            addr, host = line.split(/\s+/)

            if @hosts[host]
              @hosts[host] << addr
            else
              @hosts[host] = [addr]
            end
          end
        end

        @socket
      end

      def self.nameservers=(ns)
        @nameservers = ns
      end

      def self.nameservers
        if !@nameservers
          @nameservers = []
          IO.readlines('/etc/resolv.conf').each do |line|
            if line =~ /^nameserver (.+)$/
              @nameservers << $1.split(/\s+/).first
            end
          end
        end
        @nameservers
      end

      def self.nameserver
        nameservers.shuffle.first
      end

      def self.hosts
        @hosts
      end
    end

    class RequestIdAlreadyUsed < RuntimeError; end

    class Socket < EventMachine::Connection
      def self.open
        EventMachine::open_datagram_socket('0.0.0.0', 0, self)
      end

      def initialize
        @nameserver = nil
      end

      def post_init
        @requests = {}
        EM.add_periodic_timer(0.1, &method(:tick))
      end

      def unbind
      end

      def tick
        @requests.each do |id,req|
          req.tick
        end
      end

      def register_request(id, req)
        if @requests.has_key?(id)
          raise RequestIdAlreadyUsed
        else
          @requests[id] = req
        end
      end

      def send_packet(pkt)
        send_datagram(pkt, nameserver, 53)
      end

      def nameserver=(ns)
        @nameserver = ns
      end

      def nameserver
        @nameserver || Resolver.nameserver
      end

      # Decodes the packet, looks for the request and passes the
      # response over to the requester
      def receive_data(data)
        msg = nil
        begin
          msg = Resolv::DNS::Message.decode data
        rescue
        else
          req = @requests[msg.id]
          if req
            @requests.delete(msg.id)
            req.receive_answer(msg)
          end
        end
      end
    end

    class Request
      include Deferrable
      attr_accessor :retry_interval, :max_tries

      def initialize(socket, hostname)
        @socket = socket
        @hostname = hostname
        @tries = 0
        @last_send = Time.at(0)
        @retry_interval = 3
        @max_tries = 5

        if addrs = Resolver.hosts[hostname]
          succeed addrs
        else
          EM.next_tick { tick }
        end
      end

      def tick
        # Break early if nothing to do
        return if @last_send + @retry_interval > Time.now
        if @tries < @max_tries
          send
        else
          fail 'retries exceeded'
        end
      end

      def receive_answer(msg)
        addrs = []
        msg.each_answer do |name,ttl,data|
          if data.kind_of?(Resolv::DNS::Resource::IN::A) ||
              data.kind_of?(Resolv::DNS::Resource::IN::AAAA)
            addrs << data.address.to_s
          end
        end

        if addrs.empty?
          fail "rcode=#{msg.rcode}"
        else
          succeed addrs
        end
      end

      private

        def send
          @tries += 1
          @last_send = Time.now
          @socket.send_packet(packet.encode)
        end

        def id
          begin
            @id = rand(65535)
            @socket.register_request(@id, self)
          rescue RequestIdAlreadyUsed
            retry
          end unless defined?(@id)

          @id
        end

        def packet
          msg = Resolv::DNS::Message.new
          msg.id = id
          msg.rd = 1
          msg.add_question @hostname, Resolv::DNS::Resource::IN::A
          msg
        end

    end
  end
end