diff options
author | Bruno Cabral <bcabral@uw.edu> | 2015-06-15 05:46:13 +0000 |
---|---|---|
committer | Bruno Cabral <bcabral@uw.edu> | 2015-06-15 05:46:13 +0000 |
commit | 1ed484dfdf1676d92e95b9ed262abc28ca7b3aee (patch) | |
tree | cc76406ab7f0a3484cd9aa66fca168d864aa246d | |
parent | fa7754fd510260ffb8850feb5d6559e55f75d4e9 (diff) | |
download | gnunet-1ed484dfdf1676d92e95b9ed262abc28ca7b3aee.tar.gz gnunet-1ed484dfdf1676d92e95b9ed262abc28ca7b3aee.zip |
Initial import of STUN support
-rw-r--r-- | src/nat/Makefile.am | 11 | ||||
-rw-r--r-- | src/nat/nat.c | 5 | ||||
-rw-r--r-- | src/nat/test_stun.c | 514 | ||||
-rw-r--r-- | src/nat/test_stun.h | 108 |
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 | ||
68 | libgnunetnat_la_LIBADD = \ | 69 | libgnunetnat_la_LIBADD = \ |
69 | $(top_builddir)/src/util/libgnunetutil.la \ | 70 | $(top_builddir)/src/util/libgnunetutil.la \ |
@@ -76,7 +77,8 @@ libgnunetnat_la_LDFLAGS = \ | |||
76 | check_PROGRAMS = \ | 77 | check_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 | ||
81 | if ENABLE_TEST_RUN | 83 | if 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 | ||
107 | test_stun_SOURCES = \ | ||
108 | test_stun.c | ||
109 | test_stun_LDADD = \ | ||
110 | libgnunetnat.la \ | ||
111 | $(top_builddir)/src/util/libgnunetutil.la | ||
105 | 112 | ||
106 | EXTRA_DIST = \ | 113 | EXTRA_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 | */ | ||
45 | static unsigned long port = 7895; | ||
46 | |||
47 | static int ret = 1; | ||
48 | |||
49 | /** | ||
50 | * The listen socket of the service for IPv4 | ||
51 | */ | ||
52 | static struct GNUNET_NETWORK_Handle *lsock4; | ||
53 | |||
54 | |||
55 | /** | ||
56 | * The listen task ID for IPv4 | ||
57 | */ | ||
58 | static struct GNUNET_SCHEDULER_Task * ltask4; | ||
59 | |||
60 | |||
61 | static char *stun_server = STUN_SERVER; | ||
62 | static int stun_port = STUN_PORT; | ||
63 | |||
64 | static int stun_debug = 1; | ||
65 | |||
66 | |||
67 | struct stun_strings { | ||
68 | const int value; | ||
69 | const char *name; | ||
70 | }; | ||
71 | |||
72 | |||
73 | static inline int stun_msg2class(int msg) | ||
74 | { | ||
75 | return ((msg & 0x0010) >> 4) | ((msg & 0x0100) >> 7); | ||
76 | } | ||
77 | |||
78 | static inline int stun_msg2method(int msg) | ||
79 | { | ||
80 | return (msg & 0x000f) | ((msg & 0x00e0) >> 1) | ((msg & 0x3e00) >> 2); | ||
81 | } | ||
82 | |||
83 | static 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 */ | ||
90 | static 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 */ | ||
126 | static 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 */ | ||
160 | struct stun_state { | ||
161 | unsigned short attr; | ||
162 | }; | ||
163 | |||
164 | static 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 */ | ||
183 | static 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 */ | ||
201 | static 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. */ | ||
211 | typedef 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 | */ | ||
221 | static 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 | */ | ||
289 | static 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 | */ | ||
328 | int 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 | |||
373 | static 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 | */ | ||
386 | static void | ||
387 | do_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 | */ | ||
421 | static 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 | |||
458 | static void | ||
459 | run (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 | |||
494 | int | ||
495 | main (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 | |||
40 | typedef struct { unsigned int id[3]; } __attribute__((packed)) stun_trans_id; | ||
41 | |||
42 | struct 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 | |||
50 | struct 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 | */ | ||
59 | struct 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 | ||