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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
#[cfg(test)]
mod attributes_test;
use crate::message::*;
use util::Error;
use std::fmt;
#[derive(Default, PartialEq, Eq, Debug, Clone)]
pub struct Attributes(pub Vec<RawAttribute>);
impl Attributes {
pub fn get(&self, t: AttrType) -> (RawAttribute, bool) {
for candidate in &self.0 {
if candidate.typ == t {
return (candidate.clone(), true);
}
}
(RawAttribute::default(), false)
}
}
#[derive(PartialEq, Debug, Eq, Default, Copy, Clone)]
pub struct AttrType(pub u16);
impl fmt::Display for AttrType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let other = format!("0x{:x}", self.0);
let s = match *self {
ATTR_MAPPED_ADDRESS => "MAPPED-ADDRESS",
ATTR_USERNAME => "USERNAME",
ATTR_ERROR_CODE => "ERROR-CODE",
ATTR_MESSAGE_INTEGRITY => "MESSAGE-INTEGRITY",
ATTR_UNKNOWN_ATTRIBUTES => "UNKNOWN-ATTRIBUTES",
ATTR_REALM => "REALM",
ATTR_NONCE => "NONCE",
ATTR_XORMAPPED_ADDRESS => "XOR-MAPPED-ADDRESS",
ATTR_SOFTWARE => "SOFTWARE",
ATTR_ALTERNATE_SERVER => "ALTERNATE-SERVER",
ATTR_FINGERPRINT => "FINGERPRINT",
ATTR_PRIORITY => "PRIORITY",
ATTR_USE_CANDIDATE => "USE-CANDIDATE",
ATTR_ICE_CONTROLLED => "ICE-CONTROLLED",
ATTR_ICE_CONTROLLING => "ICE-CONTROLLING",
ATTR_CHANNEL_NUMBER => "CHANNEL-NUMBER",
ATTR_LIFETIME => "LIFETIME",
ATTR_XOR_PEER_ADDRESS => "XOR-PEER-ADDRESS",
ATTR_DATA => "DATA",
ATTR_XOR_RELAYED_ADDRESS => "XOR-RELAYED-ADDRESS",
ATTR_EVEN_PORT => "EVEN-PORT",
ATTR_REQUESTED_TRANSPORT => "REQUESTED-TRANSPORT",
ATTR_DONT_FRAGMENT => "DONT-FRAGMENT",
ATTR_RESERVATION_TOKEN => "RESERVATION-TOKEN",
ATTR_CONNECTION_ID => "CONNECTION-ID",
ATTR_REQUESTED_ADDRESS_FAMILY => "REQUESTED-ADDRESS-FAMILY",
ATTR_MESSAGE_INTEGRITY_SHA256 => "MESSAGE-INTEGRITY-SHA256",
ATTR_PASSWORD_ALGORITHM => "PASSWORD-ALGORITHM",
ATTR_USER_HASH => "USERHASH",
ATTR_PASSWORD_ALGORITHMS => "PASSWORD-ALGORITHMS",
ATTR_ALTERNATE_DOMAIN => "ALTERNATE-DOMAIN",
_ => other.as_str(),
};
write!(f, "{}", s)
}
}
impl AttrType {
pub fn required(&self) -> bool {
self.0 <= 0x7FFF
}
pub fn optional(&self) -> bool {
self.0 >= 0x8000
}
pub fn value(&self) -> u16 {
self.0
}
}
pub const ATTR_MAPPED_ADDRESS: AttrType = AttrType(0x0001);
pub const ATTR_USERNAME: AttrType = AttrType(0x0006);
pub const ATTR_MESSAGE_INTEGRITY: AttrType = AttrType(0x0008);
pub const ATTR_ERROR_CODE: AttrType = AttrType(0x0009);
pub const ATTR_UNKNOWN_ATTRIBUTES: AttrType = AttrType(0x000A);
pub const ATTR_REALM: AttrType = AttrType(0x0014);
pub const ATTR_NONCE: AttrType = AttrType(0x0015);
pub const ATTR_XORMAPPED_ADDRESS: AttrType = AttrType(0x0020);
pub const ATTR_SOFTWARE: AttrType = AttrType(0x8022);
pub const ATTR_ALTERNATE_SERVER: AttrType = AttrType(0x8023);
pub const ATTR_FINGERPRINT: AttrType = AttrType(0x8028);
pub const ATTR_PRIORITY: AttrType = AttrType(0x0024);
pub const ATTR_USE_CANDIDATE: AttrType = AttrType(0x0025);
pub const ATTR_ICE_CONTROLLED: AttrType = AttrType(0x8029);
pub const ATTR_ICE_CONTROLLING: AttrType = AttrType(0x802A);
pub const ATTR_CHANNEL_NUMBER: AttrType = AttrType(0x000C);
pub const ATTR_LIFETIME: AttrType = AttrType(0x000D);
pub const ATTR_XOR_PEER_ADDRESS: AttrType = AttrType(0x0012);
pub const ATTR_DATA: AttrType = AttrType(0x0013);
pub const ATTR_XOR_RELAYED_ADDRESS: AttrType = AttrType(0x0016);
pub const ATTR_EVEN_PORT: AttrType = AttrType(0x0018);
pub const ATTR_REQUESTED_TRANSPORT: AttrType = AttrType(0x0019);
pub const ATTR_DONT_FRAGMENT: AttrType = AttrType(0x001A);
pub const ATTR_RESERVATION_TOKEN: AttrType = AttrType(0x0022);
pub const ATTR_CHANGE_REQUEST: AttrType = AttrType(0x0003);
pub const ATTR_PADDING: AttrType = AttrType(0x0026);
pub const ATTR_RESPONSE_PORT: AttrType = AttrType(0x0027);
pub const ATTR_CACHE_TIMEOUT: AttrType = AttrType(0x8027);
pub const ATTR_RESPONSE_ORIGIN: AttrType = AttrType(0x802b);
pub const ATTR_OTHER_ADDRESS: AttrType = AttrType(0x802C);
pub const ATTR_SOURCE_ADDRESS: AttrType = AttrType(0x0004);
pub const ATTR_CHANGED_ADDRESS: AttrType = AttrType(0x0005);
pub const ATTR_CONNECTION_ID: AttrType = AttrType(0x002a);
pub const ATTR_REQUESTED_ADDRESS_FAMILY: AttrType = AttrType(0x0017);
pub const ATTR_ORIGIN: AttrType = AttrType(0x802F);
pub const ATTR_MESSAGE_INTEGRITY_SHA256: AttrType = AttrType(0x001C);
pub const ATTR_PASSWORD_ALGORITHM: AttrType = AttrType(0x001D);
pub const ATTR_USER_HASH: AttrType = AttrType(0x001E);
pub const ATTR_PASSWORD_ALGORITHMS: AttrType = AttrType(0x8002);
pub const ATTR_ALTERNATE_DOMAIN: AttrType = AttrType(0x8003);
#[derive(Default, Debug, Clone, PartialEq, Eq)]
pub struct RawAttribute {
pub typ: AttrType,
pub length: u16,
pub value: Vec<u8>,
}
impl fmt::Display for RawAttribute {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}: {:?}", self.typ, self.value)
}
}
impl Setter for RawAttribute {
fn add_to(&self, m: &mut Message) -> Result<(), Error> {
m.add(self.typ, &self.value);
Ok(())
}
}
pub(crate) const PADDING: usize = 4;
pub(crate) fn nearest_padded_value_length(l: usize) -> usize {
let mut n = PADDING * (l / PADDING);
if n < l {
n += PADDING
}
n
}
pub(crate) fn compat_attr_type(val: u16) -> AttrType {
if val == 0x8020 {
ATTR_XORMAPPED_ADDRESS
} else {
AttrType(val)
}
}