File: parse.go

package info (click to toggle)
opensnitch 1.5.9-4
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 10,536 kB
  • sloc: ansic: 136,511; python: 6,597; sh: 204; makefile: 167; xml: 50
file content (120 lines) | stat: -rw-r--r-- 2,732 bytes parent folder | download | duplicates (3)
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
package netstat

import (
	"bufio"
	"encoding/binary"
	"fmt"
	"net"
	"os"
	"regexp"
	"strconv"

	"github.com/evilsocket/opensnitch/daemon/core"
	"github.com/evilsocket/opensnitch/daemon/log"
)

var (
	parser = regexp.MustCompile(`(?i)` +
		`\d+:\s+` + // sl
		`([a-f0-9]{8,32}):([a-f0-9]{4})\s+` + // local_address
		`([a-f0-9]{8,32}):([a-f0-9]{4})\s+` + // rem_address
		`[a-f0-9]{2}\s+` + // st
		`[a-f0-9]{8}:[a-f0-9]{8}\s+` + // tx_queue rx_queue
		`[a-f0-9]{2}:[a-f0-9]{8}\s+` + // tr tm->when
		`[a-f0-9]{8}\s+` + // retrnsmt
		`(\d+)\s+` + // uid
		`\d+\s+` + // timeout
		`(\d+)\s+` + // inode
		`.+`) // stuff we don't care about
)

func decToInt(n string) int {
	d, err := strconv.ParseInt(n, 10, 64)
	if err != nil {
		log.Fatal("Error while parsing %s to int: %s", n, err)
	}
	return int(d)
}

func hexToInt(h string) uint {
	d, err := strconv.ParseUint(h, 16, 64)
	if err != nil {
		log.Fatal("Error while parsing %s to int: %s", h, err)
	}
	return uint(d)
}

func hexToInt2(h string) (uint, uint) {
	if len(h) > 16 {
		d, err := strconv.ParseUint(h[:16], 16, 64)
		if err != nil {
			log.Fatal("Error while parsing %s to int: %s", h[16:], err)
		}
		d2, err := strconv.ParseUint(h[16:], 16, 64)
		if err != nil {
			log.Fatal("Error while parsing %s to int: %s", h[16:], err)
		}
		return uint(d), uint(d2)
	}

	d, err := strconv.ParseUint(h, 16, 64)
	if err != nil {
		log.Fatal("Error while parsing %s to int: %s", h[16:], err)
	}
	return uint(d), 0
}

func hexToIP(h string) net.IP {
	n, m := hexToInt2(h)
	var ip net.IP
	if m != 0 {
		ip = make(net.IP, 16)
		// TODO: Check if this depends on machine endianness?
		binary.LittleEndian.PutUint32(ip, uint32(n>>32))
		binary.LittleEndian.PutUint32(ip[4:], uint32(n))
		binary.LittleEndian.PutUint32(ip[8:], uint32(m>>32))
		binary.LittleEndian.PutUint32(ip[12:], uint32(m))
	} else {
		ip = make(net.IP, 4)
		binary.LittleEndian.PutUint32(ip, uint32(n))
	}
	return ip
}

// Parse scans and retrieves the opened connections, from /proc/net/ files
func Parse(proto string) ([]Entry, error) {
	filename := fmt.Sprintf("/proc/net/%s", proto)
	fd, err := os.Open(filename)
	if err != nil {
		return nil, err
	}
	defer fd.Close()

	entries := make([]Entry, 0)
	scanner := bufio.NewScanner(fd)
	for lineno := 0; scanner.Scan(); lineno++ {
		// skip column names
		if lineno == 0 {
			continue
		}

		line := core.Trim(scanner.Text())
		m := parser.FindStringSubmatch(line)
		if m == nil {
			log.Warning("Could not parse netstat line from %s: %s", filename, line)
			continue
		}

		entries = append(entries, NewEntry(
			proto,
			hexToIP(m[1]),
			hexToInt(m[2]),
			hexToIP(m[3]),
			hexToInt(m[4]),
			decToInt(m[5]),
			decToInt(m[6]),
		))
	}

	return entries, nil
}