uncrustify as demanded.
[oweals/gnunet.git] / src / nat-auto / nat_auto_api.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2007-2017 GNUnet e.V.
4
5      GNUnet is free software: you can redistribute it and/or modify it
6      under the terms of the GNU Affero General Public License as published
7      by the Free Software Foundation, either version 3 of the License,
8      or (at your option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      Affero General Public License for more details.
14
15      You should have received a copy of the GNU Affero General Public License
16      along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18      SPDX-License-Identifier: AGPL3.0-or-later
19  */
20
21 /**
22  * @author Christian Grothoff
23  * @author Milan Bouchet-Valat
24  *
25  * @file nat-auto/nat_auto_api.c
26  * Routines for NAT auto configuration.
27  */
28 #include "platform.h"
29 #include "gnunet_nat_service.h"
30 #include "gnunet_nat_auto_service.h"
31 #include "nat-auto.h"
32
33
34
35 /**
36  * Handle to auto-configuration in progress.
37  */
38 struct GNUNET_NAT_AUTO_AutoHandle {
39   /**
40    * Configuration we use.
41    */
42   const struct GNUNET_CONFIGURATION_Handle *cfg;
43
44   /**
45    * Message queue for communicating with the NAT service.
46    */
47   struct GNUNET_MQ_Handle *mq;
48
49   /**
50    * Function called with the result from the autoconfiguration.
51    */
52   GNUNET_NAT_AUTO_AutoResultCallback arc;
53
54   /**
55    * Closure for @e arc.
56    */
57   void *arc_cls;
58 };
59
60
61 /**
62  * Converts `enum GNUNET_NAT_StatusCode` to string
63  *
64  * @param err error code to resolve to a string
65  * @return point to a static string containing the error code
66  */
67 const char *
68 GNUNET_NAT_AUTO_status2string(enum GNUNET_NAT_StatusCode err)
69 {
70   switch (err)
71     {
72     case GNUNET_NAT_ERROR_SUCCESS:
73       return _("Operation Successful");
74
75     case GNUNET_NAT_ERROR_IPC_FAILURE:
76       return _("IPC failure");
77
78     case GNUNET_NAT_ERROR_INTERNAL_NETWORK_ERROR:
79       return _("Failure in network subsystem, check permissions.");
80
81     case GNUNET_NAT_ERROR_TIMEOUT:
82       return _("Encountered timeout while performing operation");
83
84     case GNUNET_NAT_ERROR_NOT_ONLINE:
85       return _("detected that we are offline");
86
87     case GNUNET_NAT_ERROR_UPNPC_NOT_FOUND:
88       return _("`upnpc` command not found");
89
90     case GNUNET_NAT_ERROR_UPNPC_FAILED:
91       return _("Failed to run `upnpc` command");
92
93     case GNUNET_NAT_ERROR_UPNPC_TIMEOUT:
94       return _("`upnpc' command took too long, process killed");
95
96     case GNUNET_NAT_ERROR_UPNPC_PORTMAP_FAILED:
97       return _("`upnpc' command failed to establish port mapping");
98
99     case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_NOT_FOUND:
100       return _("`external-ip' command not found");
101
102     case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_FAILED:
103       return _("Failed to run `external-ip` command");
104
105     case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_OUTPUT_INVALID:
106       return _("`external-ip' command output invalid");
107
108     case GNUNET_NAT_ERROR_EXTERNAL_IP_ADDRESS_INVALID:
109       return _("no valid address was returned by `external-ip'");
110
111     case GNUNET_NAT_ERROR_NO_VALID_IF_IP_COMBO:
112       return _("Could not determine interface with internal/local network address");
113
114     case GNUNET_NAT_ERROR_HELPER_NAT_SERVER_NOT_FOUND:
115       return _("No functioning gnunet-helper-nat-server installation found");
116
117     case GNUNET_NAT_ERROR_NAT_TEST_START_FAILED:
118       return _("NAT test could not be initialized");
119
120     case GNUNET_NAT_ERROR_NAT_TEST_TIMEOUT:
121       return _("NAT test timeout reached");
122
123     case GNUNET_NAT_ERROR_NAT_REGISTER_FAILED:
124       return _("could not register NAT");
125
126     case GNUNET_NAT_ERROR_HELPER_NAT_CLIENT_NOT_FOUND:
127       return _("No working gnunet-helper-nat-client installation found");
128
129     default:
130       return "unknown status code";
131     }
132 }
133
134
135 /**
136  * Check result from autoconfiguration attempt.
137  *
138  * @param cls the `struct GNUNET_NAT_AUTO_AutoHandle`
139  * @param res the result
140  * @return #GNUNET_OK if @a res is well-formed (always for now)
141  */
142 static int
143 check_auto_result(void *cls,
144                   const struct GNUNET_NAT_AUTO_AutoconfigResultMessage *res)
145 {
146   return GNUNET_OK;
147 }
148
149
150 /**
151  * Handle result from autoconfiguration attempt.
152  *
153  * @param cls the `struct GNUNET_NAT_AUTO_AutoHandle`
154  * @param res the result
155  */
156 static void
157 handle_auto_result(void *cls,
158                    const struct GNUNET_NAT_AUTO_AutoconfigResultMessage *res)
159 {
160   struct GNUNET_NAT_AUTO_AutoHandle *ah = cls;
161   size_t left;
162   struct GNUNET_CONFIGURATION_Handle *cfg;
163   enum GNUNET_NAT_Type type
164     = (enum GNUNET_NAT_Type)ntohl(res->type);
165   enum GNUNET_NAT_StatusCode status
166     = (enum GNUNET_NAT_StatusCode)ntohl(res->status_code);
167
168   left = ntohs(res->header.size) - sizeof(*res);
169   cfg = GNUNET_CONFIGURATION_create();
170   if (GNUNET_OK !=
171       GNUNET_CONFIGURATION_deserialize(cfg,
172                                        (const char *)&res[1],
173                                        left,
174                                        NULL))
175     {
176       GNUNET_break(0);
177       ah->arc(ah->arc_cls,
178               NULL,
179               GNUNET_NAT_ERROR_IPC_FAILURE,
180               type);
181     }
182   else
183     {
184       ah->arc(ah->arc_cls,
185               cfg,
186               status,
187               type);
188     }
189   GNUNET_CONFIGURATION_destroy(cfg);
190   GNUNET_NAT_AUTO_autoconfig_cancel(ah);
191 }
192
193
194 /**
195  * Handle queue errors by reporting autoconfiguration failure.
196  *
197  * @param cls the `struct GNUNET_NAT_AUTO_AutoHandle *`
198  * @param error details about the error
199  */
200 static void
201 ah_error_handler(void *cls,
202                  enum GNUNET_MQ_Error error)
203 {
204   struct GNUNET_NAT_AUTO_AutoHandle *ah = cls;
205
206   ah->arc(ah->arc_cls,
207           NULL,
208           GNUNET_NAT_ERROR_IPC_FAILURE,
209           GNUNET_NAT_TYPE_UNKNOWN);
210   GNUNET_NAT_AUTO_autoconfig_cancel(ah);
211 }
212
213
214 /**
215  * Start auto-configuration routine.  The transport adapters should
216  * be stopped while this function is called.
217  *
218  * @param cfg initial configuration
219  * @param cb function to call with autoconfiguration result
220  * @param cb_cls closure for @a cb
221  * @return handle to cancel operation
222  */
223 struct GNUNET_NAT_AUTO_AutoHandle *
224 GNUNET_NAT_AUTO_autoconfig_start(const struct GNUNET_CONFIGURATION_Handle *cfg,
225                                  GNUNET_NAT_AUTO_AutoResultCallback cb,
226                                  void *cb_cls)
227 {
228   struct GNUNET_NAT_AUTO_AutoHandle *ah = GNUNET_new(struct GNUNET_NAT_AUTO_AutoHandle);
229   struct GNUNET_MQ_MessageHandler handlers[] = {
230     GNUNET_MQ_hd_var_size(auto_result,
231                           GNUNET_MESSAGE_TYPE_NAT_AUTO_CFG_RESULT,
232                           struct GNUNET_NAT_AUTO_AutoconfigResultMessage,
233                           ah),
234     GNUNET_MQ_handler_end()
235   };
236   struct GNUNET_MQ_Envelope *env;
237   struct GNUNET_NAT_AUTO_AutoconfigRequestMessage *req;
238   char *buf;
239   size_t size;
240
241   buf = GNUNET_CONFIGURATION_serialize(cfg,
242                                        &size);
243   if (size > GNUNET_MAX_MESSAGE_SIZE - sizeof(*req))
244     {
245       GNUNET_break(0);
246       GNUNET_free(buf);
247       GNUNET_free(ah);
248       return NULL;
249     }
250   ah->arc = cb;
251   ah->arc_cls = cb_cls;
252   ah->mq = GNUNET_CLIENT_connect(cfg,
253                                  "nat",
254                                  handlers,
255                                  &ah_error_handler,
256                                  ah);
257   if (NULL == ah->mq)
258     {
259       GNUNET_break(0);
260       GNUNET_free(buf);
261       GNUNET_free(ah);
262       return NULL;
263     }
264   env = GNUNET_MQ_msg_extra(req,
265                             size,
266                             GNUNET_MESSAGE_TYPE_NAT_AUTO_REQUEST_CFG);
267   GNUNET_memcpy(&req[1],
268                 buf,
269                 size);
270   GNUNET_free(buf);
271   GNUNET_MQ_send(ah->mq,
272                  env);
273   return ah;
274 }
275
276
277 /**
278  * Abort autoconfiguration.
279  *
280  * @param ah handle for operation to abort
281  */
282 void
283 GNUNET_NAT_AUTO_autoconfig_cancel(struct GNUNET_NAT_AUTO_AutoHandle *ah)
284 {
285   GNUNET_MQ_destroy(ah->mq);
286   GNUNET_free(ah);
287 }
288
289 /* end of nat_api_auto.c */