diff options
Diffstat (limited to 'src/nat/test_stun.c')
-rw-r--r-- | src/nat/test_stun.c | 1028 |
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 | */ |
45 | static unsigned long port = 7895; | 45 | static unsigned long port = 7895; |
46 | 46 | ||
47 | static int ret = 1; | 47 | static 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 | */ |
52 | static struct GNUNET_NETWORK_Handle *lsock4; | 52 | static 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 | */ |
58 | static struct GNUNET_SCHEDULER_Task * ltask4; | 58 | static struct GNUNET_SCHEDULER_Task * ltask4; |
59 | 59 | ||
60 | 60 | ||
61 | static char *stun_server = STUN_SERVER; | 61 | static char *stun_server = STUN_SERVER; |
62 | static int stun_port = STUN_PORT; | 62 | static int stun_port = STUN_PORT; |
63 | 63 | ||
64 | static int stun_debug = 1; | 64 | static int stun_debug = 1; |
65 | 65 | ||
66 | 66 | ||
67 | struct stun_strings { | 67 | struct stun_strings { |
68 | const int value; | 68 | const int value; |
69 | const char *name; | 69 | const char *name; |
70 | }; | 70 | }; |
71 | 71 | ||
72 | 72 | ||
73 | static inline int stun_msg2class(int msg) | 73 | static 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 | ||
78 | static inline int stun_msg2method(int msg) | 78 | static 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 | ||
83 | static inline int stun_msg2type(int class, int method) | 83 | static 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 */ |
90 | static const char *stun_msg2str(int msg) | 90 | static 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 */ |
126 | static const char *stun_attr2str(int msg) | 126 | static 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 */ |
160 | struct stun_state { | 160 | struct stun_state { |
161 | unsigned short attr; | 161 | unsigned short attr; |
162 | }; | 162 | }; |
163 | 163 | ||
164 | static int stun_process_attr(struct stun_state *state, struct stun_attr *attr) | 164 | static 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 */ |
183 | static void append_attr_string(struct stun_attr **attr, int attrval, const char *s, int *len, int *left) | 183 | static 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 */ |
201 | static void stun_req_id(struct stun_header *req) | 201 | static 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. */ |
211 | typedef int (stun_cb_f)(struct stun_state *st, struct stun_attr *attr, void *arg, unsigned int magic); | 211 | typedef 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 | */ |
221 | static int stun_handle_packet(unsigned char *data, size_t len, stun_cb_f *stun_cb, void *arg) | 221 | static 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 | */ |
289 | static int stun_get_mapped(struct stun_state *st, struct stun_attr *attr, void *arg, unsigned int magic) | 289 | static 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 | */ |
328 | int stun_request(struct GNUNET_NETWORK_Handle * sock) | 328 | int 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 | ||
373 | static void print_answer(struct sockaddr_in* answer) | 373 | static 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 | */ |
386 | static void | 386 | static void |
387 | do_udp_read (void *cls, | 387 | do_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 | */ |
421 | static struct GNUNET_NETWORK_Handle * | 421 | static 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 | ||
458 | static void | 458 | static void |
459 | run (void *cls, char *const *args, const char *cfgfile, | 459 | run (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 | ||
494 | int | 494 | int |
495 | main (int argc, char *const argv[]) | 495 | main (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 */ |