Browse Source

Initial revision.

Bernd Fix 3 months ago
parent
commit
c2df4d11f7
1 changed files with 147 additions and 0 deletions
  1. 147
    0
      src/gnunet/service/gns/box.go

+ 147
- 0
src/gnunet/service/gns/box.go View File

@@ -0,0 +1,147 @@
1
+package gns
2
+
3
+import (
4
+	"encoding/hex"
5
+	"strconv"
6
+	"strings"
7
+
8
+	"github.com/bfix/gospel/data"
9
+	"github.com/bfix/gospel/logger"
10
+)
11
+
12
+// Box is an encapsulated RR for special names
13
+type Box struct {
14
+	Proto uint16 `order:"big"` // Protcol identifier
15
+	Svc   uint16 `order:"big"` // Service identifier
16
+	Type  uint32 `order:"big"` // Type of embedded RR
17
+	RR    []byte `size:"*"`    // embedded RR
18
+
19
+	// transient attributes (not serialized)
20
+	key string
21
+}
22
+
23
+// NewBox creates a new box instance from a BOX resource record.
24
+func NewBox(buf []byte) *Box {
25
+	b := new(Box)
26
+	if err := data.Unmarshal(b, buf); err != nil {
27
+		logger.Printf(logger.ERROR, "[gns] Can't unmarshal BOX")
28
+		return nil
29
+	}
30
+	b.key = hex.EncodeToString(buf[:8])
31
+	return b
32
+}
33
+
34
+// Matches verifies that the remaining labels comply with the values
35
+// in the BOX record.
36
+func (b *Box) Matches(labels []string) bool {
37
+	// resolve protocol and service names
38
+	proto, protoName := GetProtocol(labels[0])
39
+	svc, _ := GetService(labels[1], protoName)
40
+	// no match on invalid resolution
41
+	if proto == 0 || svc == 0 {
42
+		return false
43
+	}
44
+	// check for matching values in box
45
+	return proto == b.Proto && svc == b.Svc
46
+}
47
+
48
+//----------------------------------------------------------------------
49
+// helper functions
50
+
51
+// list of handled protocols in BOX records
52
+var protocols = map[string]int{
53
+	"icmp":      1,
54
+	"igmp":      2,
55
+	"tcp":       6,
56
+	"udp":       17,
57
+	"ipv6-icmp": 58,
58
+}
59
+
60
+// GetProtocol returns the protocol number and name for a given name. The
61
+// name can be  an integer value (e.g. "_6" for "tcp") or a mnemonic name
62
+// (e.g. like "_tcp").
63
+func GetProtocol(name string) (uint16, string) {
64
+	// check for required prefix
65
+	if name[0] != '_' {
66
+		return 0, ""
67
+	}
68
+	name = strings.ToLower(name[1:])
69
+
70
+	// if label is an integer value it is the protocol number
71
+	if val, err := strconv.Atoi(name); err == nil {
72
+		// check for valid number (reverse protocol lookup)
73
+		for label, id := range protocols {
74
+			if id == val {
75
+				// return found entry
76
+				return uint16(val), label
77
+			}
78
+		}
79
+		// number out of range
80
+		return 0, ""
81
+	}
82
+	// try to resolve via protocol map
83
+	if id, ok := protocols[name]; ok {
84
+		return uint16(id), name
85
+	}
86
+	// resolution failed
87
+	return 0, ""
88
+}
89
+
90
+// list of services (per protocol) handled in BOX records
91
+var services = map[string]map[string]int{
92
+	"udp": {
93
+		"domain": 53,
94
+	},
95
+	"tcp": {
96
+		"ftp":    21,
97
+		"ftps":   990,
98
+		"gopher": 70,
99
+		"http":   80,
100
+		"https":  443,
101
+		"imap2":  143,
102
+		"imap3":  220,
103
+		"imaps":  993,
104
+		"pop3":   110,
105
+		"pop3s":  995,
106
+		"smtp":   25,
107
+		"ssh":    22,
108
+		"telnet": 23,
109
+	},
110
+}
111
+
112
+// GetService returns the port number and the name of a service (with given
113
+// protocol).  The name can be an integer value (e.g. "_443" for "https") or
114
+// a mnemonic name (e.g. like "_https").
115
+func GetService(name, proto string) (uint16, string) {
116
+	// check for required prefix
117
+	if name[0] != '_' {
118
+		return 0, ""
119
+	}
120
+	name = strings.ToLower(name[1:])
121
+
122
+	// get list of services for given protocol
123
+	svcs, ok := services[proto]
124
+	if !ok {
125
+		// no services available for this protocol
126
+		return 0, ""
127
+	}
128
+
129
+	// if label is an integer value it is the port number
130
+	if val, err := strconv.Atoi(name); err == nil {
131
+		// check for valid number (reverse service lookup)
132
+		for label, id := range svcs {
133
+			if id == val {
134
+				// return found entry
135
+				return uint16(val), label
136
+			}
137
+		}
138
+		// number out of range
139
+		return 0, ""
140
+	}
141
+	// try to resolve via services map
142
+	if id, ok := svcs[name]; ok {
143
+		return uint16(id), name
144
+	}
145
+	// resolution failed
146
+	return 0, ""
147
+}

Loading…
Cancel
Save