Change all stun_XXX_t enums/structs into StunXxx to have a common naming convention
[sipe-libnice.git] / stun / tests / test-bind.c
blob282f82a77868f1379ff73775d457feb03090b89a
1 /*
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
15 * License.
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.
22 * Contributors:
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.
36 #ifdef HAVE_CONFIG_H
37 # include <config.h>
38 #endif
40 #include <sys/types.h>
41 #include "stun/stunagent.h"
42 #include "stun/usages/bind.h"
44 #include <stdlib.h>
45 #include <stdio.h>
46 #include <unistd.h>
47 #include <string.h>
49 #ifdef _WIN32
50 #include <winsock2.h>
51 #include <ws2tcpip.h>
53 #define MSG_DONTWAIT 0
54 #define MSG_NOSIGNAL 0
56 #define alarm(...)
57 #define close closesocket
58 #else
59 #include <sys/types.h>
60 #include <sys/socket.h>
61 #include <arpa/inet.h>
62 #include <netdb.h>
63 #endif
65 #undef NDEBUG /* ensure assertions are built-in */
66 #include <assert.h>
69 static int listen_dgram (void)
71 struct addrinfo hints, *res;
72 int val = -1;
74 memset (&hints, 0, sizeof (hints));
75 hints.ai_socktype = SOCK_DGRAM;
77 if (getaddrinfo (NULL, "0", &hints, &res))
78 return -1;
80 for (const struct addrinfo *ptr = res; ptr != NULL; ptr = ptr->ai_next)
82 int fd = socket (ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
83 if (fd == -1)
84 continue;
86 if (bind (fd, ptr->ai_addr, ptr->ai_addrlen))
88 close (fd);
89 continue;
92 val = fd;
93 break;
96 freeaddrinfo (res);
97 return val;
101 /** Incorrect socket family test */
102 static void bad_family (void)
104 struct sockaddr addr, dummy;
105 int val;
107 memset (&addr, 0, sizeof (addr));
108 addr.sa_family = AF_UNSPEC;
109 #ifdef HAVE_SA_LEN
110 addr.sa_len = sizeof (addr);
111 #endif
113 val = stun_usage_bind_run (&addr, sizeof (addr),
114 &dummy, &(socklen_t){ sizeof (dummy) });
115 assert (val != 0);
119 /** Too small socket address test */
120 static void small_srv_addr (void)
122 struct sockaddr addr, dummy;
123 int val;
125 memset (&addr, 0, sizeof (addr));
126 addr.sa_family = AF_INET;
127 #ifdef HAVE_SA_LEN
128 addr.sa_len = sizeof (addr);
129 #endif
131 val = stun_usage_bind_run (&addr, 1,
132 &dummy, &(socklen_t){ sizeof (dummy) });
133 assert (val == STUN_USAGE_BIND_RETURN_ERROR);
137 /** Too big socket address test */
138 static void big_srv_addr (void)
140 uint8_t buf[sizeof (struct sockaddr_storage) + 16];
141 struct sockaddr dummy;
142 int fd, val;
145 memset (buf, 0, sizeof (buf));
146 val = stun_usage_bind_run ((struct sockaddr *)buf, sizeof (buf),
147 &dummy, &(socklen_t){ sizeof (dummy) });
148 assert (val == STUN_USAGE_BIND_RETURN_ERROR);
152 /** Timeout test */
153 static void timeout (void)
155 struct sockaddr_storage srv;
156 struct sockaddr dummy;
157 socklen_t srvlen = sizeof (srv);
158 int val;
160 /* Allocate a local UDP port, so we are 100% sure nobody responds there */
161 int servfd = listen_dgram ();
162 assert (servfd != -1);
164 val = getsockname (servfd, (struct sockaddr *)&srv, &srvlen);
165 assert (val == 0);
167 val = stun_usage_bind_run ((struct sockaddr *)&srv, srvlen,
168 &dummy, &(socklen_t){ sizeof (dummy) });
169 assert (val == STUN_USAGE_BIND_RETURN_TIMEOUT);
171 close (servfd);
174 /** Malformed responses test */
175 static void bad_responses (void)
177 struct sockaddr_storage addr;
178 socklen_t addrlen = sizeof (addr);
179 ssize_t val, len;
180 uint8_t buf[STUN_MAX_MESSAGE_SIZE];
181 uint8_t req[STUN_MAX_MESSAGE_SIZE];
182 size_t req_len;
183 StunAgent agent;
184 StunMessage msg;
185 StunMessage req_msg;
187 uint16_t known_attributes[] = {
188 STUN_ATTRIBUTE_MAPPED_ADDRESS,
189 STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS,
190 STUN_ATTRIBUTE_PRIORITY,
191 STUN_ATTRIBUTE_USERNAME,
192 STUN_ATTRIBUTE_MESSAGE_INTEGRITY,
193 STUN_ATTRIBUTE_ERROR_CODE, 0};
195 stun_agent_init (&agent, known_attributes,
196 STUN_COMPATIBILITY_RFC5389, 0);
198 /* Allocate a local UDP port */
199 int servfd = listen_dgram (), fd;
200 assert (servfd != -1);
202 val = getsockname (servfd, (struct sockaddr *)&addr, &addrlen);
203 assert (val == 0);
205 fd = socket (addr.ss_family, SOCK_DGRAM, 0);
206 assert (fd != -1);
208 req_len = stun_usage_bind_create (&agent, &req_msg, req, sizeof(req));
209 assert (req_len > 0);
211 val = sendto (fd, req, req_len, MSG_DONTWAIT | MSG_NOSIGNAL,
212 (struct sockaddr *)&addr, addrlen);
213 assert (val >= 0);
215 /* Send to/receive from our client instance only */
216 val = getsockname (fd, (struct sockaddr *)&addr, &addrlen);
217 assert (val == 0);
219 val = connect (servfd, (struct sockaddr *)&addr, addrlen);
220 assert (val == 0);
222 /* Send request instead of response */
223 val = getsockname (servfd, (struct sockaddr *)&addr, &addrlen);
224 assert (val == 0);
225 len = recv (servfd, buf, 1000, MSG_DONTWAIT);
226 assert (len >= 20);
228 assert (stun_agent_validate (&agent, &msg, buf, len, NULL, NULL)
229 == STUN_VALIDATION_SUCCESS);
231 val = stun_usage_bind_process (&msg,
232 (struct sockaddr *)&addr, &addrlen, (struct sockaddr *)&addr, &addrlen);
233 assert (val == STUN_USAGE_BIND_RETURN_RETRY);
235 /* Send response with wrong request type */
236 buf[0] |= 0x03;
237 buf[0] ^= 0x02;
239 /* Send error response without ERROR-CODE */
240 buf[1] |= 0x10;
241 val = stun_usage_bind_process (&msg,
242 (struct sockaddr *)&addr, &addrlen, (struct sockaddr *)&addr, &addrlen);
243 assert (val == STUN_USAGE_BIND_RETURN_RETRY);
245 close (fd);
246 close (servfd);
249 /** Various responses test */
250 static void responses (void)
252 struct sockaddr_storage addr;
253 socklen_t addrlen = sizeof (addr);
254 ssize_t val;
255 size_t len;
256 int servfd, fd;
257 uint8_t buf[STUN_MAX_MESSAGE_SIZE];
258 uint8_t req[STUN_MAX_MESSAGE_SIZE];
259 size_t req_len;
260 StunAgent agent;
261 StunMessage msg;
262 StunMessage req_msg;
264 uint16_t known_attributes[] = {
265 STUN_ATTRIBUTE_MAPPED_ADDRESS,
266 STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS,
267 STUN_ATTRIBUTE_PRIORITY,
268 STUN_ATTRIBUTE_USERNAME,
269 STUN_ATTRIBUTE_MESSAGE_INTEGRITY,
270 STUN_ATTRIBUTE_ERROR_CODE, 0};
272 stun_agent_init (&agent, known_attributes,
273 STUN_COMPATIBILITY_RFC5389, 0);
275 /* Allocate a local UDP port for server */
276 servfd = listen_dgram ();
277 assert (servfd != -1);
279 val = getsockname (servfd, (struct sockaddr *)&addr, &addrlen);
280 assert (val == 0);
282 /* Allocate a client socket and connect to server */
283 fd = socket (addr.ss_family, SOCK_DGRAM, 0);
284 assert (fd != -1);
286 val = connect (fd, (struct sockaddr *)&addr, addrlen);
287 assert (val == 0);
289 /* Send to/receive from our client instance only */
290 val = getsockname (fd, (struct sockaddr *)&addr, &addrlen);
291 assert (val == 0);
293 val = connect (servfd, (struct sockaddr *)&addr, addrlen);
294 assert (val == 0);
296 /* Send error response */
297 req_len = stun_usage_bind_create (&agent, &req_msg, req, sizeof(req));
298 assert (req_len > 0);
300 val = send (fd, req, req_len, MSG_DONTWAIT | MSG_NOSIGNAL);
301 assert (val >= 0);
303 val = recv (servfd, buf, 1000, MSG_DONTWAIT);
304 assert (val >= 0);
306 assert (stun_agent_validate (&agent, &msg, buf, val, NULL, NULL)
307 == STUN_VALIDATION_SUCCESS);
309 stun_agent_init_error (&agent, &msg, buf, sizeof (buf), &msg, STUN_ERROR_SERVER_ERROR);
310 len = stun_agent_finish_message (&agent, &msg, NULL, 0);
311 assert (len > 0);
313 val = getsockname (servfd, (struct sockaddr *)&addr, &addrlen);
314 assert (val == 0);
316 val = stun_usage_bind_process (&msg,
317 (struct sockaddr *)&addr, &addrlen, (struct sockaddr *)&addr, &addrlen);
318 assert (val == STUN_USAGE_BIND_RETURN_ERROR);
320 /* Send response with a no mapped address at all */
321 req_len = stun_usage_bind_create (&agent, &req_msg, req, sizeof(req));
322 assert (req_len > 0);
324 val = send (fd, req, req_len, MSG_DONTWAIT | MSG_NOSIGNAL);
325 assert (val >= 0);
327 val = recv (servfd, buf, 1000, MSG_DONTWAIT);
328 assert (val >= 0);
330 assert (stun_agent_validate (&agent, &msg, buf, val, NULL, NULL)
331 == STUN_VALIDATION_SUCCESS);
333 stun_agent_init_response (&agent, &msg, buf, sizeof (buf), &msg);
334 len = stun_agent_finish_message (&agent, &msg, NULL, 0);
335 assert (len > 0);
337 assert (stun_agent_validate (&agent, &msg, buf, len, NULL, NULL)
338 == STUN_VALIDATION_SUCCESS);
340 val = getsockname (servfd, (struct sockaddr *)&addr, &addrlen);
341 assert (val == 0);
343 val = stun_usage_bind_process (&msg,
344 (struct sockaddr *)&addr, &addrlen, (struct sockaddr *)&addr, &addrlen);
345 assert (val == STUN_USAGE_BIND_RETURN_ERROR);
347 /* Send old-style response */
348 req_len = stun_usage_bind_create (&agent, &req_msg, req, sizeof(req));
349 assert (req_len > 0);
351 val = send (fd, req, req_len, MSG_DONTWAIT | MSG_NOSIGNAL);
352 assert (val >= 0);
354 val = recv (servfd, buf, 1000, MSG_DONTWAIT);
355 assert (val >= 0);
357 assert (stun_agent_validate (&agent, &msg, buf, val, NULL, NULL)
358 == STUN_VALIDATION_SUCCESS);
360 stun_agent_init_response (&agent, &msg, buf, sizeof (buf), &msg);
361 assert (stun_message_append_addr (&msg, STUN_ATTRIBUTE_MAPPED_ADDRESS,
362 (struct sockaddr *)&addr, addrlen) == STUN_MESSAGE_RETURN_SUCCESS);
363 len = stun_agent_finish_message (&agent, &msg, NULL, 0);
364 assert (len > 0);
366 assert (stun_agent_validate (&agent, &msg, buf, len, NULL, NULL)
367 == STUN_VALIDATION_SUCCESS);
369 val = getsockname (servfd, (struct sockaddr *)&addr, &addrlen);
370 assert (val == 0);
372 val = stun_usage_bind_process (&msg,
373 (struct sockaddr *)&addr, &addrlen, (struct sockaddr *)&addr, &addrlen);
374 assert (val == STUN_USAGE_BIND_RETURN_SUCCESS);
376 /* End */
377 close (servfd);
379 val = close (fd);
380 assert (val == 0);
383 static void keepalive (void)
385 struct sockaddr_storage addr = {0};
386 socklen_t addrlen = sizeof (addr);
387 int val, servfd, fd;
389 uint8_t buf[STUN_MAX_MESSAGE_SIZE];
390 size_t len;
391 StunAgent agent;
392 StunMessage msg;
394 uint16_t known_attributes[] = {
395 STUN_ATTRIBUTE_MAPPED_ADDRESS,
396 STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS,
397 STUN_ATTRIBUTE_PRIORITY,
398 STUN_ATTRIBUTE_USERNAME,
399 STUN_ATTRIBUTE_MESSAGE_INTEGRITY,
400 STUN_ATTRIBUTE_ERROR_CODE, 0};
402 stun_agent_init (&agent, known_attributes,
403 STUN_COMPATIBILITY_RFC5389, 0);
405 /* Allocate a local UDP port for server */
406 servfd = listen_dgram ();
407 assert (servfd != -1);
409 val = getsockname (servfd, (struct sockaddr *)&addr, &addrlen);
410 assert (val == 0);
412 /* Allocate a client socket and connect to server */
413 fd = socket (addr.ss_family, SOCK_DGRAM, 0);
414 assert (fd != -1);
416 /* Keep alive sending smoke test */
417 len = stun_usage_bind_keepalive (&agent, &msg, buf, sizeof(buf));
418 assert (len == 20);
420 val = sendto (fd, buf, len, MSG_DONTWAIT | MSG_NOSIGNAL,
421 (struct sockaddr *)&addr, addrlen);
422 assert (val >= 0);
425 /* Wrong address family test */
426 addr.ss_family = addr.ss_family == AF_INET ? AF_INET6 : AF_INET;
427 val = sendto (fd, buf, len, MSG_DONTWAIT | MSG_NOSIGNAL,
428 (struct sockaddr *)&addr, addrlen);
429 assert (val < 0);
431 /* End */
432 close (servfd);
434 val = close (fd);
435 assert (val == 0);
439 static void test (void (*func) (void), const char *name)
441 alarm (10);
443 printf ("%s test... ", name);
444 func ();
445 puts ("OK");
449 int main (void)
451 test (bad_family, "Bad socket family");
452 test (small_srv_addr, "Too small server address");
453 test (big_srv_addr, "Too big server address");
454 test (bad_responses, "Bad responses");
455 test (responses, "Error responses");
456 test (keepalive, "Keep alives");
457 test (timeout, "Binding discovery timeout");
458 return 0;