Source code

Revision control

Other Tools

1
/*
2
Copyright (c) 2007, Adobe Systems, Incorporated
3
All rights reserved.
4
5
Redistribution and use in source and binary forms, with or without
6
modification, are permitted provided that the following conditions are
7
met:
8
9
* Redistributions of source code must retain the above copyright
10
notice, this list of conditions and the following disclaimer.
11
12
* Redistributions in binary form must reproduce the above copyright
13
notice, this list of conditions and the following disclaimer in the
14
documentation and/or other materials provided with the distribution.
15
16
* Neither the name of Adobe Systems, Network Resonance nor the names of its
17
contributors may be used to endorse or promote products derived from
18
this software without specific prior written permission.
19
20
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
*/
32
33
#include <errno.h>
34
#include <csi_platform.h>
35
36
#ifdef WIN32
37
#include <winsock2.h>
38
#include <stdlib.h>
39
#include <io.h>
40
#include <time.h>
41
#else /* UNIX */
42
#include <string.h>
43
#endif /* end UNIX */
44
#include <assert.h>
45
46
#include "stun.h"
47
48
49
int
50
nr_stun_message_create(nr_stun_message **msg)
51
{
52
int _status;
53
nr_stun_message *m = 0;
54
55
m = RCALLOC(sizeof(*m));
56
if (!m)
57
ABORT(R_NO_MEMORY);
58
59
TAILQ_INIT(&m->attributes);
60
61
*msg = m;
62
63
_status=0;
64
abort:
65
return(_status);
66
}
67
68
int
69
nr_stun_message_create2(nr_stun_message **msg, UCHAR *buffer, size_t length)
70
{
71
int r,_status;
72
nr_stun_message *m = 0;
73
74
if (length > sizeof(m->buffer)) {
75
ABORT(R_BAD_DATA);
76
}
77
78
if ((r=nr_stun_message_create(&m)))
79
ABORT(r);
80
81
memcpy(m->buffer, buffer, length);
82
m->length = length;
83
84
*msg = m;
85
86
_status=0;
87
abort:
88
return(_status);
89
}
90
91
int
92
nr_stun_message_destroy(nr_stun_message **msg)
93
{
94
int _status;
95
nr_stun_message_attribute_head *attrs;
96
nr_stun_message_attribute *attr;
97
98
if (msg && *msg) {
99
attrs = &(*msg)->attributes;
100
while (!TAILQ_EMPTY(attrs)) {
101
attr = TAILQ_FIRST(attrs);
102
nr_stun_message_attribute_destroy(*msg, &attr);
103
}
104
105
RFREE(*msg);
106
107
*msg = 0;
108
}
109
110
_status=0;
111
/* abort: */
112
return(_status);
113
}
114
115
int
116
nr_stun_message_attribute_create(nr_stun_message *msg, nr_stun_message_attribute **attr)
117
{
118
int _status;
119
nr_stun_message_attribute *a = 0;
120
121
a = RCALLOC(sizeof(*a));
122
if (!a)
123
ABORT(R_NO_MEMORY);
124
125
TAILQ_INSERT_TAIL(&msg->attributes, a, entry);
126
127
*attr = a;
128
129
_status=0;
130
abort:
131
return(_status);
132
}
133
134
int
135
nr_stun_message_attribute_destroy(nr_stun_message *msg, nr_stun_message_attribute **attr)
136
{
137
int _status;
138
nr_stun_message_attribute *a = 0;
139
140
if (attr && *attr) {
141
a = *attr;
142
TAILQ_REMOVE(&msg->attributes, a, entry);
143
144
RFREE(a);
145
146
*attr = 0;
147
}
148
149
_status=0;
150
/* abort: */
151
return(_status);
152
}
153
154
int
155
nr_stun_message_has_attribute(nr_stun_message *msg, UINT2 type, nr_stun_message_attribute **attribute)
156
{
157
nr_stun_message_attribute *attr = 0;
158
159
if (attribute)
160
*attribute = 0;
161
162
TAILQ_FOREACH(attr, &msg->attributes, entry) {
163
if (attr->type == type)
164
break;
165
}
166
167
if (!attr || attr->invalid)
168
return 0; /* does not have */
169
170
if (attribute)
171
*attribute = attr;
172
173
return 1; /* has */
174
}
175
176
#define NR_STUN_MESSAGE_ADD_ATTRIBUTE(__type, __code) \
177
{ \
178
int r,_status; \
179
nr_stun_message_attribute *attr = 0; \
180
if ((r=nr_stun_message_attribute_create(msg, &attr))) \
181
ABORT(r); \
182
attr->type = (__type); \
183
{ __code } \
184
_status=0; \
185
abort: \
186
if (_status){ \
187
nr_stun_message_attribute_destroy(msg, &attr); \
188
} \
189
return(_status); \
190
}
191
192
193
int
194
nr_stun_message_add_alternate_server_attribute(nr_stun_message *msg, nr_transport_addr *alternate_server)
195
NR_STUN_MESSAGE_ADD_ATTRIBUTE(
196
NR_STUN_ATTR_ALTERNATE_SERVER,
197
{
198
if ((r=nr_transport_addr_copy(&attr->u.alternate_server, alternate_server)))
199
ABORT(r);
200
}
201
)
202
203
int
204
nr_stun_message_add_error_code_attribute(nr_stun_message *msg, UINT2 number, char *reason)
205
NR_STUN_MESSAGE_ADD_ATTRIBUTE(
206
NR_STUN_ATTR_ERROR_CODE,
207
{
208
attr->u.error_code.number = number;
209
(void)strlcpy(attr->u.error_code.reason, reason, sizeof(attr->u.error_code.reason));
210
}
211
)
212
213
int
214
nr_stun_message_add_fingerprint_attribute(nr_stun_message *msg)
215
NR_STUN_MESSAGE_ADD_ATTRIBUTE(
216
NR_STUN_ATTR_FINGERPRINT,
217
{}
218
)
219
220
int
221
nr_stun_message_add_message_integrity_attribute(nr_stun_message *msg, Data *password)
222
NR_STUN_MESSAGE_ADD_ATTRIBUTE(
223
NR_STUN_ATTR_MESSAGE_INTEGRITY,
224
{
225
if (sizeof(attr->u.message_integrity.password) < password->len)
226
ABORT(R_BAD_DATA);
227
228
memcpy(attr->u.message_integrity.password, password->data, password->len);
229
attr->u.message_integrity.passwordlen = password->len;
230
}
231
)
232
233
int
234
nr_stun_message_add_nonce_attribute(nr_stun_message *msg, char *nonce)
235
NR_STUN_MESSAGE_ADD_ATTRIBUTE(
236
NR_STUN_ATTR_NONCE,
237
{ (void)strlcpy(attr->u.nonce, nonce, sizeof(attr->u.nonce)); }
238
)
239
240
int
241
nr_stun_message_add_realm_attribute(nr_stun_message *msg, char *realm)
242
NR_STUN_MESSAGE_ADD_ATTRIBUTE(
243
NR_STUN_ATTR_REALM,
244
{ (void)strlcpy(attr->u.realm, realm, sizeof(attr->u.realm)); }
245
)
246
247
int
248
nr_stun_message_add_server_attribute(nr_stun_message *msg, char *server_name)
249
NR_STUN_MESSAGE_ADD_ATTRIBUTE(
250
NR_STUN_ATTR_SERVER,
251
{ (void)strlcpy(attr->u.server_name, server_name, sizeof(attr->u.server_name)); }
252
)
253
254
int
255
nr_stun_message_add_unknown_attributes_attribute(nr_stun_message *msg, nr_stun_attr_unknown_attributes *unknown_attributes)
256
NR_STUN_MESSAGE_ADD_ATTRIBUTE(
257
NR_STUN_ATTR_UNKNOWN_ATTRIBUTES,
258
{ memcpy(&attr->u.unknown_attributes, unknown_attributes, sizeof(attr->u.unknown_attributes)); }
259
)
260
261
int
262
nr_stun_message_add_username_attribute(nr_stun_message *msg, char *username)
263
NR_STUN_MESSAGE_ADD_ATTRIBUTE(
264
NR_STUN_ATTR_USERNAME,
265
{ (void)strlcpy(attr->u.username, username, sizeof(attr->u.username)); }
266
)
267
268
int
269
nr_stun_message_add_requested_transport_attribute(nr_stun_message *msg, UCHAR protocol)
270
NR_STUN_MESSAGE_ADD_ATTRIBUTE(
271
NR_STUN_ATTR_REQUESTED_TRANSPORT,
272
{ attr->u.requested_transport = protocol; }
273
)
274
275
int
276
nr_stun_message_add_xor_mapped_address_attribute(nr_stun_message *msg, nr_transport_addr *mapped_address)
277
NR_STUN_MESSAGE_ADD_ATTRIBUTE(
278
NR_STUN_ATTR_XOR_MAPPED_ADDRESS,
279
{
280
if ((r=nr_transport_addr_copy(&attr->u.xor_mapped_address.unmasked, mapped_address)))
281
ABORT(r);
282
}
283
)
284
285
int
286
nr_stun_message_add_xor_peer_address_attribute(nr_stun_message *msg, nr_transport_addr *peer_address)
287
NR_STUN_MESSAGE_ADD_ATTRIBUTE(
288
NR_STUN_ATTR_XOR_PEER_ADDRESS,
289
{
290
if ((r=nr_transport_addr_copy(&attr->u.xor_mapped_address.unmasked, peer_address)))
291
ABORT(r);
292
}
293
)
294
295
#ifdef USE_ICE
296
int
297
nr_stun_message_add_ice_controlled_attribute(nr_stun_message *msg, UINT8 ice_controlled)
298
NR_STUN_MESSAGE_ADD_ATTRIBUTE(
299
NR_STUN_ATTR_ICE_CONTROLLED,
300
{ attr->u.ice_controlled = ice_controlled; }
301
)
302
303
int
304
nr_stun_message_add_ice_controlling_attribute(nr_stun_message *msg, UINT8 ice_controlling)
305
NR_STUN_MESSAGE_ADD_ATTRIBUTE(
306
NR_STUN_ATTR_ICE_CONTROLLING,
307
{ attr->u.ice_controlling = ice_controlling; }
308
)
309
310
int
311
nr_stun_message_add_priority_attribute(nr_stun_message *msg, UINT4 priority)
312
NR_STUN_MESSAGE_ADD_ATTRIBUTE(
313
NR_STUN_ATTR_PRIORITY,
314
{ attr->u.priority = priority; }
315
)
316
317
int
318
nr_stun_message_add_use_candidate_attribute(nr_stun_message *msg)
319
NR_STUN_MESSAGE_ADD_ATTRIBUTE(
320
NR_STUN_ATTR_USE_CANDIDATE,
321
{}
322
)
323
#endif /* USE_ICE */
324
325
#ifdef USE_TURN
326
int
327
nr_stun_message_add_data_attribute(nr_stun_message *msg, UCHAR *data, int length)
328
329
NR_STUN_MESSAGE_ADD_ATTRIBUTE(
330
NR_STUN_ATTR_DATA,
331
{
332
if (length > NR_STUN_MAX_MESSAGE_SIZE)
333
ABORT(R_BAD_ARGS);
334
335
memcpy(attr->u.data.data, data, length);
336
attr->u.data.length=length;
337
}
338
)
339
340
int
341
nr_stun_message_add_lifetime_attribute(nr_stun_message *msg, UINT4 lifetime_secs)
342
NR_STUN_MESSAGE_ADD_ATTRIBUTE(
343
NR_STUN_ATTR_LIFETIME,
344
{ attr->u.lifetime_secs = lifetime_secs; }
345
)
346
347
#endif /* USE_TURN */
348
349
#ifdef USE_STUND_0_96
350
int
351
nr_stun_message_add_change_request_attribute(nr_stun_message *msg, UINT4 change_request)
352
NR_STUN_MESSAGE_ADD_ATTRIBUTE(
353
NR_STUN_ATTR_OLD_CHANGE_REQUEST,
354
{ attr->u.change_request = change_request; }
355
)
356
#endif /* USE_STUND_0_96 */
357