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