nat_api.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709
  1. /*
  2. This file is part of GNUnet.
  3. Copyright (C) 2007-2017 GNUnet e.V.
  4. GNUnet is free software: you can redistribute it and/or modify it
  5. under the terms of the GNU Affero General Public License as published
  6. by the Free Software Foundation, either version 3 of the License,
  7. or (at your option) any later version.
  8. GNUnet is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Affero General Public License for more details.
  12. You should have received a copy of the GNU Affero General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. SPDX-License-Identifier: AGPL3.0-or-later
  15. */
  16. /**
  17. * @author Christian Grothoff
  18. * @author Milan Bouchet-Valat
  19. *
  20. * @file nat/nat_api.c
  21. * Service for handling UPnP and NAT-PMP port forwarding
  22. * and external IP address retrieval
  23. */
  24. #include "platform.h"
  25. #include "gnunet_nat_service.h"
  26. #include "nat.h"
  27. #include "nat_stun.h"
  28. /**
  29. * Entry in DLL of addresses of this peer.
  30. */
  31. struct AddrEntry
  32. {
  33. /**
  34. * DLL.
  35. */
  36. struct AddrEntry *next;
  37. /**
  38. * DLL.
  39. */
  40. struct AddrEntry *prev;
  41. /**
  42. * Place where the application can store data (on add,
  43. * and retrieve on remove).
  44. */
  45. void *app_ctx;
  46. /**
  47. * Address class of the address.
  48. */
  49. enum GNUNET_NAT_AddressClass ac;
  50. /**
  51. * Number of bytes that follow.
  52. */
  53. socklen_t addrlen;
  54. };
  55. /**
  56. * Handle for active NAT registrations.
  57. */
  58. struct GNUNET_NAT_Handle
  59. {
  60. /**
  61. * Configuration we use.
  62. */
  63. const struct GNUNET_CONFIGURATION_Handle *cfg;
  64. /**
  65. * Message queue for communicating with the NAT service.
  66. */
  67. struct GNUNET_MQ_Handle *mq;
  68. /**
  69. * Our registration message.
  70. */
  71. struct GNUNET_MessageHeader *reg;
  72. /**
  73. * Head of address DLL.
  74. */
  75. struct AddrEntry *ae_head;
  76. /**
  77. * Tail of address DLL.
  78. */
  79. struct AddrEntry *ae_tail;
  80. /**
  81. * Function to call when our addresses change.
  82. */
  83. GNUNET_NAT_AddressCallback address_callback;
  84. /**
  85. * Function to call when another peer requests connection reversal.
  86. */
  87. GNUNET_NAT_ReversalCallback reversal_callback;
  88. /**
  89. * Closure for the various callbacks.
  90. */
  91. void *callback_cls;
  92. /**
  93. * Task scheduled to reconnect to the service.
  94. */
  95. struct GNUNET_SCHEDULER_Task *reconnect_task;
  96. /**
  97. * How long to wait until we reconnect.
  98. */
  99. struct GNUNET_TIME_Relative reconnect_delay;
  100. };
  101. /**
  102. * Task to connect to the NAT service.
  103. *
  104. * @param cls our `struct GNUNET_NAT_Handle *`
  105. */
  106. static void
  107. do_connect (void *cls);
  108. /**
  109. * Task to connect to the NAT service.
  110. *
  111. * @param nh handle to reconnect
  112. */
  113. static void
  114. reconnect (struct GNUNET_NAT_Handle *nh)
  115. {
  116. struct AddrEntry *ae;
  117. if (NULL != nh->mq)
  118. {
  119. GNUNET_MQ_destroy (nh->mq);
  120. nh->mq = NULL;
  121. }
  122. while (NULL != (ae = nh->ae_head))
  123. {
  124. GNUNET_CONTAINER_DLL_remove (nh->ae_head, nh->ae_tail, ae);
  125. nh->address_callback (nh->callback_cls,
  126. &ae->app_ctx,
  127. GNUNET_NO,
  128. ae->ac,
  129. (const struct sockaddr *) &ae[1],
  130. ae->addrlen);
  131. GNUNET_free (ae);
  132. }
  133. nh->reconnect_delay = GNUNET_TIME_STD_BACKOFF (nh->reconnect_delay);
  134. nh->reconnect_task =
  135. GNUNET_SCHEDULER_add_delayed (nh->reconnect_delay, &do_connect, nh);
  136. }
  137. /**
  138. * Check connection reversal request.
  139. *
  140. * @param cls our `struct GNUNET_NAT_Handle`
  141. * @param crm the message
  142. * @return #GNUNET_OK if @a crm is well-formed
  143. */
  144. static int
  145. check_connection_reversal_request (
  146. void *cls,
  147. const struct GNUNET_NAT_ConnectionReversalRequestedMessage *crm)
  148. {
  149. if (ntohs (crm->header.size) != sizeof(*crm) + sizeof(struct sockaddr_in))
  150. {
  151. GNUNET_break (0);
  152. return GNUNET_SYSERR;
  153. }
  154. return GNUNET_OK;
  155. }
  156. /**
  157. * Handle connection reversal request.
  158. *
  159. * @param cls our `struct GNUNET_NAT_Handle`
  160. * @param crm the message
  161. */
  162. static void
  163. handle_connection_reversal_request (
  164. void *cls,
  165. const struct GNUNET_NAT_ConnectionReversalRequestedMessage *crm)
  166. {
  167. struct GNUNET_NAT_Handle *nh = cls;
  168. nh->reversal_callback (nh->callback_cls,
  169. (const struct sockaddr *) &crm[1],
  170. sizeof(struct sockaddr_in));
  171. }
  172. /**
  173. * Check address change notification.
  174. *
  175. * @param cls our `struct GNUNET_NAT_Handle`
  176. * @param acn the message
  177. * @return #GNUNET_OK if @a crm is well-formed
  178. */
  179. static int
  180. check_address_change_notification (
  181. void *cls,
  182. const struct GNUNET_NAT_AddressChangeNotificationMessage *acn)
  183. {
  184. size_t alen = ntohs (acn->header.size) - sizeof(*acn);
  185. switch (alen)
  186. {
  187. case sizeof(struct sockaddr_in): {
  188. const struct sockaddr_in *s4 = (const struct sockaddr_in *) &acn[1];
  189. if (AF_INET != s4->sin_family)
  190. {
  191. GNUNET_break (0);
  192. return GNUNET_SYSERR;
  193. }
  194. }
  195. break;
  196. case sizeof(struct sockaddr_in6): {
  197. const struct sockaddr_in6 *s6 = (const struct sockaddr_in6 *) &acn[1];
  198. if (AF_INET6 != s6->sin6_family)
  199. {
  200. GNUNET_break (0);
  201. return GNUNET_SYSERR;
  202. }
  203. }
  204. break;
  205. default:
  206. GNUNET_break (0);
  207. return GNUNET_SYSERR;
  208. }
  209. return GNUNET_OK;
  210. }
  211. /**
  212. * Handle connection reversal request.
  213. *
  214. * @param cls our `struct GNUNET_NAT_Handle`
  215. * @param acn the message
  216. */
  217. static void
  218. handle_address_change_notification (
  219. void *cls,
  220. const struct GNUNET_NAT_AddressChangeNotificationMessage *acn)
  221. {
  222. struct GNUNET_NAT_Handle *nh = cls;
  223. size_t alen = ntohs (acn->header.size) - sizeof(*acn);
  224. const struct sockaddr *sa = (const struct sockaddr *) &acn[1];
  225. enum GNUNET_NAT_AddressClass ac;
  226. struct AddrEntry *ae;
  227. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  228. "Received address change notification\n");
  229. ac = (enum GNUNET_NAT_AddressClass) ntohl (acn->addr_class);
  230. if (GNUNET_YES == ntohl (acn->add_remove))
  231. {
  232. ae = GNUNET_malloc (sizeof(*ae) + alen);
  233. ae->ac = ac;
  234. ae->addrlen = alen;
  235. GNUNET_memcpy (&ae[1], sa, alen);
  236. GNUNET_CONTAINER_DLL_insert (nh->ae_head, nh->ae_tail, ae);
  237. nh->address_callback (nh->callback_cls,
  238. &ae->app_ctx,
  239. ntohl (acn->add_remove),
  240. ac,
  241. sa,
  242. alen);
  243. }
  244. else
  245. {
  246. for (ae = nh->ae_head; NULL != ae; ae = ae->next)
  247. if ((ae->addrlen == alen) && (0 == memcmp (&ae[1], sa, alen)))
  248. break;
  249. if (NULL == ae)
  250. {
  251. GNUNET_break (0);
  252. reconnect (nh);
  253. return;
  254. }
  255. GNUNET_CONTAINER_DLL_remove (nh->ae_head, nh->ae_tail, ae);
  256. nh->address_callback (nh->callback_cls,
  257. &ae->app_ctx,
  258. ntohl (acn->add_remove),
  259. ac,
  260. sa,
  261. alen);
  262. GNUNET_free (ae);
  263. }
  264. }
  265. /**
  266. * Handle queue errors by reconnecting to NAT.
  267. *
  268. * @param cls the `struct GNUNET_NAT_Handle *`
  269. * @param error details about the error
  270. */
  271. static void
  272. mq_error_handler (void *cls, enum GNUNET_MQ_Error error)
  273. {
  274. struct GNUNET_NAT_Handle *nh = cls;
  275. reconnect (nh);
  276. }
  277. /**
  278. * Task to connect to the NAT service.
  279. *
  280. * @param cls our `struct GNUNET_NAT_Handle *`
  281. */
  282. static void
  283. do_connect (void *cls)
  284. {
  285. struct GNUNET_NAT_Handle *nh = cls;
  286. struct GNUNET_MQ_MessageHandler handlers[] =
  287. { GNUNET_MQ_hd_var_size (connection_reversal_request,
  288. GNUNET_MESSAGE_TYPE_NAT_CONNECTION_REVERSAL_REQUESTED,
  289. struct
  290. GNUNET_NAT_ConnectionReversalRequestedMessage,
  291. nh),
  292. GNUNET_MQ_hd_var_size (address_change_notification,
  293. GNUNET_MESSAGE_TYPE_NAT_ADDRESS_CHANGE,
  294. struct GNUNET_NAT_AddressChangeNotificationMessage,
  295. nh),
  296. GNUNET_MQ_handler_end () };
  297. struct GNUNET_MQ_Envelope *env;
  298. nh->reconnect_task = NULL;
  299. nh->mq =
  300. GNUNET_CLIENT_connect (nh->cfg, "nat", handlers, &mq_error_handler, nh);
  301. if (NULL == nh->mq)
  302. {
  303. reconnect (nh);
  304. return;
  305. }
  306. env = GNUNET_MQ_msg_copy (nh->reg);
  307. GNUNET_MQ_send (nh->mq, env);
  308. }
  309. /**
  310. * Attempt to enable port redirection and detect public IP address
  311. * contacting UPnP or NAT-PMP routers on the local network. Use @a
  312. * addr to specify to which of the local host's addresses should the
  313. * external port be mapped. The port is taken from the corresponding
  314. * sockaddr_in[6] field. The NAT module should call the given @a
  315. * address_callback for any 'plausible' external address.
  316. *
  317. * @param cfg configuration to use
  318. * @param config_section name of the configuration section for optionsx
  319. * @param proto protocol this is about, IPPROTO_TCP or IPPROTO_UDP
  320. * @param num_addrs number of addresses in @a addrs
  321. * @param addrs list of local addresses packets should be redirected to
  322. * @param addrlens actual lengths of the addresses in @a addrs
  323. * @param address_callback function to call everytime the public IP address changes
  324. * @param reversal_callback function to call if someone wants connection reversal from us,
  325. * NULL if connection reversal is not supported
  326. * @param callback_cls closure for callbacks
  327. * @return NULL on error, otherwise handle that can be used to unregister
  328. */
  329. struct GNUNET_NAT_Handle *
  330. GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg,
  331. const char *config_section,
  332. uint8_t proto,
  333. unsigned int num_addrs,
  334. const struct sockaddr **addrs,
  335. const socklen_t *addrlens,
  336. GNUNET_NAT_AddressCallback address_callback,
  337. GNUNET_NAT_ReversalCallback reversal_callback,
  338. void *callback_cls)
  339. {
  340. struct GNUNET_NAT_Handle *nh;
  341. struct GNUNET_NAT_RegisterMessage *rm;
  342. size_t len;
  343. size_t str_len;
  344. char *off;
  345. len = 0;
  346. for (unsigned int i = 0; i < num_addrs; i++)
  347. len += addrlens[i];
  348. str_len = strlen (config_section) + 1;
  349. len += str_len;
  350. if ((len > GNUNET_MAX_MESSAGE_SIZE - sizeof(*rm)) ||
  351. (num_addrs > UINT16_MAX))
  352. {
  353. GNUNET_break (0);
  354. return NULL;
  355. }
  356. rm = GNUNET_malloc (sizeof(*rm) + len);
  357. rm->header.size = htons (sizeof(*rm) + len);
  358. rm->header.type = htons (GNUNET_MESSAGE_TYPE_NAT_REGISTER);
  359. rm->flags = GNUNET_NAT_RF_NONE;
  360. if (NULL != address_callback)
  361. rm->flags |= GNUNET_NAT_RF_ADDRESSES;
  362. if (NULL != reversal_callback)
  363. rm->flags |= GNUNET_NAT_RF_REVERSAL;
  364. rm->proto = proto;
  365. rm->str_len = htons (str_len);
  366. rm->num_addrs = htons ((uint16_t) num_addrs);
  367. off = (char *) &rm[1];
  368. for (unsigned int i = 0; i < num_addrs; i++)
  369. {
  370. switch (addrs[i]->sa_family)
  371. {
  372. case AF_INET:
  373. if (sizeof(struct sockaddr_in) != addrlens[i])
  374. {
  375. GNUNET_break (0);
  376. GNUNET_free (rm);
  377. return NULL;
  378. }
  379. break;
  380. case AF_INET6:
  381. if (sizeof(struct sockaddr_in6) != addrlens[i])
  382. {
  383. GNUNET_break (0);
  384. GNUNET_free (rm);
  385. return NULL;
  386. }
  387. break;
  388. #if AF_UNIX
  389. case AF_UNIX:
  390. if (sizeof(struct sockaddr_un) != addrlens[i])
  391. {
  392. GNUNET_break (0);
  393. GNUNET_free (rm);
  394. return NULL;
  395. }
  396. break;
  397. #endif
  398. default:
  399. GNUNET_break (0);
  400. GNUNET_free (rm);
  401. return NULL;
  402. }
  403. GNUNET_memcpy (off, addrs[i], addrlens[i]);
  404. off += addrlens[i];
  405. }
  406. GNUNET_memcpy (off, config_section, str_len);
  407. nh = GNUNET_new (struct GNUNET_NAT_Handle);
  408. nh->reg = &rm->header;
  409. nh->cfg = cfg;
  410. nh->address_callback = address_callback;
  411. nh->reversal_callback = reversal_callback;
  412. nh->callback_cls = callback_cls;
  413. do_connect (nh);
  414. return nh;
  415. }
  416. /**
  417. * Check if an incoming message is a STUN message.
  418. *
  419. * @param data the packet
  420. * @param len the length of the packet in @a data
  421. * @return #GNUNET_YES if @a data is a STUN packet,
  422. * #GNUNET_NO if the packet is invalid (not a stun packet)
  423. */
  424. static int
  425. test_stun_packet (const void *data, size_t len)
  426. {
  427. const struct stun_header *hdr;
  428. const struct stun_attr *attr;
  429. uint32_t advertised_message_size;
  430. uint32_t message_magic_cookie;
  431. /* On entry, 'len' is the length of the UDP payload. After the
  432. * initial checks it becomes the size of unprocessed options,
  433. * while 'data' is advanced accordingly.
  434. */
  435. if (len < sizeof(struct stun_header))
  436. {
  437. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  438. "STUN packet too short (only %d, wanting at least %d)\n",
  439. (int) len,
  440. (int) sizeof(struct stun_header));
  441. return GNUNET_NO;
  442. }
  443. hdr = (const struct stun_header *) data;
  444. /* Skip header as it is already in hdr */
  445. len -= sizeof(struct stun_header);
  446. data += sizeof(struct stun_header);
  447. /* len as advertised in the message */
  448. advertised_message_size = ntohs (hdr->msglen);
  449. message_magic_cookie = ntohl (hdr->magic);
  450. /* Compare if the cookie match */
  451. if (STUN_MAGIC_COOKIE != message_magic_cookie)
  452. {
  453. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Invalid magic cookie for STUN\n");
  454. return GNUNET_NO;
  455. }
  456. if (advertised_message_size > len)
  457. {
  458. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  459. "Scrambled STUN packet length (got %d, expecting %d)\n",
  460. advertised_message_size,
  461. (int) len);
  462. return GNUNET_NO;
  463. }
  464. len = advertised_message_size;
  465. while (len > 0)
  466. {
  467. if (len < sizeof(struct stun_attr))
  468. {
  469. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  470. "Attribute too short in STUN packet (got %d, expecting %d)\n",
  471. (int) len,
  472. (int) sizeof(struct stun_attr));
  473. return GNUNET_NO;
  474. }
  475. attr = (const struct stun_attr *) data;
  476. /* compute total attribute length */
  477. advertised_message_size = ntohs (attr->len) + sizeof(struct stun_attr);
  478. /* Check if we still have space in our buffer */
  479. if (advertised_message_size > len)
  480. {
  481. GNUNET_log (
  482. GNUNET_ERROR_TYPE_DEBUG,
  483. "Inconsistent Attribute (length %d exceeds remaining msg len %d)\n",
  484. advertised_message_size,
  485. (int) len);
  486. return GNUNET_NO;
  487. }
  488. data += advertised_message_size;
  489. len -= advertised_message_size;
  490. }
  491. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  492. "STUN Packet, msg %04x, length: %d\n",
  493. ntohs (hdr->msgtype),
  494. advertised_message_size);
  495. return GNUNET_OK;
  496. }
  497. /**
  498. * Handle an incoming STUN message. This function is useful as
  499. * some GNUnet service may be listening on a UDP port and might
  500. * thus receive STUN messages while trying to receive other data.
  501. * In this case, this function can be used to process replies
  502. * to STUN requests.
  503. *
  504. * The function does some basic sanity checks on packet size and
  505. * content, try to extract a bit of information.
  506. *
  507. * At the moment this only processes BIND requests, and returns the
  508. * externally visible address of the request to the rest of the
  509. * NAT logic.
  510. *
  511. * @param nh handle to the NAT service
  512. * @param sender_addr address from which we got @a data
  513. * @param sender_addr_len number of bytes in @a sender_addr
  514. * @param data the packet
  515. * @param data_size number of bytes in @a data
  516. * @return #GNUNET_OK on success
  517. * #GNUNET_NO if the packet is not a STUN packet
  518. * #GNUNET_SYSERR on internal error handling the packet
  519. */
  520. int
  521. GNUNET_NAT_stun_handle_packet (struct GNUNET_NAT_Handle *nh,
  522. const struct sockaddr *sender_addr,
  523. size_t sender_addr_len,
  524. const void *data,
  525. size_t data_size)
  526. {
  527. struct GNUNET_MQ_Envelope *env;
  528. struct GNUNET_NAT_HandleStunMessage *hsn;
  529. char *buf;
  530. if (GNUNET_YES != test_stun_packet (data, data_size))
  531. return GNUNET_NO;
  532. if (NULL == nh->mq)
  533. return GNUNET_SYSERR;
  534. env = GNUNET_MQ_msg_extra (hsn,
  535. data_size + sender_addr_len,
  536. GNUNET_MESSAGE_TYPE_NAT_HANDLE_STUN);
  537. hsn->sender_addr_size = htons ((uint16_t) sender_addr_len);
  538. hsn->payload_size = htons ((uint16_t) data_size);
  539. buf = (char *) &hsn[1];
  540. GNUNET_memcpy (buf, sender_addr, sender_addr_len);
  541. buf += sender_addr_len;
  542. GNUNET_memcpy (buf, data, data_size);
  543. GNUNET_MQ_send (nh->mq, env);
  544. return GNUNET_OK;
  545. }
  546. /**
  547. * Test if the given address is (currently) a plausible IP address for
  548. * this peer. Mostly a convenience function so that clients do not
  549. * have to explicitly track all IPs that the #GNUNET_NAT_AddressCallback
  550. * has returned so far.
  551. *
  552. * @param nh the handle returned by register
  553. * @param addr IP address to test (IPv4 or IPv6)
  554. * @param addrlen number of bytes in @a addr
  555. * @return #GNUNET_YES if the address is plausible,
  556. * #GNUNET_NO if the address is not plausible,
  557. * #GNUNET_SYSERR if the address is malformed
  558. */
  559. int
  560. GNUNET_NAT_test_address (struct GNUNET_NAT_Handle *nh,
  561. const void *addr,
  562. socklen_t addrlen)
  563. {
  564. struct AddrEntry *ae;
  565. if ((addrlen != sizeof(struct sockaddr_in)) &&
  566. (addrlen != sizeof(struct sockaddr_in6)))
  567. {
  568. GNUNET_break (0);
  569. return GNUNET_SYSERR;
  570. }
  571. for (ae = nh->ae_head; NULL != ae; ae = ae->next)
  572. if ((addrlen == ae->addrlen) && (0 == memcmp (addr, &ae[1], addrlen)))
  573. return GNUNET_YES;
  574. return GNUNET_NO;
  575. }
  576. /**
  577. * We learned about a peer (possibly behind NAT) so run the
  578. * gnunet-nat-client to send dummy ICMP responses to cause
  579. * that peer to connect to us (connection reversal).
  580. *
  581. * @param nh handle (used for configuration)
  582. * @param local_sa our local address of the peer (IPv4-only)
  583. * @param remote_sa the remote address of the peer (IPv4-only)
  584. * @return #GNUNET_SYSERR on error,
  585. * #GNUNET_NO if connection reversal is unavailable,
  586. * #GNUNET_OK otherwise (presumably in progress)
  587. */
  588. int
  589. GNUNET_NAT_request_reversal (struct GNUNET_NAT_Handle *nh,
  590. const struct sockaddr_in *local_sa,
  591. const struct sockaddr_in *remote_sa)
  592. {
  593. struct GNUNET_MQ_Envelope *env;
  594. struct GNUNET_NAT_RequestConnectionReversalMessage *req;
  595. char *buf;
  596. if (NULL == nh->mq)
  597. return GNUNET_SYSERR;
  598. GNUNET_break (AF_INET == local_sa->sin_family);
  599. GNUNET_break (AF_INET == remote_sa->sin_family);
  600. env =
  601. GNUNET_MQ_msg_extra (req,
  602. 2 * sizeof(struct sockaddr_in),
  603. GNUNET_MESSAGE_TYPE_NAT_REQUEST_CONNECTION_REVERSAL);
  604. req->local_addr_size = htons (sizeof(struct sockaddr_in));
  605. req->remote_addr_size = htons (sizeof(struct sockaddr_in));
  606. buf = (char *) &req[1];
  607. GNUNET_memcpy (buf, local_sa, sizeof(struct sockaddr_in));
  608. buf += sizeof(struct sockaddr_in);
  609. GNUNET_memcpy (buf, remote_sa, sizeof(struct sockaddr_in));
  610. GNUNET_MQ_send (nh->mq, env);
  611. return GNUNET_OK;
  612. }
  613. /**
  614. * Stop port redirection and public IP address detection for the given
  615. * handle. This frees the handle, after having sent the needed
  616. * commands to close open ports.
  617. *
  618. * @param nh the handle to stop
  619. */
  620. void
  621. GNUNET_NAT_unregister (struct GNUNET_NAT_Handle *nh)
  622. {
  623. if (NULL != nh->mq)
  624. {
  625. GNUNET_MQ_destroy (nh->mq);
  626. nh->mq = NULL;
  627. }
  628. if (NULL != nh->reconnect_task)
  629. {
  630. GNUNET_SCHEDULER_cancel (nh->reconnect_task);
  631. nh->reconnect_task = NULL;
  632. }
  633. GNUNET_free (nh->reg);
  634. GNUNET_free (nh);
  635. }
  636. /* end of nat_api.c */