PageRenderTime 70ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/stun/tests/test-bind.c

https://gitlab.com/libnice/libnice
C | 472 lines | 318 code | 98 blank | 56 comment | 44 complexity | d724a0b53858a2253812f2d665656b99 MD5 | raw file
  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. #ifdef HAVE_CONFIG_H
  36. # include <config.h>
  37. #endif
  38. #include <sys/types.h>
  39. #include "stun/stunagent.h"
  40. #include "stun/usages/bind.h"
  41. #include <stdlib.h>
  42. #include <stdio.h>
  43. #include <string.h>
  44. #ifdef _WIN32
  45. #include <winsock2.h>
  46. #include <ws2tcpip.h>
  47. #define MSG_DONTWAIT 0
  48. #define alarm(...)
  49. #define close closesocket
  50. #else
  51. #include <sys/types.h>
  52. #include <sys/socket.h>
  53. #include <arpa/inet.h>
  54. #include <unistd.h>
  55. #include <netdb.h>
  56. #endif
  57. #undef NDEBUG /* ensure assertions are built-in */
  58. #include <assert.h>
  59. #ifndef MSG_NOSIGNAL
  60. #define MSG_NOSIGNAL 0
  61. #endif
  62. static int listen_dgram (void)
  63. {
  64. struct addrinfo hints, *res;
  65. const struct addrinfo *ptr;
  66. int val = -1;
  67. memset (&hints, 0, sizeof (hints));
  68. hints.ai_socktype = SOCK_DGRAM;
  69. if (getaddrinfo (NULL, "0", &hints, &res))
  70. return -1;
  71. for (ptr = res; ptr != NULL; ptr = ptr->ai_next)
  72. {
  73. int fd = socket (ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
  74. if (fd == -1)
  75. continue;
  76. if (bind (fd, ptr->ai_addr, ptr->ai_addrlen))
  77. {
  78. close (fd);
  79. continue;
  80. }
  81. val = fd;
  82. break;
  83. }
  84. freeaddrinfo (res);
  85. return val;
  86. }
  87. /** Incorrect socket family test */
  88. static void bad_family (void)
  89. {
  90. struct sockaddr addr;
  91. struct sockaddr_storage dummy;
  92. int val;
  93. socklen_t dummylen = sizeof(dummy);
  94. memset (&addr, 0, sizeof (addr));
  95. addr.sa_family = AF_UNSPEC;
  96. #ifdef HAVE_SA_LEN
  97. addr.sa_len = sizeof (addr);
  98. #endif
  99. val = stun_usage_bind_run (&addr, sizeof (addr),
  100. &dummy, &dummylen);
  101. assert (val != 0);
  102. }
  103. /** Too small socket address test */
  104. static void small_srv_addr (void)
  105. {
  106. struct sockaddr addr;
  107. struct sockaddr_storage dummy;
  108. int val;
  109. socklen_t dummylen = sizeof(dummy);
  110. memset (&addr, 0, sizeof (addr));
  111. addr.sa_family = AF_INET;
  112. #ifdef HAVE_SA_LEN
  113. addr.sa_len = sizeof (addr);
  114. #endif
  115. val = stun_usage_bind_run (&addr, 1,
  116. &dummy, &dummylen);
  117. assert (val == STUN_USAGE_BIND_RETURN_ERROR);
  118. }
  119. /** Too big socket address test */
  120. static void big_srv_addr (void)
  121. {
  122. uint8_t buf[sizeof (struct sockaddr_storage) + 16];
  123. struct sockaddr_storage dummy;
  124. int val;
  125. socklen_t dummylen = sizeof(dummy);
  126. memset (buf, 0, sizeof (buf));
  127. val = stun_usage_bind_run ((struct sockaddr *)buf, sizeof (buf),
  128. &dummy, &dummylen);
  129. assert (val == STUN_USAGE_BIND_RETURN_ERROR);
  130. }
  131. #ifdef HAVE_POLL
  132. /** Timeout test */
  133. static void timeout (void)
  134. {
  135. struct sockaddr_storage srv, dummy;
  136. socklen_t srvlen = sizeof (srv);
  137. socklen_t dummylen = sizeof(dummy);
  138. int val;
  139. /* Allocate a local UDP port, so we are 100% sure nobody responds there */
  140. int servfd = listen_dgram ();
  141. assert (servfd != -1);
  142. val = getsockname (servfd, (struct sockaddr *)&srv, &srvlen);
  143. assert (val == 0);
  144. val = stun_usage_bind_run ((struct sockaddr *)&srv, srvlen,
  145. &dummy, &dummylen);
  146. assert (val == STUN_USAGE_BIND_RETURN_TIMEOUT);
  147. close (servfd);
  148. }
  149. #endif
  150. /** Malformed responses test */
  151. static void bad_responses (void)
  152. {
  153. struct sockaddr_storage addr;
  154. socklen_t addrlen = sizeof (addr);
  155. ssize_t val, len;
  156. uint8_t buf[STUN_MAX_MESSAGE_SIZE];
  157. uint8_t req[STUN_MAX_MESSAGE_SIZE];
  158. size_t req_len;
  159. StunAgent agent;
  160. StunMessage msg;
  161. StunMessage req_msg;
  162. int servfd, fd;
  163. uint16_t known_attributes[] = {
  164. STUN_ATTRIBUTE_MAPPED_ADDRESS,
  165. STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS,
  166. STUN_ATTRIBUTE_PRIORITY,
  167. STUN_ATTRIBUTE_USERNAME,
  168. STUN_ATTRIBUTE_MESSAGE_INTEGRITY,
  169. STUN_ATTRIBUTE_ERROR_CODE, 0};
  170. stun_agent_init (&agent, known_attributes,
  171. STUN_COMPATIBILITY_RFC5389, 0);
  172. /* Allocate a local UDP port */
  173. servfd = listen_dgram ();
  174. assert (servfd != -1);
  175. val = getsockname (servfd, (struct sockaddr *)&addr, &addrlen);
  176. assert (val == 0);
  177. fd = socket (addr.ss_family, SOCK_DGRAM, 0);
  178. assert (fd != -1);
  179. req_len = stun_usage_bind_create (&agent, &req_msg, req, sizeof(req));
  180. assert (req_len > 0);
  181. val = sendto (fd, req, req_len, MSG_DONTWAIT | MSG_NOSIGNAL,
  182. (struct sockaddr *)&addr, addrlen);
  183. assert (val >= 0);
  184. /* Send to/receive from our client instance only */
  185. val = getsockname (fd, (struct sockaddr *)&addr, &addrlen);
  186. assert (val == 0);
  187. /* Send request instead of response */
  188. val = getsockname (servfd, (struct sockaddr *)&addr, &addrlen);
  189. assert (val == 0);
  190. len = recvfrom (servfd, buf, 1000, MSG_DONTWAIT, NULL, 0);
  191. assert (len >= 20);
  192. assert (stun_agent_validate (&agent, &msg, buf, len, NULL, NULL)
  193. == STUN_VALIDATION_SUCCESS);
  194. val = stun_usage_bind_process (&msg, (struct sockaddr *) &addr, &addrlen,
  195. (struct sockaddr *) &addr, &addrlen);
  196. assert (val == STUN_USAGE_BIND_RETURN_INVALID);
  197. /* Send response with wrong request type */
  198. buf[0] |= 0x03;
  199. buf[0] ^= 0x02;
  200. /* Send error response without ERROR-CODE */
  201. buf[1] |= 0x10;
  202. val = stun_usage_bind_process (&msg, (struct sockaddr *) &addr, &addrlen,
  203. (struct sockaddr *) &addr, &addrlen);
  204. assert (val == STUN_USAGE_BIND_RETURN_INVALID);
  205. close (fd);
  206. close (servfd);
  207. }
  208. /** Various responses test */
  209. static void responses (void)
  210. {
  211. struct sockaddr_storage addr;
  212. socklen_t addrlen = sizeof (addr);
  213. ssize_t val;
  214. size_t len;
  215. int servfd, fd;
  216. uint8_t buf[STUN_MAX_MESSAGE_SIZE];
  217. uint8_t req[STUN_MAX_MESSAGE_SIZE];
  218. size_t req_len;
  219. StunAgent agent;
  220. StunMessage msg;
  221. StunMessage req_msg;
  222. uint16_t known_attributes[] = {
  223. STUN_ATTRIBUTE_MAPPED_ADDRESS,
  224. STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS,
  225. STUN_ATTRIBUTE_PRIORITY,
  226. STUN_ATTRIBUTE_USERNAME,
  227. STUN_ATTRIBUTE_MESSAGE_INTEGRITY,
  228. STUN_ATTRIBUTE_ERROR_CODE, 0};
  229. stun_agent_init (&agent, known_attributes,
  230. STUN_COMPATIBILITY_RFC5389, 0);
  231. /* Allocate a local UDP port for server */
  232. servfd = listen_dgram ();
  233. assert (servfd != -1);
  234. val = getsockname (servfd, (struct sockaddr *)&addr, &addrlen);
  235. assert (val == 0);
  236. /* Allocate a client socket and connect to server */
  237. fd = socket (addr.ss_family, SOCK_DGRAM, 0);
  238. assert (fd != -1);
  239. /* Send error response */
  240. req_len = stun_usage_bind_create (&agent, &req_msg, req, sizeof(req));
  241. assert (req_len > 0);
  242. val = getsockname (servfd, (struct sockaddr *)&addr, &addrlen);
  243. assert (val == 0);
  244. val = sendto (fd, req, req_len, MSG_DONTWAIT | MSG_NOSIGNAL,
  245. (struct sockaddr *)&addr, addrlen);
  246. assert (val >= 0);
  247. val = recvfrom (servfd, buf, 1000, MSG_DONTWAIT, NULL, 0);
  248. assert (val >= 0);
  249. assert (stun_agent_validate (&agent, &msg, buf, val, NULL, NULL)
  250. == STUN_VALIDATION_SUCCESS);
  251. stun_agent_init_error (&agent, &msg, buf, sizeof (buf),
  252. &msg, STUN_ERROR_SERVER_ERROR);
  253. len = stun_agent_finish_message (&agent, &msg, NULL, 0);
  254. assert (len > 0);
  255. val = getsockname (servfd, (struct sockaddr *)&addr, &addrlen);
  256. assert (val == 0);
  257. val = stun_usage_bind_process (&msg, (struct sockaddr *) &addr, &addrlen,
  258. (struct sockaddr *) &addr, &addrlen);
  259. assert (val == STUN_USAGE_BIND_RETURN_ERROR);
  260. /* Send response with a no mapped address at all */
  261. req_len = stun_usage_bind_create (&agent, &req_msg, req, sizeof(req));
  262. assert (req_len > 0);
  263. val = getsockname (servfd, (struct sockaddr *)&addr, &addrlen);
  264. assert (val == 0);
  265. val = sendto (fd, req, req_len, MSG_DONTWAIT | MSG_NOSIGNAL,
  266. (struct sockaddr *)&addr, addrlen);
  267. assert (val >= 0);
  268. val = recvfrom (servfd, buf, 1000, MSG_DONTWAIT, NULL, 0);
  269. assert (val >= 0);
  270. assert (stun_agent_validate (&agent, &msg, buf, val, NULL, NULL)
  271. == STUN_VALIDATION_SUCCESS);
  272. stun_agent_init_response (&agent, &msg, buf, sizeof (buf), &msg);
  273. len = stun_agent_finish_message (&agent, &msg, NULL, 0);
  274. assert (len > 0);
  275. assert (stun_agent_validate (&agent, &msg, buf, len, NULL, NULL)
  276. == STUN_VALIDATION_SUCCESS);
  277. val = getsockname (servfd, (struct sockaddr *)&addr, &addrlen);
  278. assert (val == 0);
  279. val = stun_usage_bind_process (&msg, (struct sockaddr *) &addr, &addrlen,
  280. (struct sockaddr *) &addr, &addrlen);
  281. assert (val == STUN_USAGE_BIND_RETURN_ERROR);
  282. /* Send old-style response */
  283. req_len = stun_usage_bind_create (&agent, &req_msg, req, sizeof(req));
  284. assert (req_len > 0);
  285. val = getsockname (servfd, (struct sockaddr *)&addr, &addrlen);
  286. assert (val == 0);
  287. val = sendto (fd, req, req_len, MSG_DONTWAIT | MSG_NOSIGNAL,
  288. (struct sockaddr *)&addr, addrlen);
  289. assert (val >= 0);
  290. val = recvfrom (servfd, buf, 1000, MSG_DONTWAIT, NULL, 0);
  291. assert (val >= 0);
  292. assert (stun_agent_validate (&agent, &msg, buf, val, NULL, NULL)
  293. == STUN_VALIDATION_SUCCESS);
  294. stun_agent_init_response (&agent, &msg, buf, sizeof (buf), &msg);
  295. assert (stun_message_append_addr (&msg, STUN_ATTRIBUTE_MAPPED_ADDRESS,
  296. (struct sockaddr *) &addr, addrlen) == STUN_MESSAGE_RETURN_SUCCESS);
  297. len = stun_agent_finish_message (&agent, &msg, NULL, 0);
  298. assert (len > 0);
  299. assert (stun_agent_validate (&agent, &msg, buf, len, NULL, NULL)
  300. == STUN_VALIDATION_SUCCESS);
  301. val = getsockname (servfd, (struct sockaddr *)&addr, &addrlen);
  302. assert (val == 0);
  303. val = stun_usage_bind_process (&msg, (struct sockaddr *) &addr, &addrlen,
  304. (struct sockaddr *) &addr, &addrlen);
  305. assert (val == STUN_USAGE_BIND_RETURN_SUCCESS);
  306. /* End */
  307. close (servfd);
  308. val = close (fd);
  309. assert (val == 0);
  310. }
  311. static void keepalive (void)
  312. {
  313. struct sockaddr_storage addr = {0};
  314. socklen_t addrlen = sizeof (addr);
  315. int val, servfd, fd;
  316. uint8_t buf[STUN_MAX_MESSAGE_SIZE];
  317. size_t len;
  318. StunAgent agent;
  319. StunMessage msg;
  320. uint16_t known_attributes[] = {
  321. STUN_ATTRIBUTE_MAPPED_ADDRESS,
  322. STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS,
  323. STUN_ATTRIBUTE_PRIORITY,
  324. STUN_ATTRIBUTE_USERNAME,
  325. STUN_ATTRIBUTE_MESSAGE_INTEGRITY,
  326. STUN_ATTRIBUTE_ERROR_CODE, 0};
  327. stun_agent_init (&agent, known_attributes,
  328. STUN_COMPATIBILITY_RFC5389, 0);
  329. /* Allocate a local UDP port for server */
  330. servfd = listen_dgram ();
  331. assert (servfd != -1);
  332. val = getsockname (servfd, (struct sockaddr *)&addr, &addrlen);
  333. assert (val == 0);
  334. /* Allocate a client socket and connect to server */
  335. fd = socket (addr.ss_family, SOCK_DGRAM, 0);
  336. assert (fd != -1);
  337. /* Keep alive sending smoke test */
  338. len = stun_usage_bind_keepalive (&agent, &msg, buf, sizeof(buf));
  339. assert (len == 20);
  340. val = sendto (fd, buf, len, MSG_DONTWAIT | MSG_NOSIGNAL,
  341. (struct sockaddr *)&addr, addrlen);
  342. assert (val >= 0);
  343. /* End */
  344. close (servfd);
  345. val = close (fd);
  346. assert (val == 0);
  347. }
  348. static void test (void (*func) (void), const char *name)
  349. {
  350. alarm (30);
  351. printf ("%s test... ", name);
  352. func ();
  353. puts ("OK");
  354. }
  355. int main (void)
  356. {
  357. #ifdef _WIN32
  358. WSADATA w;
  359. WSAStartup(0x0202, &w);
  360. #endif
  361. test (bad_family, "Bad socket family");
  362. test (small_srv_addr, "Too small server address");
  363. test (big_srv_addr, "Too big server address");
  364. test (bad_responses, "Bad responses");
  365. test (responses, "Error responses");
  366. test (keepalive, "Keep alives");
  367. #ifdef HAVE_POLL
  368. test (timeout, "Binding discovery timeout");
  369. #endif
  370. #ifdef _WIN32
  371. WSACleanup();
  372. #endif
  373. return 0;
  374. }