7df9b3cdf0e1acc1d5a8fa2a81afad04d0a8a79f
[platform/upstream/libnice.git] / stun / tests / test-bind.c
1 /*
2  * This file is part of the Nice GLib ICE library.
3  *
4  * (C) 2007 Nokia Corporation. All rights reserved.
5  *  Contact: Rémi Denis-Courmont
6  *
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/
11  *
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.
16  *
17  * The Original Code is the Nice GLib ICE library.
18  *
19  * The Initial Developers of the Original Code are Collabora Ltd and Nokia
20  * Corporation. All Rights Reserved.
21  *
22  * Contributors:
23  *   Rémi Denis-Courmont, Nokia
24  *
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.
34  */
35
36 #ifdef HAVE_CONFIG_H
37 # include <config.h>
38 #endif
39
40 #include <sys/types.h>
41 #include "stun/stunagent.h"
42 #include "stun/usages/bind.h"
43
44 #include <stdlib.h>
45 #include <stdio.h>
46 #include <string.h>
47
48 #ifdef _WIN32
49 #include <winsock2.h>
50 #include <ws2tcpip.h>
51
52 #define MSG_DONTWAIT 0
53
54 #define alarm(...)
55 #define close closesocket
56 #else
57 #include <sys/types.h>
58 #include <sys/socket.h>
59 #include <arpa/inet.h>
60 #include <unistd.h>
61 #include <netdb.h>
62 #endif
63
64 #undef NDEBUG /* ensure assertions are built-in */
65 #include <assert.h>
66
67 #ifndef MSG_NOSIGNAL
68 #define MSG_NOSIGNAL 0
69 #endif
70
71 static int listen_dgram (void)
72 {
73   struct addrinfo hints, *res;
74   const struct addrinfo *ptr;
75   int val = -1;
76
77   memset (&hints, 0, sizeof (hints));
78   hints.ai_socktype = SOCK_DGRAM;
79
80   if (getaddrinfo (NULL, "0", &hints, &res))
81     return -1;
82
83   for (ptr = res; ptr != NULL; ptr = ptr->ai_next)
84   {
85     int fd = socket (ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
86     if (fd == -1)
87       continue;
88
89     if (bind (fd, ptr->ai_addr, ptr->ai_addrlen))
90     {
91       close (fd);
92       continue;
93     }
94
95     val = fd;
96     break;
97   }
98
99   freeaddrinfo (res);
100   return val;
101 }
102
103
104 /** Incorrect socket family test */
105 static void bad_family (void)
106 {
107   struct sockaddr addr;
108   struct sockaddr_storage dummy;
109   int val;
110   socklen_t dummylen = sizeof(dummy);
111
112   memset (&addr, 0, sizeof (addr));
113   addr.sa_family = AF_UNSPEC;
114 #ifdef HAVE_SA_LEN
115   addr.sa_len = sizeof (addr);
116 #endif
117
118   val = stun_usage_bind_run (&addr, sizeof (addr),
119                        &dummy, &dummylen);
120   assert (val != 0);
121 }
122
123
124 /** Too small socket address test */
125 static void small_srv_addr (void)
126 {
127   struct sockaddr addr;
128   struct sockaddr_storage dummy;
129   int val;
130   socklen_t dummylen = sizeof(dummy);
131
132   memset (&addr, 0, sizeof (addr));
133   addr.sa_family = AF_INET;
134 #ifdef HAVE_SA_LEN
135   addr.sa_len = sizeof (addr);
136 #endif
137
138   val = stun_usage_bind_run (&addr, 1,
139                        &dummy, &dummylen);
140   assert (val == STUN_USAGE_BIND_RETURN_ERROR);
141 }
142
143
144 /** Too big socket address test */
145 static void big_srv_addr (void)
146 {
147   uint8_t buf[sizeof (struct sockaddr_storage) + 16];
148   struct sockaddr_storage dummy;
149   int val;
150   socklen_t dummylen = sizeof(dummy);
151
152
153   memset (buf, 0, sizeof (buf));
154   val = stun_usage_bind_run ((struct sockaddr *)buf, sizeof (buf),
155                        &dummy, &dummylen);
156   assert (val == STUN_USAGE_BIND_RETURN_ERROR);
157 }
158
159
160 #ifdef HAVE_POLL
161 /** Timeout test */
162 static void timeout (void)
163 {
164   struct sockaddr_storage srv, dummy;
165   socklen_t srvlen = sizeof (srv);
166   socklen_t dummylen = sizeof(dummy);
167   int val;
168
169   /* Allocate a local UDP port, so we are 100% sure nobody responds there */
170   int servfd = listen_dgram ();
171   assert (servfd != -1);
172
173   val = getsockname (servfd, (struct sockaddr *)&srv, &srvlen);
174   assert (val == 0);
175
176   val = stun_usage_bind_run ((struct sockaddr *)&srv, srvlen,
177                        &dummy, &dummylen);
178   assert (val == STUN_USAGE_BIND_RETURN_TIMEOUT);
179
180   close (servfd);
181 }
182 #endif
183
184 /** Malformed responses test */
185 static void bad_responses (void)
186 {
187   struct sockaddr_storage addr;
188   socklen_t addrlen = sizeof (addr);
189   ssize_t val, len;
190   uint8_t buf[STUN_MAX_MESSAGE_SIZE];
191   uint8_t req[STUN_MAX_MESSAGE_SIZE];
192   size_t req_len;
193   StunAgent agent;
194   StunMessage msg;
195   StunMessage req_msg;
196   int servfd, fd;
197
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};
205
206   stun_agent_init (&agent, known_attributes,
207       STUN_COMPATIBILITY_RFC5389, 0);
208
209   /* Allocate a local UDP port */
210   servfd = listen_dgram ();
211   assert (servfd != -1);
212
213   val = getsockname (servfd, (struct sockaddr *)&addr, &addrlen);
214   assert (val == 0);
215
216   fd = socket (addr.ss_family, SOCK_DGRAM, 0);
217   assert (fd != -1);
218
219   req_len = stun_usage_bind_create (&agent, &req_msg, req, sizeof(req));
220   assert (req_len > 0);
221
222   val = sendto (fd, req, req_len, MSG_DONTWAIT | MSG_NOSIGNAL,
223       (struct sockaddr *)&addr, addrlen);
224   assert (val >= 0);
225
226   /* Send to/receive from our client instance only */
227   val = getsockname (fd, (struct sockaddr *)&addr, &addrlen);
228   assert (val == 0);
229
230   /* Send request instead of response */
231   val = getsockname (servfd, (struct sockaddr *)&addr, &addrlen);
232   assert (val == 0);
233   len = recvfrom (servfd, buf, 1000, MSG_DONTWAIT, NULL, 0);
234   assert (len >= 20);
235
236   assert (stun_agent_validate (&agent, &msg, buf, len, NULL, NULL)
237       == STUN_VALIDATION_SUCCESS);
238
239   val = stun_usage_bind_process (&msg, (struct sockaddr *) &addr, &addrlen,
240       (struct sockaddr *) &addr, &addrlen);
241   assert (val == STUN_USAGE_BIND_RETURN_INVALID);
242
243   /* Send response with wrong request type */
244   buf[0] |= 0x03;
245   buf[0] ^= 0x02;
246
247   /* Send error response without ERROR-CODE */
248   buf[1] |= 0x10;
249   val = stun_usage_bind_process (&msg, (struct sockaddr *) &addr, &addrlen,
250       (struct sockaddr *) &addr, &addrlen);
251   assert (val == STUN_USAGE_BIND_RETURN_INVALID);
252
253   close (fd);
254   close (servfd);
255 }
256
257 /** Various responses test */
258 static void responses (void)
259 {
260   struct sockaddr_storage addr;
261   socklen_t addrlen = sizeof (addr);
262   ssize_t val;
263   size_t len;
264   int servfd, fd;
265   uint8_t buf[STUN_MAX_MESSAGE_SIZE];
266   uint8_t req[STUN_MAX_MESSAGE_SIZE];
267   size_t req_len;
268   StunAgent agent;
269   StunMessage msg;
270   StunMessage req_msg;
271
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};
279
280   stun_agent_init (&agent, known_attributes,
281       STUN_COMPATIBILITY_RFC5389, 0);
282
283   /* Allocate a local UDP port for server */
284   servfd = listen_dgram ();
285   assert (servfd != -1);
286
287   val = getsockname (servfd, (struct sockaddr *)&addr, &addrlen);
288   assert (val == 0);
289
290   /* Allocate a client socket and connect to server */
291   fd = socket (addr.ss_family, SOCK_DGRAM, 0);
292   assert (fd != -1);
293
294   /* Send error response */
295   req_len = stun_usage_bind_create (&agent, &req_msg, req, sizeof(req));
296   assert (req_len > 0);
297
298   val = getsockname (servfd, (struct sockaddr *)&addr, &addrlen);
299   assert (val == 0);
300
301   val = sendto (fd, req, req_len, MSG_DONTWAIT | MSG_NOSIGNAL,
302       (struct sockaddr *)&addr, addrlen);
303   assert (val >= 0);
304
305   val = recvfrom (servfd, buf, 1000, MSG_DONTWAIT, NULL, 0);
306   assert (val >= 0);
307
308   assert (stun_agent_validate (&agent, &msg, buf, val, NULL, NULL)
309       == STUN_VALIDATION_SUCCESS);
310
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);
314   assert (len > 0);
315
316   val = getsockname (servfd, (struct sockaddr *)&addr, &addrlen);
317   assert (val == 0);
318
319   val = stun_usage_bind_process (&msg, (struct sockaddr *) &addr, &addrlen,
320       (struct sockaddr *) &addr, &addrlen);
321   assert (val == STUN_USAGE_BIND_RETURN_ERROR);
322
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);
326
327   val = getsockname (servfd, (struct sockaddr *)&addr, &addrlen);
328   assert (val == 0);
329
330   val = sendto (fd, req, req_len, MSG_DONTWAIT | MSG_NOSIGNAL,
331       (struct sockaddr *)&addr, addrlen);
332   assert (val >= 0);
333
334   val = recvfrom (servfd, buf, 1000, MSG_DONTWAIT, NULL, 0);
335   assert (val >= 0);
336
337   assert (stun_agent_validate (&agent, &msg, buf, val, NULL, NULL)
338       == STUN_VALIDATION_SUCCESS);
339
340   stun_agent_init_response (&agent, &msg, buf, sizeof (buf), &msg);
341   len = stun_agent_finish_message (&agent, &msg, NULL, 0);
342   assert (len > 0);
343
344   assert (stun_agent_validate (&agent, &msg, buf, len, NULL, NULL)
345       == STUN_VALIDATION_SUCCESS);
346
347   val = getsockname (servfd, (struct sockaddr *)&addr, &addrlen);
348   assert (val == 0);
349
350   val = stun_usage_bind_process (&msg, (struct sockaddr *) &addr, &addrlen,
351       (struct sockaddr *) &addr, &addrlen);
352   assert (val == STUN_USAGE_BIND_RETURN_ERROR);
353
354   /* Send old-style response */
355   req_len = stun_usage_bind_create (&agent, &req_msg, req, sizeof(req));
356   assert (req_len > 0);
357
358   val = getsockname (servfd, (struct sockaddr *)&addr, &addrlen);
359   assert (val == 0);
360
361   val = sendto (fd, req, req_len, MSG_DONTWAIT | MSG_NOSIGNAL,
362       (struct sockaddr *)&addr, addrlen);
363   assert (val >= 0);
364
365   val = recvfrom (servfd, buf, 1000, MSG_DONTWAIT, NULL, 0);
366   assert (val >= 0);
367
368   assert (stun_agent_validate (&agent, &msg, buf, val, NULL, NULL)
369       == STUN_VALIDATION_SUCCESS);
370
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);
375   assert (len > 0);
376
377   assert (stun_agent_validate (&agent, &msg, buf, len, NULL, NULL)
378       == STUN_VALIDATION_SUCCESS);
379
380   val = getsockname (servfd, (struct sockaddr *)&addr, &addrlen);
381   assert (val == 0);
382
383   val = stun_usage_bind_process (&msg, (struct sockaddr *) &addr, &addrlen,
384       (struct sockaddr *) &addr, &addrlen);
385   assert (val == STUN_USAGE_BIND_RETURN_SUCCESS);
386
387   /* End */
388   close (servfd);
389
390   val = close (fd);
391   assert (val == 0);
392 }
393
394 static void keepalive (void)
395 {
396   struct sockaddr_storage addr = {0};
397   socklen_t addrlen = sizeof (addr);
398   int val, servfd, fd;
399
400   uint8_t buf[STUN_MAX_MESSAGE_SIZE];
401   size_t len;
402   StunAgent agent;
403   StunMessage msg;
404
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};
412
413   stun_agent_init (&agent, known_attributes,
414       STUN_COMPATIBILITY_RFC5389, 0);
415
416   /* Allocate a local UDP port for server */
417   servfd = listen_dgram ();
418   assert (servfd != -1);
419
420   val = getsockname (servfd, (struct sockaddr *)&addr, &addrlen);
421   assert (val == 0);
422
423   /* Allocate a client socket and connect to server */
424   fd = socket (addr.ss_family, SOCK_DGRAM, 0);
425   assert (fd != -1);
426
427   /* Keep alive sending smoke test */
428   len = stun_usage_bind_keepalive (&agent, &msg, buf, sizeof(buf));
429   assert (len == 20);
430
431   val = sendto (fd, buf, len, MSG_DONTWAIT | MSG_NOSIGNAL,
432       (struct sockaddr *)&addr, addrlen);
433   assert (val >= 0);
434
435   /* End */
436   close (servfd);
437
438   val = close (fd);
439   assert (val == 0);
440 }
441
442
443 static void test (void (*func) (void), const char *name)
444 {
445   alarm (30);
446
447   printf ("%s test... ", name);
448   func ();
449   puts ("OK");
450 }
451
452
453 int main (void)
454 {
455 #ifdef _WIN32
456   WSADATA w;
457   WSAStartup(0x0202, &w);
458 #endif
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");
465 #ifdef HAVE_POLL
466   test (timeout, "Binding discovery timeout");
467 #endif
468 #ifdef _WIN32
469   WSACleanup();
470 #endif
471   return 0;
472 }