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"
53 #define MSG_DONTWAIT 0
54 #define MSG_NOSIGNAL 0
57 #define close closesocket
59 #include <sys/types.h>
60 #include <sys/socket.h>
61 #include <arpa/inet.h>
65 #undef NDEBUG /* ensure assertions are built-in */
69 static int listen_dgram (void)
71 struct addrinfo hints
, *res
;
74 memset (&hints
, 0, sizeof (hints
));
75 hints
.ai_socktype
= SOCK_DGRAM
;
77 if (getaddrinfo (NULL
, "0", &hints
, &res
))
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
);
86 if (bind (fd
, ptr
->ai_addr
, ptr
->ai_addrlen
))
101 /** Incorrect socket family test */
102 static void bad_family (void)
104 struct sockaddr addr
, dummy
;
107 memset (&addr
, 0, sizeof (addr
));
108 addr
.sa_family
= AF_UNSPEC
;
110 addr
.sa_len
= sizeof (addr
);
113 val
= stun_usage_bind_run (&addr
, sizeof (addr
),
114 &dummy
, &(socklen_t
){ sizeof (dummy
) });
119 /** Too small socket address test */
120 static void small_srv_addr (void)
122 struct sockaddr addr
, dummy
;
125 memset (&addr
, 0, sizeof (addr
));
126 addr
.sa_family
= AF_INET
;
128 addr
.sa_len
= sizeof (addr
);
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
;
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
);
153 static void timeout (void)
155 struct sockaddr_storage srv
;
156 struct sockaddr dummy
;
157 socklen_t srvlen
= sizeof (srv
);
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
);
167 val
= stun_usage_bind_run ((struct sockaddr
*)&srv
, srvlen
,
168 &dummy
, &(socklen_t
){ sizeof (dummy
) });
169 assert (val
== STUN_USAGE_BIND_RETURN_TIMEOUT
);
174 /** Malformed responses test */
175 static void bad_responses (void)
177 struct sockaddr_storage addr
;
178 socklen_t addrlen
= sizeof (addr
);
180 uint8_t buf
[STUN_MAX_MESSAGE_SIZE
];
181 uint8_t req
[STUN_MAX_MESSAGE_SIZE
];
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
);
205 fd
= socket (addr
.ss_family
, SOCK_DGRAM
, 0);
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
);
215 /* Send to/receive from our client instance only */
216 val
= getsockname (fd
, (struct sockaddr
*)&addr
, &addrlen
);
219 val
= connect (servfd
, (struct sockaddr
*)&addr
, addrlen
);
222 /* Send request instead of response */
223 val
= getsockname (servfd
, (struct sockaddr
*)&addr
, &addrlen
);
225 len
= recv (servfd
, buf
, 1000, MSG_DONTWAIT
);
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 */
239 /* Send error response without ERROR-CODE */
241 val
= stun_usage_bind_process (&msg
,
242 (struct sockaddr
*)&addr
, &addrlen
, (struct sockaddr
*)&addr
, &addrlen
);
243 assert (val
== STUN_USAGE_BIND_RETURN_RETRY
);
249 /** Various responses test */
250 static void responses (void)
252 struct sockaddr_storage addr
;
253 socklen_t addrlen
= sizeof (addr
);
257 uint8_t buf
[STUN_MAX_MESSAGE_SIZE
];
258 uint8_t req
[STUN_MAX_MESSAGE_SIZE
];
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
);
282 /* Allocate a client socket and connect to server */
283 fd
= socket (addr
.ss_family
, SOCK_DGRAM
, 0);
286 val
= connect (fd
, (struct sockaddr
*)&addr
, addrlen
);
289 /* Send to/receive from our client instance only */
290 val
= getsockname (fd
, (struct sockaddr
*)&addr
, &addrlen
);
293 val
= connect (servfd
, (struct sockaddr
*)&addr
, addrlen
);
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
);
303 val
= recv (servfd
, buf
, 1000, MSG_DONTWAIT
);
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);
313 val
= getsockname (servfd
, (struct sockaddr
*)&addr
, &addrlen
);
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
);
327 val
= recv (servfd
, buf
, 1000, MSG_DONTWAIT
);
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);
337 assert (stun_agent_validate (&agent
, &msg
, buf
, len
, NULL
, NULL
)
338 == STUN_VALIDATION_SUCCESS
);
340 val
= getsockname (servfd
, (struct sockaddr
*)&addr
, &addrlen
);
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
);
354 val
= recv (servfd
, buf
, 1000, MSG_DONTWAIT
);
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);
366 assert (stun_agent_validate (&agent
, &msg
, buf
, len
, NULL
, NULL
)
367 == STUN_VALIDATION_SUCCESS
);
369 val
= getsockname (servfd
, (struct sockaddr
*)&addr
, &addrlen
);
372 val
= stun_usage_bind_process (&msg
,
373 (struct sockaddr
*)&addr
, &addrlen
, (struct sockaddr
*)&addr
, &addrlen
);
374 assert (val
== STUN_USAGE_BIND_RETURN_SUCCESS
);
383 static void keepalive (void)
385 struct sockaddr_storage addr
= {0};
386 socklen_t addrlen
= sizeof (addr
);
389 uint8_t buf
[STUN_MAX_MESSAGE_SIZE
];
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
);
412 /* Allocate a client socket and connect to server */
413 fd
= socket (addr
.ss_family
, SOCK_DGRAM
, 0);
416 /* Keep alive sending smoke test */
417 len
= stun_usage_bind_keepalive (&agent
, &msg
, buf
, sizeof(buf
));
420 val
= sendto (fd
, buf
, len
, MSG_DONTWAIT
| MSG_NOSIGNAL
,
421 (struct sockaddr
*)&addr
, addrlen
);
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
);
439 static void test (void (*func
) (void), const char *name
)
443 printf ("%s test... ", name
);
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");