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