Browse Source

Added CNAME handling; refactored BlockHandler interface.

Bernd Fix 2 months ago
parent
commit
aac873a7e5

+ 111
- 40
src/gnunet/service/gns/block_handler.go View File

@@ -6,6 +6,7 @@ import (
6 6
 
7 7
 	"gnunet/enums"
8 8
 	"gnunet/message"
9
+	"gnunet/util"
9 10
 
10 11
 	"github.com/bfix/gospel/crypto/ed25519"
11 12
 	"github.com/bfix/gospel/logger"
@@ -16,17 +17,22 @@ type HdlrInst func(*message.GNSResourceRecord, []string) (BlockHandler, error)
16 17
 
17 18
 // Error codes
18 19
 var (
19
-	ErrInvalidRecordMix = fmt.Errorf("Invalid mix of RR types in block")
20
-	ErrBlockHandler     = fmt.Errorf("Internal block handler failure")
20
+	ErrInvalidRecordType = fmt.Errorf("Invalid resource record type")
21
+	ErrInvalidRecordBody = fmt.Errorf("Invalid resource record body")
22
+	ErrInvalidPKEY       = fmt.Errorf("Invalid PKEY resource record")
23
+	ErrInvalidCNAME      = fmt.Errorf("Invalid CNAME resource record")
24
+	ErrInvalidRecordMix  = fmt.Errorf("Invalid mix of RR types in block")
25
+	ErrBlockHandler      = fmt.Errorf("Internal block handler failure")
21 26
 )
22 27
 
23 28
 // Mapping of RR types to BlockHandler instanciation functions
24 29
 var (
25 30
 	customHandler = map[int]HdlrInst{
26
-		enums.GNS_TYPE_PKEY:    NewPkeyHandler,
27
-		enums.GNS_TYPE_GNS2DNS: NewGns2DnsHandler,
28
-		enums.GNS_TYPE_BOX:     NewBoxHandler,
29
-		enums.GNS_TYPE_LEHO:    NewLehoHandler,
31
+		enums.GNS_TYPE_PKEY:      NewPkeyHandler,
32
+		enums.GNS_TYPE_GNS2DNS:   NewGns2DnsHandler,
33
+		enums.GNS_TYPE_BOX:       NewBoxHandler,
34
+		enums.GNS_TYPE_LEHO:      NewLehoHandler,
35
+		enums.GNS_TYPE_DNS_CNAME: NewCnameHandler,
30 36
 	}
31 37
 )
32 38
 
@@ -39,17 +45,17 @@ var (
39 45
 
40 46
 // BlockHandler interface.
41 47
 type BlockHandler interface {
42
-	// AddRecord inserts a RR into the BlockHandler for (later) processing.
43
-	// The handler can inspect the remaining labels in a path if required.
44
-	// It returns an error if a record is not accepted by the block handler.
48
+	// AddRecord inserts an associated RR into the BlockHandler for (later)
49
+	// processing. The handler can inspect the remaining labels in a path
50
+	// if required. The method returns an error if a record is not accepted
51
+	// by the block handler (RR not of required type).
45 52
 	AddRecord(rr *message.GNSResourceRecord, labels []string) error
46 53
 
47
-	// TypeAction returns a flag indicating how a resource record of a
48
-	// given type is to be treated by a custom block handler:
49
-	//   = -1: Record is not allowed
50
-	//   =  0: Record is allowed but will be ignored
51
-	//   =  1: Record is allowed and will be processed
52
-	TypeAction(t int) int
54
+	// Coexist checks if a custom block handler can co-exist with other
55
+	// resource records in the same block. 'cm' maps the resource type
56
+	// to an integer count (how many records of a type are present in the
57
+	// GNS block).
58
+	Coexist(cm util.CounterMap) bool
53 59
 
54 60
 	// Records returns a list of RR of the given types associated with
55 61
 	// the custom handler
@@ -69,7 +75,8 @@ type BlockHandler interface {
69 75
 
70 76
 // BlockHandlerList is a list of block handlers instantiated.
71 77
 type BlockHandlerList struct {
72
-	list map[int]BlockHandler // list of handler instances
78
+	list   map[int]BlockHandler // list of handler instances
79
+	counts util.CounterMap      // count number of RRs by type
73 80
 }
74 81
 
75 82
 // NewBlockHandlerList instantiates an a list of active block handlers
@@ -77,13 +84,17 @@ type BlockHandlerList struct {
77 84
 func NewBlockHandlerList(records []*message.GNSResourceRecord, labels []string) (*BlockHandlerList, error) {
78 85
 	// initialize block handler list
79 86
 	hl := &BlockHandlerList{
80
-		list: make(map[int]BlockHandler),
87
+		list:   make(map[int]BlockHandler),
88
+		counts: make(util.CounterMap),
81 89
 	}
82 90
 
83 91
 	// Traverse record list and build list of handler instances
84 92
 	for _, rec := range records {
85
-		// check for custom handler type
93
+		// update counter map
86 94
 		rrType := int(rec.Type)
95
+		hl.counts.Add(rrType)
96
+
97
+		// check for custom handler type
87 98
 		if creat, ok := customHandler[rrType]; ok {
88 99
 			// check if a handler for given type already exists
89 100
 			var (
@@ -105,6 +116,15 @@ func NewBlockHandlerList(records []*message.GNSResourceRecord, labels []string)
105 116
 			hl.list[rrType] = hdlr
106 117
 		}
107 118
 	}
119
+
120
+	// Check if all registered handlers in list can co-exist with
121
+	// all the other records of varying type
122
+	for _, hdlr := range hl.list {
123
+		if !hdlr.Coexist(hl.counts) {
124
+			return nil, ErrInvalidRecordMix
125
+		}
126
+	}
127
+	// return assembled handler list
108 128
 	return hl, nil
109 129
 }
110 130
 
@@ -162,14 +182,11 @@ func (h *PkeyHandler) AddRecord(rec *message.GNSResourceRecord, labels []string)
162 182
 	return nil
163 183
 }
164 184
 
165
-// TypeAction return a flag indicating how a resource record of a given type
185
+// Coexist return a flag indicating how a resource record of a given type
166 186
 // is to be treated (see BlockHandler interface)
167
-func (h *PkeyHandler) TypeAction(t int) int {
168
-	// no other resource record type is not allowed
169
-	if t == enums.GNS_TYPE_PKEY {
170
-		return 1
171
-	}
172
-	return -1
187
+func (h *PkeyHandler) Coexist(cm util.CounterMap) bool {
188
+	// only one type (GNS_TYPE_PKEY) is present
189
+	return len(cm) == 1 && cm.Num(enums.GNS_TYPE_PKEY) == 1
173 190
 }
174 191
 
175 192
 // Records returns a list of RR of the given type associated with this handler
@@ -235,11 +252,11 @@ func (h *Gns2DnsHandler) AddRecord(rec *message.GNSResourceRecord, labels []stri
235 252
 	return nil
236 253
 }
237 254
 
238
-// TypeAction return a flag indicating how a resource record of a given type
255
+// Coexist return a flag indicating how a resource record of a given type
239 256
 // is to be treated (see BlockHandler interface)
240
-func (h *Gns2DnsHandler) TypeAction(t int) int {
241
-	// anything goes...
242
-	return 1
257
+func (h *Gns2DnsHandler) Coexist(cm util.CounterMap) bool {
258
+	// only one type (GNS_TYPE_GNS2DNS) is present
259
+	return len(cm) == 1 && cm.Num(enums.GNS_TYPE_GNS2DNS) > 0
243 260
 }
244 261
 
245 262
 // Records returns a list of RR of the given type associated with this handler
@@ -300,11 +317,11 @@ func (h *BoxHandler) AddRecord(rec *message.GNSResourceRecord, labels []string)
300 317
 	return nil
301 318
 }
302 319
 
303
-// TypeAction return a flag indicating how a resource record of a given type
320
+// Coexist return a flag indicating how a resource record of a given type
304 321
 // is to be treated (see BlockHandler interface)
305
-func (h *BoxHandler) TypeAction(t int) int {
322
+func (h *BoxHandler) Coexist(cm util.CounterMap) bool {
306 323
 	// anything goes...
307
-	return 1
324
+	return true
308 325
 }
309 326
 
310 327
 // Records returns a list of RR of the given type associated with this handler
@@ -359,16 +376,17 @@ func (h *LehoHandler) AddRecord(rec *message.GNSResourceRecord, labels []string)
359 376
 	return nil
360 377
 }
361 378
 
362
-// TypeAction return a flag indicating how a resource record of a given type
379
+// Coexist return a flag indicating how a resource record of a given type
363 380
 // is to be treated (see BlockHandler interface)
364
-func (h *LehoHandler) TypeAction(t int) int {
365
-	// only A and AAAA records allowed beside LEHO
366
-	switch t {
367
-	case enums.GNS_TYPE_LEHO, enums.GNS_TYPE_DNS_A, enums.GNS_TYPE_DNS_AAAA:
368
-		return 1
369
-	default:
370
-		return -1
381
+func (h *LehoHandler) Coexist(cm util.CounterMap) bool {
382
+	// requires exactly one A/AAAA record alongside single LEHO
383
+	if len(cm) != 2 {
384
+		return false
385
+	}
386
+	if cm.Num(enums.GNS_TYPE_LEHO) != 1 {
387
+		return false
371 388
 	}
389
+	return cm.Num(enums.GNS_TYPE_DNS_A) == 1 || cm.Num(enums.GNS_TYPE_DNS_AAAA) == 1
372 390
 }
373 391
 
374 392
 // Records returns a list of RR of the given type associated with this handler
@@ -379,3 +397,56 @@ func (h *LehoHandler) Records(kind RRTypeList) *GNSRecordSet {
379 397
 	}
380 398
 	return rs
381 399
 }
400
+
401
+//----------------------------------------------------------------------
402
+// CNAME handler
403
+//----------------------------------------------------------------------
404
+
405
+// CnameHandler implementing the BlockHandler interface
406
+type CnameHandler struct {
407
+	name string
408
+	rec  *message.GNSResourceRecord
409
+}
410
+
411
+// NewCnameHandler returns a new BlockHandler instance
412
+func NewCnameHandler(rec *message.GNSResourceRecord, labels []string) (BlockHandler, error) {
413
+	if int(rec.Type) != enums.GNS_TYPE_DNS_CNAME {
414
+		return nil, ErrInvalidRecordType
415
+	}
416
+	h := &CnameHandler{
417
+		name: "",
418
+	}
419
+	if err := h.AddRecord(rec, labels); err != nil {
420
+		return nil, err
421
+	}
422
+	return h, nil
423
+}
424
+
425
+// AddRecord inserts a CNAME record into the handler.
426
+func (h *CnameHandler) AddRecord(rec *message.GNSResourceRecord, labels []string) error {
427
+	if int(rec.Type) != enums.GNS_TYPE_DNS_CNAME {
428
+		return ErrInvalidRecordType
429
+	}
430
+	if h.rec != nil {
431
+		return ErrInvalidCNAME
432
+	}
433
+	_, h.name = DNSNameFromBytes(rec.Data, 0)
434
+	h.rec = rec
435
+	return nil
436
+}
437
+
438
+// Coexist return a flag indicating how a resource record of a given type
439
+// is to be treated (see BlockHandler interface)
440
+func (h *CnameHandler) Coexist(cm util.CounterMap) bool {
441
+	// anything goes
442
+	return true
443
+}
444
+
445
+// Records returns a list of RR of the given type associated with this handler
446
+func (h *CnameHandler) Records(kind RRTypeList) *GNSRecordSet {
447
+	rs := NewGNSRecordSet()
448
+	if kind.HasType(enums.GNS_TYPE_DNS_CNAME) {
449
+		rs.AddRecord(h.rec)
450
+	}
451
+	return rs
452
+}

+ 19
- 30
src/gnunet/service/gns/dns.go View File

@@ -45,9 +45,11 @@ func DNSNameFromBytes(b []byte, offset int) (int, string) {
45 45
 	return pos + 1, str
46 46
 }
47 47
 
48
-// queryDNS resolves a name on a given nameserver and delivers all matching
49
-// resource record (of type 'kind') to the result channel.
50
-func queryDNS(id int, name string, server net.IP, kind RRTypeList, res chan *GNSRecordSet) {
48
+func QueryDNS(id int, name string, server net.IP, kind RRTypeList) *GNSRecordSet {
49
+	// get default nameserver if not defined.
50
+	if server == nil {
51
+		server = net.IPv4(8, 8, 8, 8)
52
+	}
51 53
 	logger.Printf(logger.DBG, "[dns][%d] Starting query for '%s' on '%s'...\n", id, name, server.String())
52 54
 
53 55
 	// assemble query
@@ -80,14 +82,13 @@ func queryDNS(id int, name string, server net.IP, kind RRTypeList, res chan *GNS
80 82
 				continue
81 83
 			}
82 84
 			logger.Printf(logger.ERROR, "[dns][%d] Error: %s\n", id, errMsg)
83
-			res <- nil
85
+			return nil
84 86
 		}
85 87
 		// process results
86 88
 		logger.Printf(logger.WARN, "[dns][%d] Response from DNS server received (%d/5).\n", id, retry+1)
87 89
 		if in == nil {
88 90
 			logger.Printf(logger.ERROR, "[dns][%d] No results\n", id)
89
-			res <- nil
90
-			return
91
+			return nil
91 92
 		}
92 93
 		set := NewGNSRecordSet()
93 94
 		for _, record := range in.Answer {
@@ -118,12 +119,11 @@ func queryDNS(id int, name string, server net.IP, kind RRTypeList, res chan *GNS
118 119
 				set.AddRecord(rr)
119 120
 			}
120 121
 		}
121
-		logger.Printf(logger.WARN, "[dns][%d] %d resource records extracted from response (%d/5).\n", id, set.Count, retry+1)
122
-		res <- set
123
-		return
122
+		logger.Printf(logger.INFO, "[dns][%d] %d resource records extracted from response (%d/5).\n", id, set.Count, retry+1)
123
+		return set
124 124
 	}
125 125
 	logger.Printf(logger.WARN, "[dns][%d] Resolution failed -- giving up...\n", id)
126
-	res <- nil
126
+	return nil
127 127
 }
128 128
 
129 129
 // ResolveDNS resolves a name in DNS. Multiple DNS servers are queried in
@@ -135,29 +135,16 @@ func (gns *GNSModule) ResolveDNS(name string, servers []string, kind RRTypeList,
135 135
 	// start DNS queries concurrently
136 136
 	res := make(chan *GNSRecordSet)
137 137
 	running := 0
138
-	for idx, srv := range servers {
138
+	for _, srv := range servers {
139 139
 		// check if srv is an IPv4/IPv6 address
140 140
 		addr := net.ParseIP(srv)
141 141
 		logger.Printf(logger.DBG, "ParseIP('%s', len=%d) --> %v\n", srv, len(srv), addr)
142 142
 		if addr == nil {
143
+			// no, it is a name... try to resolve an IP address from the name
143 144
 			query := NewRRTypeList(enums.GNS_TYPE_DNS_A, enums.GNS_TYPE_DNS_AAAA)
144
-			// no; resolve server name in GNS
145
-			if strings.HasSuffix(srv, ".+") {
146
-				// resolve server name relative to current zone
147
-				zone := util.EncodeBinaryToString(pkey.Bytes())
148
-				srv = strings.TrimSuffix(srv, ".+")
149
-				set, err = gns.Resolve(srv, pkey, query, enums.GNS_LO_DEFAULT)
150
-				if err != nil {
151
-					logger.Printf(logger.ERROR, "[dns] Can't resolve NS server '%s' in '%s'\n", srv, zone)
152
-					continue
153
-				}
154
-			} else {
155
-				// resolve absolute GNS name (name MUST end in a PKEY)
156
-				set, err = gns.Resolve(srv, nil, query, enums.GNS_LO_DEFAULT)
157
-				if err != nil {
158
-					logger.Printf(logger.ERROR, "[dns] Can't resolve NS server '%s'\n", srv)
159
-					continue
160
-				}
145
+			if set, err = gns.ResolveUnknown(srv, pkey, query); err != nil {
146
+				logger.Printf(logger.ERROR, "[dns] Can't resolve NS server '%s': %s\n", srv, err.Error())
147
+				continue
161 148
 			}
162 149
 			// traverse resource records for 'A' and 'AAAA' records.
163 150
 		rec_loop:
@@ -173,12 +160,14 @@ func (gns *GNSModule) ResolveDNS(name string, servers []string, kind RRTypeList,
173 160
 			}
174 161
 			// check if we have an IP address available
175 162
 			if addr == nil {
176
-				logger.Printf(logger.WARN, "[dns] No IP address for nameserver in GNS")
163
+				logger.Printf(logger.WARN, "[dns] No IP address for nameserver '%s'\n", srv)
177 164
 				continue
178 165
 			}
179 166
 		}
180 167
 		// query DNS concurrently
181
-		go queryDNS(idx, name, addr, kind, res)
168
+		go func() {
169
+			res <- QueryDNS(util.NextID(), name, addr, kind)
170
+		}()
182 171
 		running++
183 172
 	}
184 173
 	// check if we started some queries at all.

+ 90
- 35
src/gnunet/service/gns/module.go View File

@@ -20,10 +20,7 @@ import (
20 20
 
21 21
 // Error codes
22 22
 var (
23
-	ErrUnknownTLD        = fmt.Errorf("Unknown TLD in name")
24
-	ErrInvalidRecordType = fmt.Errorf("Invalid resource record type")
25
-	ErrInvalidRecordBody = fmt.Errorf("Invalid resource record body")
26
-	ErrInvalidPKEY       = fmt.Errorf("Invalid PKEY resource record")
23
+	ErrUnknownTLD = fmt.Errorf("Unknown TLD in name")
27 24
 )
28 25
 
29 26
 //----------------------------------------------------------------------
@@ -83,7 +80,7 @@ func NewQuery(pkey *ed25519.PublicKey, label string) *Query {
83 80
 //          (d) if rec is CNAME record:
84 81
 //                  if no remaining labels:
85 82
 //                      if requested types include CNAME -> (5)
86
-//                      if
83
+//                      -> Resolve(CNAME)
87 84
 //      resolution failed: name not completely processed and no zone available
88 85
 //
89 86
 //  (5) return records: it is the responsibility of the caller to assemble
@@ -119,30 +116,23 @@ func (gns *GNSModule) Resolve(path string, pkey *ed25519.PublicKey, kind RRTypeL
119 116
 
120 117
 // Resolve a fully qualified GNS absolute name (with multiple labels).
121 118
 func (gns *GNSModule) ResolveAbsolute(labels []string, kind RRTypeList, mode int) (set *GNSRecordSet, err error) {
122
-	// get the root zone key for the TLD
123
-	var (
124
-		pkey *ed25519.PublicKey
125
-		data []byte
126
-	)
127
-	for {
128
-		// (1) check if TLD is a public key string
129
-		if len(labels[0]) == 52 {
130
-			if data, err = util.DecodeStringToBinary(labels[0], 32); err == nil {
131
-				if pkey = ed25519.NewPublicKeyFromBytes(data); pkey != nil {
132
-					break
133
-				}
134
-			}
135
-		}
119
+	// get the zone key for the TLD
120
+	// (1) check if TLD is a PKEY
121
+	pkey := gns.GetZoneKey(labels[0])
122
+	if pkey == nil {
136 123
 		// (2) check if TLD is in our local config
137
-		if pkey = config.Cfg.GNS.GetRootZoneKey(labels[0]); pkey != nil {
138
-			break
139
-		}
124
+		pkey = config.Cfg.GNS.GetRootZoneKey(labels[0])
125
+	}
126
+	if pkey == nil {
140 127
 		// (3) check if TLD is one of our identities
141
-		if pkey, err = gns.GetLocalZone(labels[0]); err == nil {
142
-			break
128
+		pkey, err = gns.GetLocalZone(labels[0])
129
+	}
130
+	if pkey == nil {
131
+		if err == nil {
132
+			err = ErrUnknownTLD
143 133
 		}
144 134
 		// (4) we can't resolve this TLD
145
-		return nil, ErrUnknownTLD
135
+		return
146 136
 	}
147 137
 	// continue with resolution relative to a zone.
148 138
 	return gns.ResolveRelative(labels[1:], pkey, kind, mode)
@@ -156,7 +146,6 @@ func (gns *GNSModule) ResolveRelative(labels []string, pkey *ed25519.PublicKey,
156 146
 		records []*message.GNSResourceRecord // final resource records from resolution
157 147
 		hdlrs   *BlockHandlerList            // list of block handlers in final step
158 148
 	)
159
-name_loop:
160 149
 	for ; len(labels) > 0; labels = labels[1:] {
161 150
 		logger.Printf(logger.DBG, "[gns] ResolveRelative '%s' in '%s'\n", labels[0], util.EncodeBinaryToString(pkey.Bytes()))
162 151
 
@@ -192,16 +181,24 @@ name_loop:
192 181
 		if hdlr := hdlrs.GetHandler(enums.GNS_TYPE_PKEY); hdlr != nil {
193 182
 			// (1) PKEY record:
194 183
 			inst := hdlr.(*PkeyHandler)
195
-			// if labels are pending, set new zone and continue resolution
196
-			if len(labels) > 1 {
197
-				pkey = inst.pkey
198
-				continue name_loop
184
+			// if labels are pending, set new zone and continue resolution;
185
+			// otherwise resolve "@" label for the zone if no PKEY record
186
+			// was requested.
187
+			pkey = inst.pkey
188
+			if len(labels) == 1 && !kind.HasType(enums.GNS_TYPE_PKEY) {
189
+				labels = append(labels, "@")
199 190
 			}
200 191
 		} else if hdlr := hdlrs.GetHandler(enums.GNS_TYPE_GNS2DNS); hdlr != nil {
201
-			// (2) GNS2DNS records: delegate resolution to DNS
192
+			// (2) GNS2DNS records
202 193
 			inst := hdlr.(*Gns2DnsHandler)
203
-			// we need to handle delegation to DNS: returns a list of found
204
-			// resource records in DNS (filter by 'kind')
194
+			// if we are at the end of the path and the requested type
195
+			// includes GNS_TYPE_GNS2DNS, the GNS2DNS records are returned...
196
+			if len(labels) == 1 && kind.HasType(enums.GNS_TYPE_GNS2DNS) {
197
+				records = inst.recs
198
+				break
199
+			}
200
+			// ... otherwise we need to handle delegation to DNS: returns a
201
+			// list of found resource records in DNS (filter by 'kind')
205 202
 			lbls := strings.Join(util.ReverseStringList(labels[1:]), ".")
206 203
 			if len(lbls) > 0 {
207 204
 				lbls += "."
@@ -213,15 +210,30 @@ name_loop:
213 210
 			}
214 211
 			// we are done with resolution; pass on records to caller
215 212
 			records = set.Records
216
-			break name_loop
213
+			break
217 214
 		} else if hdlr := hdlrs.GetHandler(enums.GNS_TYPE_BOX); hdlr != nil {
218 215
 			// (3) BOX records:
219 216
 			inst := hdlr.(*BoxHandler)
220 217
 			new_records := inst.Records(kind).Records
221 218
 			if len(new_records) > 0 {
222 219
 				records = new_records
223
-				break name_loop
220
+				break
221
+			}
222
+		} else if hdlr := hdlrs.GetHandler(enums.GNS_TYPE_DNS_CNAME); hdlr != nil {
223
+			// (4) CNAME records:
224
+			inst := hdlr.(*CnameHandler)
225
+			// if we are at the end of the path and the requested type
226
+			// includes GNS_TYPE_DNS_CNAME, the records are returned...
227
+			if len(labels) == 1 && kind.HasType(enums.GNS_TYPE_DNS_CNAME) {
228
+				break
224 229
 			}
230
+			if set, err = gns.ResolveUnknown(inst.name, pkey, kind); err != nil {
231
+				logger.Println(logger.ERROR, "[gns] CNAME resolution failed.")
232
+				return
233
+			}
234
+			// we are done with resolution; pass on records to caller
235
+			records = set.Records
236
+			break
225 237
 		}
226 238
 	}
227 239
 	// Assemble resulting resource record set by filtering for requested types.
@@ -237,6 +249,49 @@ name_loop:
237 249
 	return
238 250
 }
239 251
 
252
+// ResolveUnknown resolves a name either in GNS (if applicable) or DNS:
253
+// If the name is a relative GNS path (ending in ".+"), it is resolved in GNS
254
+// relative to the zone PKEY. If the name is an absolute GNS name (ending in
255
+// a PKEY TLD), it is also resolved with GNS. All other names are resolved
256
+// via DNS queries.
257
+func (gns *GNSModule) ResolveUnknown(name string, pkey *ed25519.PublicKey, kind RRTypeList) (set *GNSRecordSet, err error) {
258
+	// relative GNS-based server name?
259
+	if strings.HasSuffix(name, ".+") {
260
+		// resolve server name relative to current zone
261
+		name = strings.TrimSuffix(name, ".+")
262
+		if set, err = gns.Resolve(name, pkey, kind, enums.GNS_LO_DEFAULT); err != nil {
263
+			return
264
+		}
265
+	} else {
266
+		// check for absolute GNS name (with PKEY as TLD)
267
+		if zk := gns.GetZoneKey(name); zk != nil {
268
+			// resolve absolute GNS name (name ends in a PKEY)
269
+			if set, err = gns.Resolve(util.StripPathRight(name), zk, kind, enums.GNS_LO_DEFAULT); err != nil {
270
+				return
271
+			}
272
+		} else {
273
+			// resolve the server name via DNS
274
+			if set = QueryDNS(util.NextID(), name, nil, kind); set == nil {
275
+				err = ErrNoDNSResults
276
+			}
277
+		}
278
+	}
279
+	return
280
+}
281
+
282
+// GetZoneKey returns the PKEY (or nil) from an absolute GNS path.
283
+func (gns *GNSModule) GetZoneKey(path string) *ed25519.PublicKey {
284
+	labels := util.ReverseStringList(strings.Split(path, "."))
285
+	if len(labels[0]) == 52 {
286
+		if data, err := util.DecodeStringToBinary(labels[0], 32); err == nil {
287
+			if pkey := ed25519.NewPublicKeyFromBytes(data); pkey != nil {
288
+				return pkey
289
+			}
290
+		}
291
+	}
292
+	return nil
293
+}
294
+
240 295
 // Lookup name in GNS.
241 296
 func (gns *GNSModule) Lookup(pkey *ed25519.PublicKey, label string, remote bool) (block *GNSBlock, err error) {
242 297
 

+ 33
- 0
src/gnunet/util/misc.go View File

@@ -0,0 +1,33 @@
1
+package util
2
+
3
+import (
4
+	"strings"
5
+)
6
+
7
+type CounterMap map[interface{}]int
8
+
9
+func (cm CounterMap) Add(i interface{}) int {
10
+	count, ok := cm[i]
11
+	if !ok {
12
+		count = 1
13
+	} else {
14
+		count++
15
+	}
16
+	cm[i] = count
17
+	return count
18
+}
19
+
20
+func (cm CounterMap) Num(i interface{}) int {
21
+	count, ok := cm[i]
22
+	if !ok {
23
+		count = 0
24
+	}
25
+	return count
26
+}
27
+
28
+func StripPathRight(s string) string {
29
+	if idx := strings.LastIndex(s, "."); idx != -1 {
30
+		return s[:idx]
31
+	}
32
+	return s
33
+}

Loading…
Cancel
Save