2 * This file is part of the Nice GLib ICE library.
4 * (C) 2007 Nokia Corporation. All rights reserved.
5 * Contact: Rémi Denis-Courmont
7 * The contents of this file are subject to the Mozilla Public License Version
8 * 1.1 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 * for the specific language governing rights and limitations under the
17 * The Original Code is the Nice GLib ICE library.
19 * The Initial Developers of the Original Code are Collabora Ltd and Nokia
20 * Corporation. All Rights Reserved.
23 * Rémi Denis-Courmont, Nokia
25 * Alternatively, the contents of this file may be used under the terms of the
26 * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
27 * case the provisions of LGPL are applicable instead of those above. If you
28 * wish to allow use of your version of this file only under the terms of the
29 * LGPL and not to allow others to use your version of this file under the
30 * MPL, indicate your decision by deleting the provisions above and replace
31 * them with the notice and other provisions required by the LGPL. If you do
32 * not delete the provisions above, a recipient may use your version of this
33 * file under either the MPL or the LGPL.
40 #include <sys/types.h>
41 #include "stun/stunagent.h"
42 #include "stun/usages/bind.h"
52 #define MSG_DONTWAIT 0
55 #define close closesocket
57 #include <sys/types.h>
58 #include <sys/socket.h>
59 #include <arpa/inet.h>
64 #undef NDEBUG /* ensure assertions are built-in */
68 #define MSG_NOSIGNAL 0
71 static int listen_dgram (void)
73 struct addrinfo hints, *res;
74 const struct addrinfo *ptr;
77 memset (&hints, 0, sizeof (hints));
78 hints.ai_socktype = SOCK_DGRAM;
80 if (getaddrinfo (NULL, "0", &hints, &res))
83 for (ptr = res; ptr != NULL; ptr = ptr->ai_next)
85 int fd = socket (ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
89 if (bind (fd, ptr->ai_addr, ptr->ai_addrlen))
104 /** Incorrect socket family test */
105 static void bad_family (void)
107 struct sockaddr addr;
108 struct sockaddr_storage dummy;
110 socklen_t dummylen = sizeof(dummy);
112 memset (&addr, 0, sizeof (addr));
113 addr.sa_family = AF_UNSPEC;
115 addr.sa_len = sizeof (addr);
118 val = stun_usage_bind_run (&addr, sizeof (addr),
124 /** Too small socket address test */
125 static void small_srv_addr (void)
127 struct sockaddr addr;
128 struct sockaddr_storage dummy;
130 socklen_t dummylen = sizeof(dummy);
132 memset (&addr, 0, sizeof (addr));
133 addr.sa_family = AF_INET;
135 addr.sa_len = sizeof (addr);
138 val = stun_usage_bind_run (&addr, 1,
140 assert (val == STUN_USAGE_BIND_RETURN_ERROR);
144 /** Too big socket address test */
145 static void big_srv_addr (void)
147 uint8_t buf[sizeof (struct sockaddr_storage) + 16];
148 struct sockaddr_storage dummy;
150 socklen_t dummylen = sizeof(dummy);
153 memset (buf, 0, sizeof (buf));
154 val = stun_usage_bind_run ((struct sockaddr *)buf, sizeof (buf),
156 assert (val == STUN_USAGE_BIND_RETURN_ERROR);
162 static void timeout (void)
164 struct sockaddr_storage srv, dummy;
165 socklen_t srvlen = sizeof (srv);
166 socklen_t dummylen = sizeof(dummy);
169 /* Allocate a local UDP port, so we are 100% sure nobody responds there */
170 int servfd = listen_dgram ();
171 assert (servfd != -1);
173 val = getsockname (servfd, (struct sockaddr *)&srv, &srvlen);
176 val = stun_usage_bind_run ((struct sockaddr *)&srv, srvlen,
178 assert (val == STUN_USAGE_BIND_RETURN_TIMEOUT);
184 /** Malformed responses test */
185 static void bad_responses (void)
187 struct sockaddr_storage addr;
188 socklen_t addrlen = sizeof (addr);
190 uint8_t buf[STUN_MAX_MESSAGE_SIZE];
191 uint8_t req[STUN_MAX_MESSAGE_SIZE];
198 uint16_t known_attributes[] = {
199 STUN_ATTRIBUTE_MAPPED_ADDRESS,
200 STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS,
201 STUN_ATTRIBUTE_PRIORITY,
202 STUN_ATTRIBUTE_USERNAME,
203 STUN_ATTRIBUTE_MESSAGE_INTEGRITY,
204 STUN_ATTRIBUTE_ERROR_CODE, 0};
206 stun_agent_init (&agent, known_attributes,
207 STUN_COMPATIBILITY_RFC5389, 0);
209 /* Allocate a local UDP port */
210 servfd = listen_dgram ();
211 assert (servfd != -1);
213 val = getsockname (servfd, (struct sockaddr *)&addr, &addrlen);
216 fd = socket (addr.ss_family, SOCK_DGRAM, 0);
219 req_len = stun_usage_bind_create (&agent, &req_msg, req, sizeof(req));
220 assert (req_len > 0);
222 val = sendto (fd, req, req_len, MSG_DONTWAIT | MSG_NOSIGNAL,
223 (struct sockaddr *)&addr, addrlen);
226 /* Send to/receive from our client instance only */
227 val = getsockname (fd, (struct sockaddr *)&addr, &addrlen);
230 /* Send request instead of response */
231 val = getsockname (servfd, (struct sockaddr *)&addr, &addrlen);
233 len = recvfrom (servfd, buf, 1000, MSG_DONTWAIT, NULL, 0);
236 assert (stun_agent_validate (&agent, &msg, buf, len, NULL, NULL)
237 == STUN_VALIDATION_SUCCESS);
239 val = stun_usage_bind_process (&msg, (struct sockaddr *) &addr, &addrlen,
240 (struct sockaddr *) &addr, &addrlen);
241 assert (val == STUN_USAGE_BIND_RETURN_INVALID);
243 /* Send response with wrong request type */
247 /* Send error response without ERROR-CODE */
249 val = stun_usage_bind_process (&msg, (struct sockaddr *) &addr, &addrlen,
250 (struct sockaddr *) &addr, &addrlen);
251 assert (val == STUN_USAGE_BIND_RETURN_INVALID);
257 /** Various responses test */
258 static void responses (void)
260 struct sockaddr_storage addr;
261 socklen_t addrlen = sizeof (addr);
265 uint8_t buf[STUN_MAX_MESSAGE_SIZE];
266 uint8_t req[STUN_MAX_MESSAGE_SIZE];
272 uint16_t known_attributes[] = {
273 STUN_ATTRIBUTE_MAPPED_ADDRESS,
274 STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS,
275 STUN_ATTRIBUTE_PRIORITY,
276 STUN_ATTRIBUTE_USERNAME,
277 STUN_ATTRIBUTE_MESSAGE_INTEGRITY,
278 STUN_ATTRIBUTE_ERROR_CODE, 0};
280 stun_agent_init (&agent, known_attributes,
281 STUN_COMPATIBILITY_RFC5389, 0);
283 /* Allocate a local UDP port for server */
284 servfd = listen_dgram ();
285 assert (servfd != -1);
287 val = getsockname (servfd, (struct sockaddr *)&addr, &addrlen);
290 /* Allocate a client socket and connect to server */
291 fd = socket (addr.ss_family, SOCK_DGRAM, 0);
294 /* Send error response */
295 req_len = stun_usage_bind_create (&agent, &req_msg, req, sizeof(req));
296 assert (req_len > 0);
298 val = getsockname (servfd, (struct sockaddr *)&addr, &addrlen);
301 val = sendto (fd, req, req_len, MSG_DONTWAIT | MSG_NOSIGNAL,
302 (struct sockaddr *)&addr, addrlen);
305 val = recvfrom (servfd, buf, 1000, MSG_DONTWAIT, NULL, 0);
308 assert (stun_agent_validate (&agent, &msg, buf, val, NULL, NULL)
309 == STUN_VALIDATION_SUCCESS);
311 stun_agent_init_error (&agent, &msg, buf, sizeof (buf),
312 &msg, STUN_ERROR_SERVER_ERROR);
313 len = stun_agent_finish_message (&agent, &msg, NULL, 0);
316 val = getsockname (servfd, (struct sockaddr *)&addr, &addrlen);
319 val = stun_usage_bind_process (&msg, (struct sockaddr *) &addr, &addrlen,
320 (struct sockaddr *) &addr, &addrlen);
321 assert (val == STUN_USAGE_BIND_RETURN_ERROR);
323 /* Send response with a no mapped address at all */
324 req_len = stun_usage_bind_create (&agent, &req_msg, req, sizeof(req));
325 assert (req_len > 0);
327 val = getsockname (servfd, (struct sockaddr *)&addr, &addrlen);
330 val = sendto (fd, req, req_len, MSG_DONTWAIT | MSG_NOSIGNAL,
331 (struct sockaddr *)&addr, addrlen);
334 val = recvfrom (servfd, buf, 1000, MSG_DONTWAIT, NULL, 0);
337 assert (stun_agent_validate (&agent, &msg, buf, val, NULL, NULL)
338 == STUN_VALIDATION_SUCCESS);
340 stun_agent_init_response (&agent, &msg, buf, sizeof (buf), &msg);
341 len = stun_agent_finish_message (&agent, &msg, NULL, 0);
344 assert (stun_agent_validate (&agent, &msg, buf, len, NULL, NULL)
345 == STUN_VALIDATION_SUCCESS);
347 val = getsockname (servfd, (struct sockaddr *)&addr, &addrlen);
350 val = stun_usage_bind_process (&msg, (struct sockaddr *) &addr, &addrlen,
351 (struct sockaddr *) &addr, &addrlen);
352 assert (val == STUN_USAGE_BIND_RETURN_ERROR);
354 /* Send old-style response */
355 req_len = stun_usage_bind_create (&agent, &req_msg, req, sizeof(req));
356 assert (req_len > 0);
358 val = getsockname (servfd, (struct sockaddr *)&addr, &addrlen);
361 val = sendto (fd, req, req_len, MSG_DONTWAIT | MSG_NOSIGNAL,
362 (struct sockaddr *)&addr, addrlen);
365 val = recvfrom (servfd, buf, 1000, MSG_DONTWAIT, NULL, 0);
368 assert (stun_agent_validate (&agent, &msg, buf, val, NULL, NULL)
369 == STUN_VALIDATION_SUCCESS);
371 stun_agent_init_response (&agent, &msg, buf, sizeof (buf), &msg);
372 assert (stun_message_append_addr (&msg, STUN_ATTRIBUTE_MAPPED_ADDRESS,
373 (struct sockaddr *) &addr, addrlen) == STUN_MESSAGE_RETURN_SUCCESS);
374 len = stun_agent_finish_message (&agent, &msg, NULL, 0);
377 assert (stun_agent_validate (&agent, &msg, buf, len, NULL, NULL)
378 == STUN_VALIDATION_SUCCESS);
380 val = getsockname (servfd, (struct sockaddr *)&addr, &addrlen);
383 val = stun_usage_bind_process (&msg, (struct sockaddr *) &addr, &addrlen,
384 (struct sockaddr *) &addr, &addrlen);
385 assert (val == STUN_USAGE_BIND_RETURN_SUCCESS);
394 static void keepalive (void)
396 struct sockaddr_storage addr = {0};
397 socklen_t addrlen = sizeof (addr);
400 uint8_t buf[STUN_MAX_MESSAGE_SIZE];
405 uint16_t known_attributes[] = {
406 STUN_ATTRIBUTE_MAPPED_ADDRESS,
407 STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS,
408 STUN_ATTRIBUTE_PRIORITY,
409 STUN_ATTRIBUTE_USERNAME,
410 STUN_ATTRIBUTE_MESSAGE_INTEGRITY,
411 STUN_ATTRIBUTE_ERROR_CODE, 0};
413 stun_agent_init (&agent, known_attributes,
414 STUN_COMPATIBILITY_RFC5389, 0);
416 /* Allocate a local UDP port for server */
417 servfd = listen_dgram ();
418 assert (servfd != -1);
420 val = getsockname (servfd, (struct sockaddr *)&addr, &addrlen);
423 /* Allocate a client socket and connect to server */
424 fd = socket (addr.ss_family, SOCK_DGRAM, 0);
427 /* Keep alive sending smoke test */
428 len = stun_usage_bind_keepalive (&agent, &msg, buf, sizeof(buf));
431 val = sendto (fd, buf, len, MSG_DONTWAIT | MSG_NOSIGNAL,
432 (struct sockaddr *)&addr, addrlen);
443 static void test (void (*func) (void), const char *name)
447 printf ("%s test... ", name);
457 WSAStartup(0x0202, &w);
459 test (bad_family, "Bad socket family");
460 test (small_srv_addr, "Too small server address");
461 test (big_srv_addr, "Too big server address");
462 test (bad_responses, "Bad responses");
463 test (responses, "Error responses");
464 test (keepalive, "Keep alives");
466 test (timeout, "Binding discovery timeout");