nat_auto_api.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  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-auto/nat_auto_api.c
  21. * Routines for NAT auto configuration.
  22. */
  23. #include "platform.h"
  24. #include "gnunet_nat_service.h"
  25. #include "gnunet_nat_auto_service.h"
  26. #include "nat-auto.h"
  27. /**
  28. * Handle to auto-configuration in progress.
  29. */
  30. struct GNUNET_NAT_AUTO_AutoHandle
  31. {
  32. /**
  33. * Configuration we use.
  34. */
  35. const struct GNUNET_CONFIGURATION_Handle *cfg;
  36. /**
  37. * Message queue for communicating with the NAT service.
  38. */
  39. struct GNUNET_MQ_Handle *mq;
  40. /**
  41. * Function called with the result from the autoconfiguration.
  42. */
  43. GNUNET_NAT_AUTO_AutoResultCallback arc;
  44. /**
  45. * Closure for @e arc.
  46. */
  47. void *arc_cls;
  48. };
  49. /**
  50. * Converts `enum GNUNET_NAT_StatusCode` to string
  51. *
  52. * @param err error code to resolve to a string
  53. * @return point to a static string containing the error code
  54. */
  55. const char *
  56. GNUNET_NAT_AUTO_status2string (enum GNUNET_NAT_StatusCode err)
  57. {
  58. switch (err)
  59. {
  60. case GNUNET_NAT_ERROR_SUCCESS:
  61. return _ ("Operation Successful");
  62. case GNUNET_NAT_ERROR_IPC_FAILURE:
  63. return _ ("IPC failure");
  64. case GNUNET_NAT_ERROR_INTERNAL_NETWORK_ERROR:
  65. return _ ("Failure in network subsystem, check permissions.");
  66. case GNUNET_NAT_ERROR_TIMEOUT:
  67. return _ ("Encountered timeout while performing operation");
  68. case GNUNET_NAT_ERROR_NOT_ONLINE:
  69. return _ ("detected that we are offline");
  70. case GNUNET_NAT_ERROR_UPNPC_NOT_FOUND:
  71. return _ ("`upnpc` command not found");
  72. case GNUNET_NAT_ERROR_UPNPC_FAILED:
  73. return _ ("Failed to run `upnpc` command");
  74. case GNUNET_NAT_ERROR_UPNPC_TIMEOUT:
  75. return _ ("`upnpc' command took too long, process killed");
  76. case GNUNET_NAT_ERROR_UPNPC_PORTMAP_FAILED:
  77. return _ ("`upnpc' command failed to establish port mapping");
  78. case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_NOT_FOUND:
  79. return _ ("`external-ip' command not found");
  80. case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_FAILED:
  81. return _ ("Failed to run `external-ip` command");
  82. case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_OUTPUT_INVALID:
  83. return _ ("`external-ip' command output invalid");
  84. case GNUNET_NAT_ERROR_EXTERNAL_IP_ADDRESS_INVALID:
  85. return _ ("no valid address was returned by `external-ip'");
  86. case GNUNET_NAT_ERROR_NO_VALID_IF_IP_COMBO:
  87. return _ ("Could not determine interface with internal/local network address");
  88. case GNUNET_NAT_ERROR_HELPER_NAT_SERVER_NOT_FOUND:
  89. return _ ("No functioning gnunet-helper-nat-server installation found");
  90. case GNUNET_NAT_ERROR_NAT_TEST_START_FAILED:
  91. return _ ("NAT test could not be initialized");
  92. case GNUNET_NAT_ERROR_NAT_TEST_TIMEOUT:
  93. return _ ("NAT test timeout reached");
  94. case GNUNET_NAT_ERROR_NAT_REGISTER_FAILED:
  95. return _ ("could not register NAT");
  96. case GNUNET_NAT_ERROR_HELPER_NAT_CLIENT_NOT_FOUND:
  97. return _ ("No working gnunet-helper-nat-client installation found");
  98. default:
  99. return "unknown status code";
  100. }
  101. }
  102. /**
  103. * Check result from autoconfiguration attempt.
  104. *
  105. * @param cls the `struct GNUNET_NAT_AUTO_AutoHandle`
  106. * @param res the result
  107. * @return #GNUNET_OK if @a res is well-formed (always for now)
  108. */
  109. static int
  110. check_auto_result (void *cls,
  111. const struct GNUNET_NAT_AUTO_AutoconfigResultMessage *res)
  112. {
  113. return GNUNET_OK;
  114. }
  115. /**
  116. * Handle result from autoconfiguration attempt.
  117. *
  118. * @param cls the `struct GNUNET_NAT_AUTO_AutoHandle`
  119. * @param res the result
  120. */
  121. static void
  122. handle_auto_result (void *cls,
  123. const struct GNUNET_NAT_AUTO_AutoconfigResultMessage *res)
  124. {
  125. struct GNUNET_NAT_AUTO_AutoHandle *ah = cls;
  126. size_t left;
  127. struct GNUNET_CONFIGURATION_Handle *cfg;
  128. enum GNUNET_NAT_Type type
  129. = (enum GNUNET_NAT_Type) ntohl (res->type);
  130. enum GNUNET_NAT_StatusCode status
  131. = (enum GNUNET_NAT_StatusCode) ntohl (res->status_code);
  132. left = ntohs (res->header.size) - sizeof (*res);
  133. cfg = GNUNET_CONFIGURATION_create ();
  134. if (GNUNET_OK !=
  135. GNUNET_CONFIGURATION_deserialize (cfg,
  136. (const char *) &res[1],
  137. left,
  138. NULL))
  139. {
  140. GNUNET_break (0);
  141. ah->arc (ah->arc_cls,
  142. NULL,
  143. GNUNET_NAT_ERROR_IPC_FAILURE,
  144. type);
  145. }
  146. else
  147. {
  148. ah->arc (ah->arc_cls,
  149. cfg,
  150. status,
  151. type);
  152. }
  153. GNUNET_CONFIGURATION_destroy (cfg);
  154. GNUNET_NAT_AUTO_autoconfig_cancel (ah);
  155. }
  156. /**
  157. * Handle queue errors by reporting autoconfiguration failure.
  158. *
  159. * @param cls the `struct GNUNET_NAT_AUTO_AutoHandle *`
  160. * @param error details about the error
  161. */
  162. static void
  163. ah_error_handler (void *cls,
  164. enum GNUNET_MQ_Error error)
  165. {
  166. struct GNUNET_NAT_AUTO_AutoHandle *ah = cls;
  167. ah->arc (ah->arc_cls,
  168. NULL,
  169. GNUNET_NAT_ERROR_IPC_FAILURE,
  170. GNUNET_NAT_TYPE_UNKNOWN);
  171. GNUNET_NAT_AUTO_autoconfig_cancel (ah);
  172. }
  173. /**
  174. * Start auto-configuration routine. The transport adapters should
  175. * be stopped while this function is called.
  176. *
  177. * @param cfg initial configuration
  178. * @param cb function to call with autoconfiguration result
  179. * @param cb_cls closure for @a cb
  180. * @return handle to cancel operation
  181. */
  182. struct GNUNET_NAT_AUTO_AutoHandle *
  183. GNUNET_NAT_AUTO_autoconfig_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
  184. GNUNET_NAT_AUTO_AutoResultCallback cb,
  185. void *cb_cls)
  186. {
  187. struct GNUNET_NAT_AUTO_AutoHandle *ah = GNUNET_new (struct GNUNET_NAT_AUTO_AutoHandle);
  188. struct GNUNET_MQ_MessageHandler handlers[] = {
  189. GNUNET_MQ_hd_var_size (auto_result,
  190. GNUNET_MESSAGE_TYPE_NAT_AUTO_CFG_RESULT,
  191. struct GNUNET_NAT_AUTO_AutoconfigResultMessage,
  192. ah),
  193. GNUNET_MQ_handler_end ()
  194. };
  195. struct GNUNET_MQ_Envelope *env;
  196. struct GNUNET_NAT_AUTO_AutoconfigRequestMessage *req;
  197. char *buf;
  198. size_t size;
  199. buf = GNUNET_CONFIGURATION_serialize (cfg,
  200. &size);
  201. if (size > GNUNET_MAX_MESSAGE_SIZE - sizeof (*req))
  202. {
  203. GNUNET_break (0);
  204. GNUNET_free (buf);
  205. GNUNET_free (ah);
  206. return NULL;
  207. }
  208. ah->arc = cb;
  209. ah->arc_cls = cb_cls;
  210. ah->mq = GNUNET_CLIENT_connect (cfg,
  211. "nat",
  212. handlers,
  213. &ah_error_handler,
  214. ah);
  215. if (NULL == ah->mq)
  216. {
  217. GNUNET_break (0);
  218. GNUNET_free (buf);
  219. GNUNET_free (ah);
  220. return NULL;
  221. }
  222. env = GNUNET_MQ_msg_extra (req,
  223. size,
  224. GNUNET_MESSAGE_TYPE_NAT_AUTO_REQUEST_CFG);
  225. GNUNET_memcpy (&req[1],
  226. buf,
  227. size);
  228. GNUNET_free (buf);
  229. GNUNET_MQ_send (ah->mq,
  230. env);
  231. return ah;
  232. }
  233. /**
  234. * Abort autoconfiguration.
  235. *
  236. * @param ah handle for operation to abort
  237. */
  238. void
  239. GNUNET_NAT_AUTO_autoconfig_cancel (struct GNUNET_NAT_AUTO_AutoHandle *ah)
  240. {
  241. GNUNET_MQ_destroy (ah->mq);
  242. GNUNET_free (ah);
  243. }
  244. /* end of nat_api_auto.c */