diff options
author | Bernd Fix <brf@hoi-polloi.org> | 2019-12-23 12:21:56 +0100 |
---|---|---|
committer | Bernd Fix <brf@hoi-polloi.org> | 2019-12-23 12:21:56 +0100 |
commit | 8e4c1501b82cdbba6c545a4b49eb5b65050579ba (patch) | |
tree | 8b7bae3a79d6b4f69bc9290e6fe279b05493dc2a /src | |
parent | 96e32f827e626dac13bb7615cd473998ce2ce3a9 (diff) | |
download | gnunet-go-8e4c1501b82cdbba6c545a4b49eb5b65050579ba.tar.gz gnunet-go-8e4c1501b82cdbba6c545a4b49eb5b65050579ba.zip |
Changes after review feedback.
Diffstat (limited to 'src')
-rw-r--r-- | src/gnunet/enums/gns.go | 5 | ||||
-rw-r--r-- | src/gnunet/service/gns/block_handler.go | 147 | ||||
-rw-r--r-- | src/gnunet/service/gns/module.go | 19 |
3 files changed, 157 insertions, 14 deletions
diff --git a/src/gnunet/enums/gns.go b/src/gnunet/enums/gns.go index d5b1f7a..1d45fff 100644 --- a/src/gnunet/enums/gns.go +++ b/src/gnunet/enums/gns.go | |||
@@ -4,6 +4,11 @@ package enums | |||
4 | var ( | 4 | var ( |
5 | GNS_MAX_BLOCK_SIZE = (63 * 1024) // Maximum size of a value that can be stored in a GNS block. | 5 | GNS_MAX_BLOCK_SIZE = (63 * 1024) // Maximum size of a value that can be stored in a GNS block. |
6 | 6 | ||
7 | // GNS record flags | ||
8 | GNS_FLAG_PRIVATE = 2 | ||
9 | GNS_FLAGS_EXPREL = 8 | ||
10 | GNS_FLAG_SHADOW = 16 | ||
11 | |||
7 | // GNS record types | 12 | // GNS record types |
8 | GNS_TYPE_ANY = 0 // Record type indicating any record/'*' | 13 | GNS_TYPE_ANY = 0 // Record type indicating any record/'*' |
9 | GNS_TYPE_DNS_A = 1 // [RFC1035] IPv4 Address record | 14 | GNS_TYPE_DNS_A = 1 // [RFC1035] IPv4 Address record |
diff --git a/src/gnunet/service/gns/block_handler.go b/src/gnunet/service/gns/block_handler.go index bf65e95..c3372f2 100644 --- a/src/gnunet/service/gns/block_handler.go +++ b/src/gnunet/service/gns/block_handler.go | |||
@@ -21,6 +21,7 @@ var ( | |||
21 | ErrInvalidRecordBody = fmt.Errorf("Invalid resource record body") | 21 | ErrInvalidRecordBody = fmt.Errorf("Invalid resource record body") |
22 | ErrInvalidPKEY = fmt.Errorf("Invalid PKEY resource record") | 22 | ErrInvalidPKEY = fmt.Errorf("Invalid PKEY resource record") |
23 | ErrInvalidCNAME = fmt.Errorf("Invalid CNAME resource record") | 23 | ErrInvalidCNAME = fmt.Errorf("Invalid CNAME resource record") |
24 | ErrInvalidVPN = fmt.Errorf("Invalid VPN resource record") | ||
24 | ErrInvalidRecordMix = fmt.Errorf("Invalid mix of RR types in block") | 25 | ErrInvalidRecordMix = fmt.Errorf("Invalid mix of RR types in block") |
25 | ErrBlockHandler = fmt.Errorf("Internal block handler failure") | 26 | ErrBlockHandler = fmt.Errorf("Internal block handler failure") |
26 | ) | 27 | ) |
@@ -33,6 +34,7 @@ var ( | |||
33 | enums.GNS_TYPE_BOX: NewBoxHandler, | 34 | enums.GNS_TYPE_BOX: NewBoxHandler, |
34 | enums.GNS_TYPE_LEHO: NewLehoHandler, | 35 | enums.GNS_TYPE_LEHO: NewLehoHandler, |
35 | enums.GNS_TYPE_DNS_CNAME: NewCnameHandler, | 36 | enums.GNS_TYPE_DNS_CNAME: NewCnameHandler, |
37 | enums.GNS_TYPE_VPN: NewVpnHandler, | ||
36 | } | 38 | } |
37 | ) | 39 | ) |
38 | 40 | ||
@@ -60,6 +62,9 @@ type BlockHandler interface { | |||
60 | // Records returns a list of RR of the given types associated with | 62 | // Records returns a list of RR of the given types associated with |
61 | // the custom handler | 63 | // the custom handler |
62 | Records(kind RRTypeList) *GNSRecordSet | 64 | Records(kind RRTypeList) *GNSRecordSet |
65 | |||
66 | // Name returns the human-readable name of the handler | ||
67 | Name() string | ||
63 | } | 68 | } |
64 | 69 | ||
65 | //---------------------------------------------------------------------- | 70 | //---------------------------------------------------------------------- |
@@ -71,6 +76,9 @@ type BlockHandler interface { | |||
71 | // The BlockHandlerList maintains a map of actually instantiated handlers | 76 | // The BlockHandlerList maintains a map of actually instantiated handlers |
72 | // (indexed by record type) and a list of record types (with occurrence | 77 | // (indexed by record type) and a list of record types (with occurrence |
73 | // count) in the block. | 78 | // count) in the block. |
79 | // The instance is also responsible for any required post-processing like | ||
80 | // filtering out expired records (and eventually "activating" associated | ||
81 | // shadow records collect from the same block). | ||
74 | //---------------------------------------------------------------------- | 82 | //---------------------------------------------------------------------- |
75 | 83 | ||
76 | // BlockHandlerList is a list of block handlers instantiated. | 84 | // BlockHandlerList is a list of block handlers instantiated. |
@@ -81,15 +89,46 @@ type BlockHandlerList struct { | |||
81 | 89 | ||
82 | // NewBlockHandlerList instantiates an a list of active block handlers | 90 | // NewBlockHandlerList instantiates an a list of active block handlers |
83 | // for a given set of records (GNS block). | 91 | // for a given set of records (GNS block). |
84 | func NewBlockHandlerList(records []*message.GNSResourceRecord, labels []string) (*BlockHandlerList, error) { | 92 | func NewBlockHandlerList(records []*message.GNSResourceRecord, labels []string) (*BlockHandlerList, []*message.GNSResourceRecord, error) { |
85 | // initialize block handler list | 93 | // initialize block handler list |
86 | hl := &BlockHandlerList{ | 94 | hl := &BlockHandlerList{ |
87 | list: make(map[int]BlockHandler), | 95 | list: make(map[int]BlockHandler), |
88 | counts: make(util.CounterMap), | 96 | counts: make(util.CounterMap), |
89 | } | 97 | } |
90 | 98 | ||
91 | // Traverse record list and build list of handler instances | 99 | // first pass: build list of shadow records in this block |
100 | shadows := make([]*message.GNSResourceRecord, 0) | ||
101 | for _, rec := range records { | ||
102 | // filter out shadow records... | ||
103 | if (int(rec.Flags) & enums.GNS_FLAG_SHADOW) != 0 { | ||
104 | shadows = append(shadows, rec) | ||
105 | } | ||
106 | } | ||
107 | // second pass: normalize block by filtering out expired records (and | ||
108 | // replacing them with shadow records if available | ||
109 | active := make([]*message.GNSResourceRecord, 0) | ||
92 | for _, rec := range records { | 110 | for _, rec := range records { |
111 | // don't process shadow records again | ||
112 | if (int(rec.Flags) & enums.GNS_FLAG_SHADOW) != 0 { | ||
113 | continue | ||
114 | } | ||
115 | // check for expired record | ||
116 | if rec.Expires.Expired() { | ||
117 | // do we have an associated shadow record? | ||
118 | for _, shadow := range shadows { | ||
119 | if shadow.Type == rec.Type && !shadow.Expires.Expired() { | ||
120 | // deliver un-expired shadow record instead. | ||
121 | shadow.Flags &^= uint32(enums.GNS_FLAG_SHADOW) | ||
122 | active = append(active, shadow) | ||
123 | } | ||
124 | } | ||
125 | } else { | ||
126 | active = append(active, rec) | ||
127 | } | ||
128 | } | ||
129 | |||
130 | // Third pass: Traverse active list and build list of handler instances. | ||
131 | for _, rec := range active { | ||
93 | // update counter map | 132 | // update counter map |
94 | rrType := int(rec.Type) | 133 | rrType := int(rec.Type) |
95 | hl.counts.Add(rrType) | 134 | hl.counts.Add(rrType) |
@@ -104,13 +143,13 @@ func NewBlockHandlerList(records []*message.GNSResourceRecord, labels []string) | |||
104 | if hdlr, ok = hl.list[rrType]; ok { | 143 | if hdlr, ok = hl.list[rrType]; ok { |
105 | // add record to existing handler | 144 | // add record to existing handler |
106 | if err = hdlr.AddRecord(rec, labels); err != nil { | 145 | if err = hdlr.AddRecord(rec, labels); err != nil { |
107 | return nil, err | 146 | return nil, active, err |
108 | } | 147 | } |
109 | continue | 148 | continue |
110 | } | 149 | } |
111 | // create a new handler instance | 150 | // create a new handler instance |
112 | if hdlr, err = creat(rec, labels); err != nil { | 151 | if hdlr, err = creat(rec, labels); err != nil { |
113 | return nil, err | 152 | return nil, active, err |
114 | } | 153 | } |
115 | // store handler in list | 154 | // store handler in list |
116 | hl.list[rrType] = hdlr | 155 | hl.list[rrType] = hdlr |
@@ -121,11 +160,12 @@ func NewBlockHandlerList(records []*message.GNSResourceRecord, labels []string) | |||
121 | // all the other records of varying type | 160 | // all the other records of varying type |
122 | for _, hdlr := range hl.list { | 161 | for _, hdlr := range hl.list { |
123 | if !hdlr.Coexist(hl.counts) { | 162 | if !hdlr.Coexist(hl.counts) { |
124 | return nil, ErrInvalidRecordMix | 163 | logger.Printf(logger.ERROR, "[gns] %s.Coexist() failed!\n", hdlr.Name()) |
164 | return nil, active, ErrInvalidRecordMix | ||
125 | } | 165 | } |
126 | } | 166 | } |
127 | // return assembled handler list | 167 | // return assembled handler list |
128 | return hl, nil | 168 | return hl, active, nil |
129 | } | 169 | } |
130 | 170 | ||
131 | // GetHandler returns a BlockHandler for the given key. If no block handler exists | 171 | // GetHandler returns a BlockHandler for the given key. If no block handler exists |
@@ -139,6 +179,12 @@ func (hl *BlockHandlerList) GetHandler(t int) BlockHandler { | |||
139 | return nil | 179 | return nil |
140 | } | 180 | } |
141 | 181 | ||
182 | // FinalizeRecord post-processes records | ||
183 | func (hl *BlockHandlerList) FinalizeRecord(rec *message.GNSResourceRecord) *message.GNSResourceRecord { | ||
184 | // no implementation yet | ||
185 | return rec | ||
186 | } | ||
187 | |||
142 | //---------------------------------------------------------------------- | 188 | //---------------------------------------------------------------------- |
143 | // PKEY handler: Only one PKEY as sole record in a block | 189 | // PKEY handler: Only one PKEY as sole record in a block |
144 | //---------------------------------------------------------------------- | 190 | //---------------------------------------------------------------------- |
@@ -198,13 +244,18 @@ func (h *PkeyHandler) Records(kind RRTypeList) *GNSRecordSet { | |||
198 | return rs | 244 | return rs |
199 | } | 245 | } |
200 | 246 | ||
247 | // Name returns the human-readable name of the handler. | ||
248 | func (h *PkeyHandler) Name() string { | ||
249 | return "PKEY_Handler" | ||
250 | } | ||
251 | |||
201 | //---------------------------------------------------------------------- | 252 | //---------------------------------------------------------------------- |
202 | // GNS2DNS handler | 253 | // GNS2DNS handler |
203 | //---------------------------------------------------------------------- | 254 | //---------------------------------------------------------------------- |
204 | 255 | ||
205 | // Gns2DnsHandler implementing the BlockHandler interface | 256 | // Gns2DnsHandler implementing the BlockHandler interface |
206 | type Gns2DnsHandler struct { | 257 | type Gns2DnsHandler struct { |
207 | Name string // DNS query name | 258 | Query string // DNS query name |
208 | Servers []string // DNS servers to ask | 259 | Servers []string // DNS servers to ask |
209 | recs []*message.GNSResourceRecord // list of rersource records | 260 | recs []*message.GNSResourceRecord // list of rersource records |
210 | } | 261 | } |
@@ -215,7 +266,7 @@ func NewGns2DnsHandler(rec *message.GNSResourceRecord, labels []string) (BlockHa | |||
215 | return nil, ErrInvalidRecordType | 266 | return nil, ErrInvalidRecordType |
216 | } | 267 | } |
217 | h := &Gns2DnsHandler{ | 268 | h := &Gns2DnsHandler{ |
218 | Name: "", | 269 | Query: "", |
219 | Servers: make([]string, 0), | 270 | Servers: make([]string, 0), |
220 | recs: make([]*message.GNSResourceRecord, 0), | 271 | recs: make([]*message.GNSResourceRecord, 0), |
221 | } | 272 | } |
@@ -242,9 +293,9 @@ func (h *Gns2DnsHandler) AddRecord(rec *message.GNSResourceRecord, labels []stri | |||
242 | 293 | ||
243 | // check if all GNS2DNS records refer to the same query name | 294 | // check if all GNS2DNS records refer to the same query name |
244 | if len(h.Servers) == 0 { | 295 | if len(h.Servers) == 0 { |
245 | h.Name = dnsQuery | 296 | h.Query = dnsQuery |
246 | } | 297 | } |
247 | if dnsQuery != h.Name { | 298 | if dnsQuery != h.Query { |
248 | return ErrInvalidRecordBody | 299 | return ErrInvalidRecordBody |
249 | } | 300 | } |
250 | h.Servers = append(h.Servers, dnsServer) | 301 | h.Servers = append(h.Servers, dnsServer) |
@@ -270,6 +321,11 @@ func (h *Gns2DnsHandler) Records(kind RRTypeList) *GNSRecordSet { | |||
270 | return rs | 321 | return rs |
271 | } | 322 | } |
272 | 323 | ||
324 | // Name returns the human-readable name of the handler. | ||
325 | func (h *Gns2DnsHandler) Name() string { | ||
326 | return "GNS2DNS_Handler" | ||
327 | } | ||
328 | |||
273 | //---------------------------------------------------------------------- | 329 | //---------------------------------------------------------------------- |
274 | // BOX handler | 330 | // BOX handler |
275 | //---------------------------------------------------------------------- | 331 | //---------------------------------------------------------------------- |
@@ -342,6 +398,11 @@ func (h *BoxHandler) Records(kind RRTypeList) *GNSRecordSet { | |||
342 | return rs | 398 | return rs |
343 | } | 399 | } |
344 | 400 | ||
401 | // Name returns the human-readable name of the handler. | ||
402 | func (h *BoxHandler) Name() string { | ||
403 | return "BOX_Handler" | ||
404 | } | ||
405 | |||
345 | //---------------------------------------------------------------------- | 406 | //---------------------------------------------------------------------- |
346 | // LEHO handler | 407 | // LEHO handler |
347 | //---------------------------------------------------------------------- | 408 | //---------------------------------------------------------------------- |
@@ -386,7 +447,7 @@ func (h *LehoHandler) Coexist(cm util.CounterMap) bool { | |||
386 | if cm.Num(enums.GNS_TYPE_LEHO) != 1 { | 447 | if cm.Num(enums.GNS_TYPE_LEHO) != 1 { |
387 | return false | 448 | return false |
388 | } | 449 | } |
389 | return cm.Num(enums.GNS_TYPE_DNS_A) == 1 || cm.Num(enums.GNS_TYPE_DNS_AAAA) == 1 | 450 | return (cm.Num(enums.GNS_TYPE_DNS_A) + cm.Num(enums.GNS_TYPE_DNS_AAAA)) > 1 |
390 | } | 451 | } |
391 | 452 | ||
392 | // Records returns a list of RR of the given type associated with this handler | 453 | // Records returns a list of RR of the given type associated with this handler |
@@ -398,6 +459,11 @@ func (h *LehoHandler) Records(kind RRTypeList) *GNSRecordSet { | |||
398 | return rs | 459 | return rs |
399 | } | 460 | } |
400 | 461 | ||
462 | // Name returns the human-readable name of the handler. | ||
463 | func (h *LehoHandler) Name() string { | ||
464 | return "LEHO_Handler" | ||
465 | } | ||
466 | |||
401 | //---------------------------------------------------------------------- | 467 | //---------------------------------------------------------------------- |
402 | // CNAME handler | 468 | // CNAME handler |
403 | //---------------------------------------------------------------------- | 469 | //---------------------------------------------------------------------- |
@@ -450,3 +516,62 @@ func (h *CnameHandler) Records(kind RRTypeList) *GNSRecordSet { | |||
450 | } | 516 | } |
451 | return rs | 517 | return rs |
452 | } | 518 | } |
519 | |||
520 | // Name returns the human-readable name of the handler. | ||
521 | func (h *CnameHandler) Name() string { | ||
522 | return "CNAME_Handler" | ||
523 | } | ||
524 | |||
525 | //---------------------------------------------------------------------- | ||
526 | // VPN handler | ||
527 | //---------------------------------------------------------------------- | ||
528 | |||
529 | // VpnHandler implementing the BlockHandler interface | ||
530 | type VpnHandler struct { | ||
531 | rec *message.GNSResourceRecord | ||
532 | } | ||
533 | |||
534 | // NewVpnHandler returns a new BlockHandler instance | ||
535 | func NewVpnHandler(rec *message.GNSResourceRecord, labels []string) (BlockHandler, error) { | ||
536 | if int(rec.Type) != enums.GNS_TYPE_VPN { | ||
537 | return nil, ErrInvalidRecordType | ||
538 | } | ||
539 | h := &VpnHandler{} | ||
540 | if err := h.AddRecord(rec, labels); err != nil { | ||
541 | return nil, err | ||
542 | } | ||
543 | return h, nil | ||
544 | } | ||
545 | |||
546 | // AddRecord inserts a VPN record into the handler. | ||
547 | func (h *VpnHandler) AddRecord(rec *message.GNSResourceRecord, labels []string) error { | ||
548 | if int(rec.Type) != enums.GNS_TYPE_VPN { | ||
549 | return ErrInvalidRecordType | ||
550 | } | ||
551 | if h.rec != nil { | ||
552 | return ErrInvalidVPN | ||
553 | } | ||
554 | h.rec = rec | ||
555 | return nil | ||
556 | } | ||
557 | |||
558 | // Coexist return a flag indicating how a resource record of a given type | ||
559 | // is to be treated (see BlockHandler interface) | ||
560 | func (h *VpnHandler) Coexist(cm util.CounterMap) bool { | ||
561 | // anything goes | ||
562 | return true | ||
563 | } | ||
564 | |||
565 | // Records returns a list of RR of the given type associated with this handler | ||
566 | func (h *VpnHandler) Records(kind RRTypeList) *GNSRecordSet { | ||
567 | rs := NewGNSRecordSet() | ||
568 | if kind.HasType(enums.GNS_TYPE_VPN) { | ||
569 | rs.AddRecord(h.rec) | ||
570 | } | ||
571 | return rs | ||
572 | } | ||
573 | |||
574 | // Name returns the human-readable name of the handler. | ||
575 | func (h *VpnHandler) Name() string { | ||
576 | return "VPN_Handler" | ||
577 | } | ||
diff --git a/src/gnunet/service/gns/module.go b/src/gnunet/service/gns/module.go index 6732e08..b5583ac 100644 --- a/src/gnunet/service/gns/module.go +++ b/src/gnunet/service/gns/module.go | |||
@@ -167,7 +167,7 @@ func (gns *GNSModule) ResolveRelative(labels []string, pkey *ed25519.PublicKey, | |||
167 | // assemble a list of block handlers for this block: if multiple | 167 | // assemble a list of block handlers for this block: if multiple |
168 | // block handlers are present, they are consistent with all block | 168 | // block handlers are present, they are consistent with all block |
169 | // records. | 169 | // records. |
170 | if hdlrs, err = NewBlockHandlerList(records, labels[1:]); err != nil { | 170 | if hdlrs, records, err = NewBlockHandlerList(records, labels[1:]); err != nil { |
171 | // conflicting block handler records found: terminate with error. | 171 | // conflicting block handler records found: terminate with error. |
172 | // (N.B.: The BlockHandlerList class executes the logic which mix | 172 | // (N.B.: The BlockHandlerList class executes the logic which mix |
173 | // of resource records in a single block is considered valid.) | 173 | // of resource records in a single block is considered valid.) |
@@ -203,7 +203,7 @@ func (gns *GNSModule) ResolveRelative(labels []string, pkey *ed25519.PublicKey, | |||
203 | if len(lbls) > 0 { | 203 | if len(lbls) > 0 { |
204 | lbls += "." | 204 | lbls += "." |
205 | } | 205 | } |
206 | fqdn := lbls + inst.Name | 206 | fqdn := lbls + inst.Query |
207 | if set, err = gns.ResolveDNS(fqdn, inst.Servers, kind, pkey); err != nil { | 207 | if set, err = gns.ResolveDNS(fqdn, inst.Servers, kind, pkey); err != nil { |
208 | logger.Println(logger.ERROR, "[gns] GNS2DNS resolution failed.") | 208 | logger.Println(logger.ERROR, "[gns] GNS2DNS resolution failed.") |
209 | return | 209 | return |
@@ -243,7 +243,20 @@ func (gns *GNSModule) ResolveRelative(labels []string, pkey *ed25519.PublicKey, | |||
243 | // is this the record type we are looking for? | 243 | // is this the record type we are looking for? |
244 | if kind.HasType(int(rec.Type)) { | 244 | if kind.HasType(int(rec.Type)) { |
245 | // add it to the result | 245 | // add it to the result |
246 | set.AddRecord(rec) | 246 | if rec = hdlrs.FinalizeRecord(rec); rec != nil { |
247 | set.AddRecord(rec) | ||
248 | } | ||
249 | } | ||
250 | } | ||
251 | |||
252 | // if no records of the requested type (either A or AAAA) have been found, | ||
253 | // and we have a VPN record, return this instead. | ||
254 | if set.Count == 0 && (kind.HasType(enums.GNS_TYPE_DNS_A) || kind.HasType(enums.GNS_TYPE_DNS_AAAA)) { | ||
255 | // check for VPN record | ||
256 | if hdlr := hdlrs.GetHandler(enums.GNS_TYPE_VPN); hdlr != nil { | ||
257 | // add VPN record to result set | ||
258 | inst := hdlr.(*VpnHandler) | ||
259 | set.AddRecord(inst.rec) | ||
247 | } | 260 | } |
248 | } | 261 | } |
249 | return | 262 | return |