class Inspec::Resources::FreeBsdPorts
extracts information from sockstat
def info
def info cmd = inspec.command('sockstat -46l') return nil if cmd.exit_status.to_i != 0 ports = [] # split on each newline cmd.stdout.each_line do |line| port_info = parse_sockstat_line(line) # push data, if not headerfile next unless %w{tcp tcp6 udp udp6}.include?(port_info['protocol']) ports.push(port_info) end ports end
def parse_net_address(net_addr, protocol)
def parse_net_address(net_addr, protocol) case protocol when 'tcp4', 'udp4', 'tcp', 'udp' # replace * with 0.0.0.0 net_addr = net_addr.gsub(/^\*:/, '0.0.0.0:') if net_addr =~ /^*:(\d+)$/ ip_addr = URI('addr://'+net_addr) host = ip_addr.host port = ip_addr.port when 'tcp6', 'udp6' return [] if net_addr == '*:*' # abort for now # replace * with 0:0:0:0:0:0:0:0 net_addr = net_addr.gsub(/^\*:/, '0:0:0:0:0:0:0:0:') if net_addr =~ /^*:(\d+)$/ # extract port ip6 = /^(\S+):(\d+)$/.match(net_addr) ip6addr = ip6[1] ip_addr = URI("addr://[#{ip6addr}]:#{ip6[2]}") # replace [] host = ip_addr.host[1..ip_addr.host.size-2] port = ip_addr.port end [host, port] rescue URI::InvalidURIError => e warn "Could not parse #{net_addr}, #{e}" nil end
def parse_sockstat_line(line)
def parse_sockstat_line(line) # 1 - USER, 2 - COMMAND, 3 - PID, 4 - FD 5 - PROTO, 6 - LOCAL ADDRESS, 7 - FOREIGN ADDRESS parsed = /^(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)$/.match(line) return {} if parsed.nil? # extract ip information protocol = parsed[5].downcase host, port = parse_net_address(parsed[6], protocol) return {} if host.nil? or port.nil? # extract process process = parsed[2] # extract PID pid = parsed[3] pid = pid.to_i if pid =~ /^\d+$/ # map tcp4 and udp4 protocol = 'tcp' if protocol.eql?('tcp4') protocol = 'udp' if protocol.eql?('udp4') { 'port' => port, 'address' => host, 'protocol' => protocol, 'process' => process, 'pid' => pid, } end