aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBruno Cabral <bcabral@uw.edu>2015-06-15 05:46:13 +0000
committerBruno Cabral <bcabral@uw.edu>2015-06-15 05:46:13 +0000
commit1ed484dfdf1676d92e95b9ed262abc28ca7b3aee (patch)
treecc76406ab7f0a3484cd9aa66fca168d864aa246d /src
parentfa7754fd510260ffb8850feb5d6559e55f75d4e9 (diff)
downloadgnunet-1ed484dfdf1676d92e95b9ed262abc28ca7b3aee.tar.gz
gnunet-1ed484dfdf1676d92e95b9ed262abc28ca7b3aee.zip
Initial import of STUN support
Diffstat (limited to 'src')
-rw-r--r--src/nat/Makefile.am11
-rw-r--r--src/nat/nat.c5
-rw-r--r--src/nat/test_stun.c514
-rw-r--r--src/nat/test_stun.h108
4 files changed, 636 insertions, 2 deletions
diff --git a/src/nat/Makefile.am b/src/nat/Makefile.am
index 72ac0a1f0..063b8e3ab 100644
--- a/src/nat/Makefile.am
+++ b/src/nat/Makefile.am
@@ -63,7 +63,8 @@ libgnunetnat_la_SOURCES = \
63 nat.c nat.h \ 63 nat.c nat.h \
64 nat_auto.c \ 64 nat_auto.c \
65 nat_test.c \ 65 nat_test.c \
66 nat_mini.c 66 nat_mini.c \
67 nat_stun.c
67 68
68libgnunetnat_la_LIBADD = \ 69libgnunetnat_la_LIBADD = \
69 $(top_builddir)/src/util/libgnunetutil.la \ 70 $(top_builddir)/src/util/libgnunetutil.la \
@@ -76,7 +77,8 @@ libgnunetnat_la_LDFLAGS = \
76check_PROGRAMS = \ 77check_PROGRAMS = \
77 test_nat \ 78 test_nat \
78 test_nat_mini \ 79 test_nat_mini \
79 test_nat_test 80 test_nat_test \
81 test_stun
80 82
81if ENABLE_TEST_RUN 83if ENABLE_TEST_RUN
82 AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; 84 AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;
@@ -102,6 +104,11 @@ test_nat_test_LDADD = \
102 libgnunetnat.la \ 104 libgnunetnat.la \
103 $(top_builddir)/src/util/libgnunetutil.la 105 $(top_builddir)/src/util/libgnunetutil.la
104 106
107test_stun_SOURCES = \
108 test_stun.c
109test_stun_LDADD = \
110 libgnunetnat.la \
111 $(top_builddir)/src/util/libgnunetutil.la
105 112
106EXTRA_DIST = \ 113EXTRA_DIST = \
107 test_nat_data.conf \ 114 test_nat_data.conf \
diff --git a/src/nat/nat.c b/src/nat/nat.c
index 85b55138d..907728fb4 100644
--- a/src/nat/nat.c
+++ b/src/nat/nat.c
@@ -69,6 +69,11 @@ enum LocalAddressSource
69 * given in the configuration (i.e. hole-punched DynDNS setup). 69 * given in the configuration (i.e. hole-punched DynDNS setup).
70 */ 70 */
71 LAL_EXTERNAL_IP, 71 LAL_EXTERNAL_IP,
72
73 /**
74 * Address was obtained by an external STUN server
75 */
76 LAL_EXTERNAL_STUN_IP,
72 77
73 /** 78 /**
74 * Address was obtained by DNS resolution of the external hostname 79 * Address was obtained by DNS resolution of the external hostname
diff --git a/src/nat/test_stun.c b/src/nat/test_stun.c
new file mode 100644
index 000000000..adb485e99
--- /dev/null
+++ b/src/nat/test_stun.c
@@ -0,0 +1,514 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009, 2015 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * Testcase for STUN server resolution
23 *
24 * @file nat/test_stun.c
25 * @brief Testcase for STUN library
26 * @author Bruno Souza Cabral
27 * @autor Mark Spencer (Original code borrowed from Asterisk)
28 *
29 */
30
31
32#include "platform.h"
33#include "gnunet_util_lib.h"
34#include "gnunet_program_lib.h"
35#include "gnunet_scheduler_lib.h"
36#include "gnunet_nat_lib.h"
37
38
39#include "test_stun.h"
40
41
42/**
43 * The port the test service is running on (default 7895)
44 */
45static unsigned long port = 7895;
46
47static int ret = 1;
48
49/**
50 * The listen socket of the service for IPv4
51 */
52static struct GNUNET_NETWORK_Handle *lsock4;
53
54
55/**
56 * The listen task ID for IPv4
57 */
58static struct GNUNET_SCHEDULER_Task * ltask4;
59
60
61static char *stun_server = STUN_SERVER;
62static int stun_port = STUN_PORT;
63
64static int stun_debug = 1;
65
66
67struct stun_strings {
68 const int value;
69 const char *name;
70};
71
72
73static inline int stun_msg2class(int msg)
74{
75 return ((msg & 0x0010) >> 4) | ((msg & 0x0100) >> 7);
76}
77
78static inline int stun_msg2method(int msg)
79{
80 return (msg & 0x000f) | ((msg & 0x00e0) >> 1) | ((msg & 0x3e00) >> 2);
81}
82
83static inline int stun_msg2type(int class, int method)
84{
85 return ((class & 1) << 4) | ((class & 2) << 7) |
86 (method & 0x000f) | ((method & 0x0070) << 1) | ((method & 0x0f800) << 2);
87}
88
89/* helper function to print message names */
90static const char *stun_msg2str(int msg)
91{
92 static const struct stun_strings classes[] = {
93 { STUN_REQUEST, "Request" },
94 { STUN_INDICATION, "Indication" },
95 { STUN_RESPONSE, "Response" },
96 { STUN_ERROR_RESPONSE, "Error Response" },
97 { 0, NULL }
98};
99 static const struct stun_strings methods[] = {
100 { STUN_BINDING, "Binding" },
101 { 0, NULL }
102};
103 static char result[32];
104 const char *class = NULL, *method = NULL;
105 int i, value;
106
107 value = stun_msg2class(msg);
108 for (i = 0; classes[i].name; i++) {
109 class = classes[i].name;
110 if (classes[i].value == value)
111 break;
112 }
113 value = stun_msg2method(msg);
114 for (i = 0; methods[i].name; i++) {
115 method = methods[i].name;
116 if (methods[i].value == value)
117 break;
118 }
119 snprintf(result, sizeof(result), "%s %s",
120 method ? : "Unknown Method",
121 class ? : "Unknown Class Message");
122 return result;
123}
124
125/* helper function to print attribute names */
126static const char *stun_attr2str(int msg)
127{
128 static const struct stun_strings attrs[] = {
129 { STUN_MAPPED_ADDRESS, "Mapped Address" },
130 { STUN_RESPONSE_ADDRESS, "Response Address" },
131 { STUN_CHANGE_ADDRESS, "Change Address" },
132 { STUN_SOURCE_ADDRESS, "Source Address" },
133 { STUN_CHANGED_ADDRESS, "Changed Address" },
134 { STUN_USERNAME, "Username" },
135 { STUN_PASSWORD, "Password" },
136 { STUN_MESSAGE_INTEGRITY, "Message Integrity" },
137 { STUN_ERROR_CODE, "Error Code" },
138 { STUN_UNKNOWN_ATTRIBUTES, "Unknown Attributes" },
139 { STUN_REFLECTED_FROM, "Reflected From" },
140 { STUN_REALM, "Realm" },
141 { STUN_NONCE, "Nonce" },
142 { STUN_XOR_MAPPED_ADDRESS, "XOR Mapped Address" },
143 { STUN_MS_VERSION, "MS Version" },
144 { STUN_MS_XOR_MAPPED_ADDRESS, "MS XOR Mapped Address" },
145 { STUN_SOFTWARE, "Software" },
146 { STUN_ALTERNATE_SERVER, "Alternate Server" },
147 { STUN_FINGERPRINT, "Fingerprint" },
148 { 0, NULL }
149};
150 int i;
151
152 for (i = 0; attrs[i].name; i++) {
153 if (attrs[i].value == msg)
154 return attrs[i].name;
155 }
156 return "Unknown Attribute";
157}
158
159/* here we store credentials extracted from a message */
160struct stun_state {
161 unsigned short attr;
162};
163
164static int stun_process_attr(struct stun_state *state, struct stun_attr *attr)
165{
166 if (stun_debug)
167 fprintf(stderr, "Found STUN Attribute %s (%04x), length %d\n",
168 stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr), ntohs(attr->len));
169 switch (ntohs(attr->attr)) {
170 case STUN_MAPPED_ADDRESS:
171 case STUN_XOR_MAPPED_ADDRESS:
172 case STUN_MS_XOR_MAPPED_ADDRESS:
173 break;
174 default:
175 if (stun_debug)
176 fprintf(stderr, "Ignoring STUN Attribute %s (%04x), length %d\n",
177 stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr), ntohs(attr->len));
178 }
179 return 0;
180}
181
182/* append a string to an STUN message */
183static void append_attr_string(struct stun_attr **attr, int attrval, const char *s, int *len, int *left)
184{
185 int str_length = strlen(s);
186 int attr_length = str_length + ((~(str_length - 1)) & 0x3);
187 int size = sizeof(**attr) + attr_length;
188 if (*left > size) {
189 (*attr)->attr = htons(attrval);
190 (*attr)->len = htons(attr_length);
191 memcpy((*attr)->value, s, str_length);
192 memset((*attr)->value + str_length, 0, attr_length - str_length);
193 (*attr) = (struct stun_attr *)((*attr)->value + attr_length);
194 *len += size;
195 *left -= size;
196 }
197}
198
199
200/* helper function to generate a random request id */
201static void stun_req_id(struct stun_header *req)
202{
203 int x;
204 srand(time(0));
205 req->magic = htonl(STUN_MAGIC_COOKIE);
206 for (x = 0; x < 3; x++)
207 req->id.id[x] = rand();
208}
209
210/* callback type to be invoked on stun responses. */
211typedef int (stun_cb_f)(struct stun_state *st, struct stun_attr *attr, void *arg, unsigned int magic);
212
213/* handle an incoming STUN message.
214 *
215 * Do some basic sanity checks on packet size and content,
216 * try to extract a bit of information, and possibly reply.
217 * At the moment this only processes BIND requests, and returns
218 * the externally visible address of the request.
219 * If a callback is specified, invoke it with the attribute.
220 */
221static int stun_handle_packet(unsigned char *data, size_t len, stun_cb_f *stun_cb, void *arg)
222{
223 struct stun_header *hdr = (struct stun_header *)data;
224 struct stun_attr *attr;
225 struct stun_state st;
226 int ret = STUN_IGNORE;
227 int x;
228
229 /* On entry, 'len' is the length of the udp payload. After the
230 * initial checks it becomes the size of unprocessed options,
231 * while 'data' is advanced accordingly.
232 */
233 if (len < sizeof(struct stun_header)) {
234 fprintf(stderr, "Runt STUN packet (only %d, wanting at least %d)\n", (int) len, (int) sizeof(struct stun_header));
235 return -1;
236 }
237 len -= sizeof(struct stun_header);
238 data += sizeof(struct stun_header);
239 x = ntohs(hdr->msglen); /* len as advertised in the message */
240 if (stun_debug)
241 fprintf(stderr, "STUN Packet, msg %s (%04x), length: %d\n", stun_msg2str(ntohs(hdr->msgtype)), ntohs(hdr->msgtype), x);
242 if (x > len) {
243 fprintf(stderr, "Scrambled STUN packet length (got %d, expecting %d)\n", x, (int)len);
244 } else
245 len = x;
246 memset(&st,0, sizeof(st));
247
248 while (len) {
249 if (len < sizeof(struct stun_attr)) {
250 fprintf(stderr, "Runt Attribute (got %d, expecting %d)\n", (int)len, (int) sizeof(struct stun_attr));
251 break;
252 }
253 attr = (struct stun_attr *)data;
254
255 /* compute total attribute length */
256 x = ntohs(attr->len) + sizeof(struct stun_attr);
257 if (x > len) {
258 fprintf(stderr, "Inconsistent Attribute (length %d exceeds remaining msg len %d)\n", x, (int)len);
259 break;
260 }
261 if (stun_cb)
262 stun_cb(&st, attr, arg, hdr->magic);
263 if (stun_process_attr(&st, attr)) {
264 fprintf(stderr, "Failed to handle attribute %s (%04x)\n", stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr));
265 break;
266 }
267 /* Clear attribute id: in case previous entry was a string,
268 * this will act as the terminator for the string.
269 */
270 attr->attr = 0;
271 data += x;
272 len -= x;
273 }
274 /* Null terminate any string.
275 * XXX NOTE, we write past the size of the buffer passed by the
276 * caller, so this is potentially dangerous. The only thing that
277 * saves us is that usually we read the incoming message in a
278 * much larger buffer
279 */
280 *data = '\0';
281
282 return ret;
283}
284
285/* Extract the STUN_MAPPED_ADDRESS from the stun response.
286 * This is used as a callback for stun_handle_response
287 * when called from stun_request.
288 */
289static int stun_get_mapped(struct stun_state *st, struct stun_attr *attr, void *arg, unsigned int magic)
290{
291 struct stun_addr *returned_addr = (struct stun_addr *)(attr + 1);
292 struct sockaddr_in *sa = (struct sockaddr_in *)arg;
293 unsigned short type = ntohs(attr->attr);
294
295 switch (type) {
296 case STUN_MAPPED_ADDRESS:
297 if (st->attr == STUN_XOR_MAPPED_ADDRESS ||
298 st->attr == STUN_MS_XOR_MAPPED_ADDRESS)
299 return 1;
300 magic = 0;
301 break;
302 case STUN_MS_XOR_MAPPED_ADDRESS:
303 if (st->attr == STUN_XOR_MAPPED_ADDRESS)
304 return 1;
305 break;
306 case STUN_XOR_MAPPED_ADDRESS:
307 break;
308 default:
309 return 1;
310 }
311 if (ntohs(attr->len) < 8 && returned_addr->family != 1)
312 return 1;
313
314 st->attr = type;
315 sa->sin_port = returned_addr->port ^ htons(ntohl(magic) >> 16);
316 sa->sin_addr.s_addr = returned_addr->addr ^ magic;
317 return 0;
318}
319
320/* Generic STUN request
321 * Send a generic stun request to the server specified,
322 * possibly waiting for a reply and filling the 'reply' field with
323 * the externally visible address.
324
325 * \param s the socket used to send the request
326 * \return 0 on success, other values on error.
327 */
328int stun_request(struct GNUNET_NETWORK_Handle * sock)
329{
330 struct stun_header *req;
331 unsigned char reqdata[1024];
332 int reqlen, reqleft;
333 struct stun_attr *attr;
334
335
336
337
338 struct sockaddr_in server;
339 struct hostent *hostinfo = gethostbyname(stun_server);
340 if (!hostinfo) {
341 fprintf(stderr, "Error resolving host %s\n", stun_server);
342 return -1;
343 }
344 memset(&server,0, sizeof(server));
345 server.sin_family = AF_INET;
346 server.sin_addr = *(struct in_addr*) hostinfo->h_addr;
347 server.sin_port = htons(stun_port);
348
349
350
351 req = (struct stun_header *)reqdata;
352 stun_req_id(req);
353 reqlen = 0;
354 reqleft = sizeof(reqdata) - sizeof(struct stun_header);
355 req->msgtype = 0;
356 req->msglen = 0;
357 attr = (struct stun_attr *)req->ies;
358
359 append_attr_string(&attr, STUN_SOFTWARE, PACKAGE " v" VERSION_PACKAGE, &reqlen, &reqleft);
360 req->msglen = htons(reqlen);
361 req->msgtype = htons(stun_msg2type(STUN_REQUEST, STUN_BINDING));
362
363
364 if (-1 == GNUNET_NETWORK_socket_sendto (sock, req, ntohs(req->msglen) + sizeof(*req),
365 (const struct sockaddr *) &server, sizeof (server)))
366 {
367 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "sendto");
368 }
369
370 return -1;
371}
372
373static void print_answer(struct sockaddr_in* answer)
374{
375 printf("External IP is: %s , with port %d\n", inet_ntoa(answer->sin_addr), ntohs(answer->sin_port));
376}
377
378
379/**
380 * Activity on our incoming socket. Read data from the
381 * incoming connection.
382 *
383 * @param cls
384 * @param tc scheduler context
385 */
386static void
387do_udp_read (void *cls,
388 const struct GNUNET_SCHEDULER_TaskContext *tc)
389{
390 //struct GNUNET_NAT_Test *tst = cls;
391 unsigned char reply_buf[1024];
392 ssize_t rlen;
393 struct sockaddr_in answer;
394
395
396 if ((0 != (tc->reason & GNUNET_SCHEDULER_REASON_READ_READY)) &&
397 (GNUNET_NETWORK_fdset_isset (tc->read_ready,
398 lsock4)))
399 {
400 rlen = GNUNET_NETWORK_socket_recv (lsock4, reply_buf, sizeof (reply_buf));
401 printf("Recivied something of size %d", rlen);
402
403 //Lets handle the packet
404 memset(&answer, 0, sizeof(struct sockaddr_in));
405 stun_handle_packet(reply_buf, rlen, stun_get_mapped, &answer);
406 //Print the anser
407 //TODO: Delete the object
408 ret = 0;
409 print_answer(&answer);
410
411
412 }
413}
414
415
416/**
417 * Create an IPv4 listen socket bound to our port.
418 *
419 * @return NULL on error
420 */
421static struct GNUNET_NETWORK_Handle *
422 bind_v4 ()
423{
424 struct GNUNET_NETWORK_Handle *ls;
425 struct sockaddr_in sa4;
426 int eno;
427
428 memset (&sa4, 0, sizeof (sa4));
429 sa4.sin_family = AF_INET;
430 sa4.sin_port = htons (port);
431#if HAVE_SOCKADDR_IN_SIN_LEN
432 sa4.sin_len = sizeof (sa4);
433#endif
434 ls = GNUNET_NETWORK_socket_create (AF_INET,
435 SOCK_DGRAM,
436 0);
437 if (NULL == ls)
438 return NULL;
439 if (GNUNET_OK !=
440 GNUNET_NETWORK_socket_bind (ls, (const struct sockaddr *) &sa4,
441 sizeof (sa4)))
442 {
443 eno = errno;
444 GNUNET_NETWORK_socket_close (ls);
445 errno = eno;
446 return NULL;
447 }
448 return ls;
449}
450
451
452
453/**
454 * Main function run with scheduler.
455 */
456
457
458static void
459run (void *cls, char *const *args, const char *cfgfile,
460 const struct GNUNET_CONFIGURATION_Handle *cfg)
461{
462
463
464 //Lets create the socket
465 lsock4 = bind_v4 ();
466 if (NULL == lsock4)
467 {
468 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "bind");
469 }
470 else
471 {
472 printf("Binded, now will call add_read\n");
473 //Lets call our function now when it accepts
474 ltask4 = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
475 lsock4, &do_udp_read, NULL);
476
477 }
478 if(NULL == lsock4 )
479 {
480 GNUNET_SCHEDULER_shutdown ();
481 return;
482 }
483 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
484 "Service listens on port %u\n",
485 port);
486 printf("Start main event\n");
487 stun_request(lsock4);
488 //Main event
489 //main_task = GNUNET_SCHEDULER_add_delayed (timeout, &do_timeout, nh);
490
491}
492
493
494int
495main (int argc, char *const argv[])
496{
497 struct GNUNET_GETOPT_CommandLineOption options[] = {
498 GNUNET_GETOPT_OPTION_END
499 };
500
501 char *const argv_prog[] = {
502 "test-stun",
503 NULL
504 };
505 GNUNET_log_setup ("test-stun",
506 "WARNING",
507 NULL);
508
509 GNUNET_PROGRAM_run (1, argv_prog, "test-stun", "nohelp", options, &run, NULL);
510
511 return ret;
512}
513
514/* end of test_nat.c */
diff --git a/src/nat/test_stun.h b/src/nat/test_stun.h
new file mode 100644
index 000000000..0e049d3a2
--- /dev/null
+++ b/src/nat/test_stun.h
@@ -0,0 +1,108 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009, 2015 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * Testcase for STUN server resolution
23 *
24 * @file nat/test_stun.h
25 * @brief Testcase for STUN library
26 * @author Bruno Souza Cabral
27 * @autor Mark Spencer (Original code borrowed from Asterisk)
28 *
29 */
30
31#define PACKAGE "gnunet"
32#define VERSION_PACKAGE "0.4"
33
34#define STUN_SERVER "stun.services.mozilla.com"
35#define STUN_PORT 3478
36#define STUN_COUNT 3
37#define STUN_RTO 500 /* ms */
38#define STUN_MRC 3
39
40typedef struct { unsigned int id[3]; } __attribute__((packed)) stun_trans_id;
41
42struct stun_header {
43 unsigned short msgtype;
44 unsigned short msglen;
45 unsigned int magic;
46 stun_trans_id id;
47 unsigned char ies[0];
48} __attribute__((packed));
49
50struct stun_attr {
51 unsigned short attr;
52 unsigned short len;
53 unsigned char value[0];
54} __attribute__((packed));
55
56/*
57 * The format normally used for addresses carried by STUN messages.
58 */
59struct stun_addr {
60 unsigned char unused;
61 unsigned char family;
62 unsigned short port;
63 unsigned int addr;
64} __attribute__((packed));
65
66#define STUN_IGNORE (0)
67#define STUN_ACCEPT (1)
68
69#define STUN_MAGIC_COOKIE 0x2112A442
70
71/* STUN message classes */
72#define STUN_REQUEST 0x0000
73#define STUN_INDICATION 0x0001
74#define STUN_RESPONSE 0x0002
75#define STUN_ERROR_RESPONSE 0x0003
76
77/* STUN message methods */
78#define STUN_BINDING 0x0001
79#define STUN_SHARED_SECRET 0x0002
80#define STUN_ALLOCATE 0x0003
81#define STUN_REFRESH 0x0004
82#define STUN_SEND 0x0006
83#define STUN_DATA 0x0007
84#define STUN_CREATE_PERMISSION 0x0008
85#define STUN_CHANNEL_BIND 0x0009
86
87/* Basic attribute types in stun messages.
88 * Messages can also contain custom attributes (codes above 0x7fff)
89 */
90#define STUN_MAPPED_ADDRESS 0x0001
91#define STUN_RESPONSE_ADDRESS 0x0002
92#define STUN_CHANGE_ADDRESS 0x0003
93#define STUN_SOURCE_ADDRESS 0x0004
94#define STUN_CHANGED_ADDRESS 0x0005
95#define STUN_USERNAME 0x0006
96#define STUN_PASSWORD 0x0007
97#define STUN_MESSAGE_INTEGRITY 0x0008
98#define STUN_ERROR_CODE 0x0009
99#define STUN_UNKNOWN_ATTRIBUTES 0x000a
100#define STUN_REFLECTED_FROM 0x000b
101#define STUN_REALM 0x0014
102#define STUN_NONCE 0x0015
103#define STUN_XOR_MAPPED_ADDRESS 0x0020
104#define STUN_MS_VERSION 0x8008
105#define STUN_MS_XOR_MAPPED_ADDRESS 0x8020
106#define STUN_SOFTWARE 0x8022
107#define STUN_ALTERNATE_SERVER 0x8023
108#define STUN_FINGERPRINT 0x8028