Line data Source code
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 :
34 : static char *RCSSTRING __UNUSED__="$Id: stun_build.c,v 1.2 2008/04/28 18:21:30 ekr Exp $";
35 :
36 : #include <csi_platform.h>
37 : #include <assert.h>
38 : #include <errno.h>
39 : #include <stdio.h>
40 : #include <string.h>
41 : #include <ctype.h>
42 :
43 : #include "nr_api.h"
44 : #include "stun.h"
45 : #include "registry.h"
46 : #include "stun_reg.h"
47 : #include "nr_crypto.h"
48 :
49 :
50 : /* draft-ietf-behave-rfc3489bis-10.txt S 7.1 */
51 : /* draft-ietf-behave-rfc3489bis-10.txt S 10.1.1 */
52 : /* note that S 10.1.1 states the message MUST include MESSAGE-INTEGRITY
53 : * and USERNAME, but that's not correct -- for instance ICE keepalive
54 : * messages don't include these (See draft-ietf-mmusic-ice-18.txt S 10:
55 : * "If STUN is being used for keepalives, a STUN Binding Indication is
56 : * used. The Indication MUST NOT utilize any authentication mechanism")
57 : */
58 : int
59 0 : nr_stun_form_request_or_indication(int mode, int msg_type, nr_stun_message **msg)
60 : {
61 : int r,_status;
62 0 : nr_stun_message *req = 0;
63 :
64 0 : assert(NR_STUN_GET_TYPE_CLASS(msg_type) == NR_CLASS_REQUEST
65 : || NR_STUN_GET_TYPE_CLASS(msg_type) == NR_CLASS_INDICATION);
66 :
67 0 : *msg = 0;
68 :
69 0 : if ((r=nr_stun_message_create(&req)))
70 0 : ABORT(r);
71 :
72 0 : req->header.type = msg_type;
73 :
74 0 : nr_crypto_random_bytes((UCHAR*)&req->header.id,sizeof(req->header.id));
75 :
76 0 : switch (mode) {
77 : default:
78 0 : if ((r=nr_stun_message_add_fingerprint_attribute(req)))
79 0 : ABORT(r);
80 : /* fall through */
81 : case NR_STUN_MODE_STUN_NO_AUTH:
82 0 : req->header.magic_cookie = NR_STUN_MAGIC_COOKIE;
83 0 : break;
84 :
85 : #ifdef USE_STUND_0_96
86 : case NR_STUN_MODE_STUND_0_96:
87 0 : req->header.magic_cookie = NR_STUN_MAGIC_COOKIE2;
88 :
89 : /* actually, stund 0.96 just ignores the fingerprint
90 : * attribute, but don't bother to send it */
91 :
92 0 : break;
93 : #endif /* USE_STUND_0_96 */
94 :
95 : }
96 :
97 0 : *msg = req;
98 :
99 0 : _status=0;
100 : abort:
101 0 : if (_status) RFREE(req);
102 0 : return _status;
103 : }
104 :
105 : int
106 0 : nr_stun_build_req_lt_auth(nr_stun_client_stun_binding_request_params *params, nr_stun_message **msg)
107 : {
108 : int r,_status;
109 0 : nr_stun_message *req = 0;
110 :
111 0 : if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUN, NR_STUN_MSG_BINDING_REQUEST, &req)))
112 0 : ABORT(r);
113 :
114 0 : if ((r=nr_stun_message_add_username_attribute(req, params->username)))
115 0 : ABORT(r);
116 :
117 0 : if (params->realm && params->nonce) {
118 0 : if ((r=nr_stun_message_add_realm_attribute(req, params->realm)))
119 0 : ABORT(r);
120 :
121 0 : if ((r=nr_stun_message_add_nonce_attribute(req, params->nonce)))
122 0 : ABORT(r);
123 :
124 0 : if ((r=nr_stun_message_add_message_integrity_attribute(req, params->password)))
125 0 : ABORT(r);
126 : }
127 :
128 0 : *msg = req;
129 :
130 0 : _status=0;
131 : abort:
132 0 : if (_status) nr_stun_message_destroy(&req);
133 0 : return _status;
134 : }
135 :
136 : int
137 0 : nr_stun_build_req_st_auth(nr_stun_client_stun_binding_request_params *params, nr_stun_message **msg)
138 : {
139 : int r,_status;
140 0 : nr_stun_message *req = 0;
141 :
142 0 : if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUN, NR_STUN_MSG_BINDING_REQUEST, &req)))
143 0 : ABORT(r);
144 :
145 0 : if ((r=nr_stun_message_add_username_attribute(req, params->username)))
146 0 : ABORT(r);
147 :
148 0 : if (params->password) {
149 0 : if ((r=nr_stun_message_add_message_integrity_attribute(req, params->password)))
150 0 : ABORT(r);
151 : }
152 :
153 0 : *msg = req;
154 :
155 0 : _status=0;
156 : abort:
157 0 : if (_status) nr_stun_message_destroy(&req);
158 0 : return _status;
159 : }
160 :
161 : int
162 0 : nr_stun_build_req_no_auth(nr_stun_client_stun_binding_request_params *params, nr_stun_message **msg)
163 : {
164 : int r,_status;
165 0 : nr_stun_message *req = 0;
166 :
167 0 : if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUN_NO_AUTH, NR_STUN_MSG_BINDING_REQUEST, &req)))
168 0 : ABORT(r);
169 :
170 0 : *msg = req;
171 :
172 0 : _status=0;
173 : abort:
174 0 : if (_status) nr_stun_message_destroy(&req);
175 0 : return _status;
176 : }
177 :
178 : int
179 0 : nr_stun_build_keepalive(nr_stun_client_stun_keepalive_params *params, nr_stun_message **msg)
180 : {
181 : int r,_status;
182 0 : nr_stun_message *ind = 0;
183 :
184 0 : if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUN, NR_STUN_MSG_BINDING_INDICATION, &ind)))
185 0 : ABORT(r);
186 :
187 0 : *msg = ind;
188 :
189 0 : _status=0;
190 : abort:
191 0 : if (_status) nr_stun_message_destroy(&ind);
192 0 : return _status;
193 : }
194 :
195 : #ifdef USE_STUND_0_96
196 : int
197 0 : nr_stun_build_req_stund_0_96(nr_stun_client_stun_binding_request_stund_0_96_params *params, nr_stun_message **msg)
198 : {
199 : int r,_status;
200 0 : nr_stun_message *req = 0;
201 :
202 0 : if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUND_0_96, NR_STUN_MSG_BINDING_REQUEST, &req)))
203 0 : ABORT(r);
204 :
205 0 : if ((r=nr_stun_message_add_change_request_attribute(req, 0)))
206 0 : ABORT(r);
207 :
208 0 : assert(! nr_stun_message_has_attribute(req, NR_STUN_ATTR_USERNAME, 0));
209 0 : assert(! nr_stun_message_has_attribute(req, NR_STUN_ATTR_MESSAGE_INTEGRITY, 0));
210 :
211 0 : *msg = req;
212 :
213 0 : _status=0;
214 : abort:
215 0 : if (_status) nr_stun_message_destroy(&req);
216 0 : return _status;
217 : }
218 : #endif /* USE_STUND_0_96 */
219 :
220 : #ifdef USE_ICE
221 : int
222 0 : nr_stun_build_use_candidate(nr_stun_client_ice_binding_request_params *params, nr_stun_message **msg)
223 : {
224 : int r,_status;
225 0 : nr_stun_message *req = 0;
226 :
227 0 : if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUN, NR_STUN_MSG_BINDING_REQUEST, &req)))
228 0 : ABORT(r);
229 :
230 0 : if ((r=nr_stun_message_add_username_attribute(req, params->username)))
231 0 : ABORT(r);
232 :
233 0 : if ((r=nr_stun_message_add_message_integrity_attribute(req, ¶ms->password)))
234 0 : ABORT(r);
235 :
236 0 : if ((r=nr_stun_message_add_use_candidate_attribute(req)))
237 0 : ABORT(r);
238 :
239 0 : if ((r=nr_stun_message_add_priority_attribute(req, params->priority)))
240 0 : ABORT(r);
241 :
242 0 : if ((r=nr_stun_message_add_ice_controlling_attribute(req, params->tiebreaker)))
243 0 : ABORT(r);
244 :
245 0 : *msg = req;
246 :
247 0 : _status=0;
248 : abort:
249 0 : if (_status) nr_stun_message_destroy(&req);
250 0 : return _status;
251 : }
252 :
253 : int
254 0 : nr_stun_build_req_ice(nr_stun_client_ice_binding_request_params *params, nr_stun_message **msg)
255 : {
256 : int r,_status;
257 0 : nr_stun_message *req = 0;
258 :
259 0 : if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUN, NR_STUN_MSG_BINDING_REQUEST, &req)))
260 0 : ABORT(r);
261 :
262 0 : if ((r=nr_stun_message_add_username_attribute(req, params->username)))
263 0 : ABORT(r);
264 :
265 0 : if ((r=nr_stun_message_add_message_integrity_attribute(req, ¶ms->password)))
266 0 : ABORT(r);
267 :
268 0 : if ((r=nr_stun_message_add_priority_attribute(req, params->priority)))
269 0 : ABORT(r);
270 :
271 0 : switch (params->control) {
272 : case NR_ICE_CONTROLLING:
273 0 : if ((r=nr_stun_message_add_ice_controlling_attribute(req, params->tiebreaker)))
274 0 : ABORT(r);
275 0 : break;
276 : case NR_ICE_CONTROLLED:
277 0 : if ((r=nr_stun_message_add_ice_controlled_attribute(req, params->tiebreaker)))
278 0 : ABORT(r);
279 0 : break;
280 : default:
281 0 : assert(0);
282 : ABORT(R_INTERNAL);
283 : }
284 :
285 0 : *msg = req;
286 :
287 0 : _status=0;
288 : abort:
289 0 : if (_status) nr_stun_message_destroy(&req);
290 0 : return _status;
291 : }
292 : #endif /* USE_ICE */
293 :
294 : #ifdef USE_TURN
295 :
296 : #ifndef __isascii
297 : #define __isascii(c) (((c) & ~0x7F) == 0)
298 : #endif
299 :
300 : /* Long-term passwords are computed over the key:
301 :
302 : key = MD5(username ":" realm ":" SASLprep(password))
303 :
304 : Per RFC 5389 S 15.4
305 : */
306 : int
307 0 : nr_stun_compute_lt_message_integrity_password(const char *username, const char *realm,
308 : Data *password, Data *hmac_key)
309 : {
310 : char digest_input[1000];
311 : int i;
312 : int r, _status;
313 : size_t len;
314 :
315 : /* First check that the password is ASCII. We are supposed to
316 : SASLprep but we don't support this yet
317 : TODO(ekr@rtfm.com): Add SASLprep for password.
318 : */
319 0 : for (i=0; i<password->len; i++) {
320 0 : if (!__isascii(password->data[i]))
321 0 : ABORT(R_BAD_DATA);
322 : }
323 :
324 0 : if (hmac_key->len < 16)
325 0 : ABORT(R_BAD_ARGS);
326 :
327 0 : snprintf(digest_input, sizeof(digest_input), "%s:%s:", username, realm);
328 0 : if ((sizeof(digest_input) - strlen(digest_input)) < password->len)
329 0 : ABORT(R_BAD_DATA);
330 :
331 0 : len = strlen(digest_input);
332 0 : memcpy(digest_input + len, password->data, password->len);
333 :
334 :
335 0 : if (r=nr_crypto_md5((UCHAR *)digest_input, len + password->len, hmac_key->data))
336 0 : ABORT(r);
337 0 : hmac_key->len=16;
338 :
339 0 : _status=0;
340 : abort:
341 0 : return(_status);
342 : }
343 :
344 : static int
345 0 : nr_stun_build_auth_params(nr_stun_client_auth_params *auth, nr_stun_message *req)
346 : {
347 : int r, _status;
348 : UCHAR hmac_key_d[16];
349 : Data hmac_key;
350 :
351 0 : ATTACH_DATA(hmac_key, hmac_key_d);
352 :
353 0 : if (!auth->authenticate)
354 0 : goto done;
355 :
356 0 : assert(auth->username);
357 0 : assert(auth->password.len);
358 0 : assert(auth->realm);
359 0 : assert(auth->nonce);
360 :
361 0 : if (r=nr_stun_compute_lt_message_integrity_password(auth->username,
362 0 : auth->realm,
363 : &auth->password,
364 : &hmac_key))
365 0 : ABORT(r);
366 :
367 0 : if (!auth->username) {
368 0 : r_log(NR_LOG_STUN, LOG_WARNING, "STUN authentication requested but no username provided");
369 0 : ABORT(R_INTERNAL);
370 : }
371 :
372 0 : if (!auth->password.len) {
373 0 : r_log(NR_LOG_STUN, LOG_WARNING, "STUN authentication requested but no password provided");
374 0 : ABORT(R_INTERNAL);
375 : }
376 :
377 0 : if (!auth->realm) {
378 0 : r_log(NR_LOG_STUN, LOG_WARNING, "STUN authentication requested but no realm provided");
379 0 : ABORT(R_INTERNAL);
380 : }
381 :
382 0 : if (!auth->nonce) {
383 0 : r_log(NR_LOG_STUN, LOG_WARNING, "STUN authentication requested but no nonce provided");
384 0 : ABORT(R_INTERNAL);
385 : }
386 :
387 0 : if ((r=nr_stun_message_add_username_attribute(req, auth->username)))
388 0 : ABORT(r);
389 :
390 0 : if ((r=nr_stun_message_add_realm_attribute(req, auth->realm)))
391 0 : ABORT(r);
392 :
393 0 : if ((r=nr_stun_message_add_nonce_attribute(req, auth->nonce)))
394 0 : ABORT(r);
395 :
396 0 : if ((r=nr_stun_message_add_message_integrity_attribute(req, &hmac_key)))
397 0 : ABORT(r);
398 :
399 : done:
400 0 : _status=0;
401 : abort:
402 0 : return(_status);
403 : }
404 :
405 : int
406 0 : nr_stun_build_allocate_request(nr_stun_client_auth_params *auth, nr_stun_client_allocate_request_params *params, nr_stun_message **msg)
407 : {
408 : int r,_status;
409 0 : nr_stun_message *req = 0;
410 :
411 0 : if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUN, NR_STUN_MSG_ALLOCATE_REQUEST, &req)))
412 0 : ABORT(r);
413 :
414 0 : if ((r=nr_stun_message_add_requested_transport_attribute(req, NR_STUN_ATTR_REQUESTED_TRANSPORT_UDP)))
415 0 : ABORT(r);
416 :
417 0 : if ((r=nr_stun_message_add_lifetime_attribute(req, params->lifetime_secs)))
418 0 : ABORT(r);
419 :
420 : /* TODO(ekr@rtfm.com): Add the SOFTWARE attribute (Firefox bug 857666) */
421 :
422 0 : if ((r=nr_stun_build_auth_params(auth, req)))
423 0 : ABORT(r);
424 :
425 0 : *msg = req;
426 :
427 0 : _status=0;
428 : abort:
429 0 : if (_status) nr_stun_message_destroy(&req);
430 0 : return _status;
431 : }
432 :
433 :
434 0 : int nr_stun_build_refresh_request(nr_stun_client_auth_params *auth, nr_stun_client_refresh_request_params *params, nr_stun_message **msg)
435 : {
436 : int r,_status;
437 0 : nr_stun_message *req = 0;
438 :
439 0 : if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUN, NR_STUN_MSG_REFRESH_REQUEST, &req)))
440 0 : ABORT(r);
441 :
442 0 : if ((r=nr_stun_message_add_lifetime_attribute(req, params->lifetime_secs)))
443 0 : ABORT(r);
444 :
445 :
446 : /* TODO(ekr@rtfm.com): Add the SOFTWARE attribute (Firefox bug 857666) */
447 :
448 0 : if ((r=nr_stun_build_auth_params(auth, req)))
449 0 : ABORT(r);
450 :
451 0 : *msg = req;
452 :
453 0 : _status=0;
454 : abort:
455 0 : if (_status) nr_stun_message_destroy(&req);
456 0 : return _status;
457 : }
458 :
459 :
460 0 : int nr_stun_build_permission_request(nr_stun_client_auth_params *auth, nr_stun_client_permission_request_params *params, nr_stun_message **msg)
461 : {
462 : int r,_status;
463 0 : nr_stun_message *req = 0;
464 :
465 0 : if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUN, NR_STUN_MSG_PERMISSION_REQUEST, &req)))
466 0 : ABORT(r);
467 :
468 0 : if ((r=nr_stun_message_add_xor_peer_address_attribute(req, ¶ms->remote_addr)))
469 0 : ABORT(r);
470 :
471 0 : if ((r=nr_stun_build_auth_params(auth, req)))
472 0 : ABORT(r);
473 :
474 0 : *msg = req;
475 :
476 0 : _status=0;
477 : abort:
478 0 : if (_status) nr_stun_message_destroy(&req);
479 0 : return _status;
480 : }
481 :
482 : int
483 0 : nr_stun_build_send_indication(nr_stun_client_send_indication_params *params, nr_stun_message **msg)
484 : {
485 : int r,_status;
486 0 : nr_stun_message *ind = 0;
487 :
488 0 : if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUN, NR_STUN_MSG_SEND_INDICATION, &ind)))
489 0 : ABORT(r);
490 :
491 0 : if ((r=nr_stun_message_add_xor_peer_address_attribute(ind, ¶ms->remote_addr)))
492 0 : ABORT(r);
493 :
494 0 : if ((r=nr_stun_message_add_data_attribute(ind, params->data.data, params->data.len)))
495 0 : ABORT(r);
496 :
497 0 : *msg = ind;
498 :
499 0 : _status=0;
500 : abort:
501 0 : if (_status) nr_stun_message_destroy(&ind);
502 0 : return _status;
503 : }
504 :
505 : int
506 0 : nr_stun_build_data_indication(nr_stun_client_data_indication_params *params, nr_stun_message **msg)
507 : {
508 : int r,_status;
509 0 : nr_stun_message *ind = 0;
510 :
511 0 : if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUN, NR_STUN_MSG_DATA_INDICATION, &ind)))
512 0 : ABORT(r);
513 :
514 0 : if ((r=nr_stun_message_add_xor_peer_address_attribute(ind, ¶ms->remote_addr)))
515 0 : ABORT(r);
516 :
517 0 : if ((r=nr_stun_message_add_data_attribute(ind, params->data.data, params->data.len)))
518 0 : ABORT(r);
519 :
520 0 : *msg = ind;
521 :
522 0 : _status=0;
523 : abort:
524 0 : if (_status) nr_stun_message_destroy(&ind);
525 0 : return _status;
526 : }
527 :
528 : #endif /* USE_TURN */
529 :
530 : /* draft-ietf-behave-rfc3489bis-10.txt S 7.3.1.1 */
531 : int
532 0 : nr_stun_form_success_response(nr_stun_message *req, nr_transport_addr *from, Data *password, nr_stun_message *res)
533 : {
534 : int r,_status;
535 : int request_method;
536 : char server_name[NR_STUN_MAX_SERVER_BYTES+1]; /* +1 for \0 */
537 :
538 : /* set up information for default response */
539 :
540 0 : request_method = NR_STUN_GET_TYPE_METHOD(req->header.type);
541 0 : res->header.type = NR_STUN_TYPE(request_method, NR_CLASS_RESPONSE);
542 0 : res->header.magic_cookie = req->header.magic_cookie;
543 0 : memcpy(&res->header.id, &req->header.id, sizeof(res->header.id));
544 :
545 0 : r_log(NR_LOG_STUN, LOG_DEBUG, "Mapped Address = %s", from->as_string);
546 :
547 0 : if ((r=nr_stun_message_add_xor_mapped_address_attribute(res, from)))
548 0 : ABORT(r);
549 :
550 0 : if (!NR_reg_get_string(NR_STUN_REG_PREF_SERVER_NAME, server_name, sizeof(server_name))) {
551 0 : if ((r=nr_stun_message_add_server_attribute(res, server_name)))
552 0 : ABORT(r);
553 : }
554 :
555 0 : if (res->header.magic_cookie == NR_STUN_MAGIC_COOKIE) {
556 0 : if (password != 0) {
557 0 : if ((r=nr_stun_message_add_message_integrity_attribute(res, password)))
558 0 : ABORT(r);
559 : }
560 :
561 0 : if ((r=nr_stun_message_add_fingerprint_attribute(res)))
562 0 : ABORT(r);
563 : }
564 :
565 0 : _status=0;
566 : abort:
567 0 : return _status;
568 : }
569 :
570 : /* draft-ietf-behave-rfc3489bis-10.txt S 7.3.1.1 */
571 : void
572 0 : nr_stun_form_error_response(nr_stun_message *req, nr_stun_message* res, int number, char* msg)
573 : {
574 : char *str;
575 : int request_method;
576 : char server_name[NR_STUN_MAX_SERVER_BYTES+1]; /* +1 for \0 */
577 :
578 0 : if (number < 300 || number > 699)
579 0 : number = 500;
580 :
581 0 : r_log(NR_LOG_STUN, LOG_INFO, "Responding with error %d: %s", number, msg);
582 :
583 0 : request_method = NR_STUN_GET_TYPE_METHOD(req->header.type);
584 0 : res->header.type = NR_STUN_TYPE(request_method, NR_CLASS_ERROR_RESPONSE);
585 0 : res->header.magic_cookie = req->header.magic_cookie;
586 0 : memcpy(&res->header.id, &req->header.id, sizeof(res->header.id));
587 :
588 : /* during development we should never see 500s (hopefully not in deployment either) */
589 :
590 0 : str = 0;
591 0 : switch (number) {
592 0 : case 300: str = "Try Alternate"; break;
593 0 : case 400: str = "Bad Request"; break;
594 0 : case 401: str = "Unauthorized"; break;
595 0 : case 420: str = "Unknown Attribute"; break;
596 0 : case 438: str = "Stale Nonce"; break;
597 : #ifdef USE_ICE
598 0 : case 487: str = "Role Conflict"; break;
599 : #endif
600 0 : case 500: str = "Server Error"; break;
601 : }
602 0 : if (str == 0) {
603 0 : str = "Unknown";
604 : }
605 :
606 0 : if (nr_stun_message_add_error_code_attribute(res, number, str)) {
607 0 : assert(0); /* should never happen */
608 : }
609 :
610 0 : if (!NR_reg_get_string(NR_STUN_REG_PREF_SERVER_NAME, server_name, sizeof(server_name))) {
611 0 : nr_stun_message_add_server_attribute(res, server_name);
612 : }
613 0 : }
614 :
|