forked from layeh/radius
-
Notifications
You must be signed in to change notification settings - Fork 2
/
attributes.go
115 lines (98 loc) · 2.51 KB
/
attributes.go
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
package radius
import (
"errors"
"sort"
)
// Type is the RADIUS attribute type.
type Type int
// TypeInvalid is a Type that can be used to represent an invalid RADIUS
// attribute type.
const TypeInvalid Type = -1
// Attributes is a map of RADIUS attribute types to slice of Attributes.
type Attributes map[Type][]Attribute
// ParseAttributes parses the wire-encoded RADIUS attributes and returns a new
// Attributes value. An error is returned if the buffer is malformed.
func ParseAttributes(b []byte) (Attributes, error) {
attrs := make(map[Type][]Attribute)
for len(b) > 0 {
if len(b) < 2 {
return nil, errors.New("short buffer")
}
length := int(b[1])
if length > len(b) || length < 2 || length > 255 {
return nil, errors.New("invalid attribute length")
}
typ := Type(b[0])
var value Attribute
if length > 2 {
value = make(Attribute, length-2)
copy(value, b[2:])
}
attrs[typ] = append(attrs[typ], value)
b = b[length:]
}
return attrs, nil
}
// Add appends the given Attribute to the map entry of the given type.
func (a Attributes) Add(key Type, value Attribute) {
a[key] = append(a[key], value)
}
// Del removes all Attributes of the given type from a.
func (a Attributes) Del(key Type) {
delete(a, key)
}
// Get returns the first Attribute of Type key. nil is returned if no Attribute
// of Type key exists in a.
func (a Attributes) Get(key Type) Attribute {
attr, _ := a.Lookup(key)
return attr
}
// Lookup returns the first Attribute of Type key. nil and false is returned if
// no Attribute of Type key exists in a.
func (a Attributes) Lookup(key Type) (Attribute, bool) {
m := a[key]
if len(m) == 0 {
return nil, false
}
return m[0], true
}
// Set removes all Attributes of Type key and appends value.
func (a Attributes) Set(key Type, value Attribute) {
a[key] = append(a[key][:0], value)
}
func (a Attributes) encodeTo(b []byte) {
types := make([]int, 0, len(a))
for typ := range a {
if typ >= 1 && typ <= 255 {
types = append(types, int(typ))
}
}
sort.Ints(types)
for _, typ := range types {
for _, attr := range a[Type(typ)] {
if len(attr) > 255 {
continue
}
size := 1 + 1 + len(attr)
b[0] = byte(typ)
b[1] = byte(size)
copy(b[2:], attr)
b = b[size:]
}
}
}
func (a Attributes) wireSize() (bytes int) {
for typ, attrs := range a {
if typ < 1 || typ > 255 {
continue
}
for _, attr := range attrs {
if len(attr) > 255 {
return -1
}
// type field + length field + value field
bytes += 1 + 1 + len(attr)
}
}
return
}