GNUnet  0.10.x
gnunet-daemon-testbed-underlay.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet
3  Copyright (C) 2008--2013 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 
29 #include "platform.h"
30 #include "gnunet_util_lib.h"
33 #include "gnunet_ats_service.h"
34 #include "gnunet_testing_lib.h"
35 #include <sqlite3.h>
36 
40 #define LOG(type, ...) \
41  GNUNET_log(type, __VA_ARGS__)
42 
46 #define DEBUG(...) \
47  LOG(GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
48 
54 #define LOG_SQLITE(db, msg, level, cmd) \
55  do { \
56  GNUNET_log_from(level, "sqlite", _("`%s' failed at %s:%d with error: %s\n"), \
57  cmd, __FILE__, __LINE__, sqlite3_errmsg(db)); \
58  if (msg != NULL) \
59  GNUNET_asprintf (msg, _("`%s' failed at %s:%u with error: %s"), cmd, \
60  __FILE__, __LINE__, sqlite3_errmsg(db)); \
61  } while (0)
62 
63 
68 
72 static struct sqlite3 *db;
73 
79 
84 
89 
93 static void *hostkeys_data;
94 
99 
103 static unsigned int num_hostkeys;
104 
105 
117 static int
118 iterator(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
119 {
121  value));
122  return GNUNET_YES;
123 }
124 
125 
129 static void
131 {
132  if (NULL != map)
133  {
135  &iterator,
136  NULL));
138  map = NULL;
139  }
140 }
141 
142 
150 static int
151 check_access(void *cls, const struct GNUNET_PeerIdentity * pid)
152 {
153  int contains;
154 
155  GNUNET_assert(NULL != map);
156  contains = GNUNET_CONTAINER_multipeermap_contains(map, pid);
157  if (GNUNET_YES == contains)
158  {
159  DEBUG("Permitting `%s'\n", GNUNET_i2s(pid));
160  return GNUNET_OK;
161  }
162  DEBUG("Not permitting `%s'\n", GNUNET_i2s(pid));
163  return GNUNET_SYSERR;
164 }
165 
166 
167 static int
168 get_identity(unsigned int offset,
169  struct GNUNET_PeerIdentity *id)
170 {
171  struct GNUNET_CRYPTO_EddsaPrivateKey private_key;
172 
173  if (offset >= num_hostkeys)
174  return GNUNET_SYSERR;
175  GNUNET_memcpy(&private_key,
177  GNUNET_TESTING_HOSTKEYFILESIZE);
179  &id->public_key);
180  return GNUNET_OK;
181 }
182 
183 
187 struct WhiteListRow {
192 
196  unsigned int id;
197 
201  int latency;
202 };
203 
204 
208 static int
210 {
211  char *data_dir;
212  char *idfile;
213  uint64_t fsize;
214 
215  data_dir = NULL;
216  idfile = NULL;
217  fsize = 0;
219  GNUNET_asprintf(&idfile, "%s/testing_hostkeys.ecc", data_dir);
220  GNUNET_free(data_dir);
221  data_dir = NULL;
222  if (GNUNET_OK !=
223  GNUNET_DISK_file_size(idfile, &fsize, GNUNET_YES, GNUNET_YES))
224  {
225  GNUNET_free(idfile);
226  return GNUNET_SYSERR;
227  }
228  if (0 != (fsize % GNUNET_TESTING_HOSTKEYFILESIZE))
229  {
231  _("Incorrect hostkey file format: %s\n"), idfile);
232  GNUNET_free(idfile);
233  return GNUNET_SYSERR;
234  }
235  hostkeys_fd = GNUNET_DISK_file_open(idfile, GNUNET_DISK_OPEN_READ,
237  if (NULL == hostkeys_fd)
238  {
240  GNUNET_free(idfile);
241  return GNUNET_SYSERR;
242  }
243  GNUNET_free(idfile);
244  idfile = NULL;
245  hostkeys_data = GNUNET_DISK_file_map(hostkeys_fd,
246  &hostkeys_map,
248  fsize);
249  if (NULL == hostkeys_data)
250  {
252  return GNUNET_SYSERR;
253  }
255  return GNUNET_OK;
256 }
257 
258 
262 static void
264 {
265  if (NULL != hostkeys_map)
266  {
267  GNUNET_assert(NULL != hostkeys_data);
268  GNUNET_DISK_file_unmap(hostkeys_map);
269  hostkeys_map = NULL;
270  hostkeys_data = NULL;
271  }
272  if (NULL != hostkeys_fd)
273  {
274  GNUNET_DISK_file_close(hostkeys_fd);
275  hostkeys_fd = NULL;
276  }
277 }
278 
279 
285 static void
286 do_shutdown(void *cls)
287 {
288  if (NULL != transport)
289  {
291  transport = NULL;
292  }
293  cleanup_map();
294  unload_keys();
295  if (NULL != bh)
297 }
298 
299 
308 static int
309 db_read_whitelist(struct sqlite3 *db, int pid, struct WhiteListRow **wl_rows)
310 {
311  static const char *query_wl = "SELECT oid, latency FROM whitelist WHERE (id == ?);";
312  struct sqlite3_stmt *stmt_wl;
313  struct WhiteListRow *lr;
314  int nrows;
315  int ret;
316 
317  if (SQLITE_OK != (ret = sqlite3_prepare_v2(db, query_wl, -1, &stmt_wl, NULL)))
318  {
319  LOG_SQLITE(db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_prepare_v2");
320  return GNUNET_SYSERR;
321  }
322  if (SQLITE_OK != (ret = sqlite3_bind_int(stmt_wl, 1, pid)))
323  {
324  LOG_SQLITE(db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_bind_int");
325  sqlite3_finalize(stmt_wl);
326  return GNUNET_SYSERR;
327  }
328  nrows = 0;
329  do
330  {
331  ret = sqlite3_step(stmt_wl);
332  if (SQLITE_ROW != ret)
333  break;
334  nrows++;
335  lr = GNUNET_new(struct WhiteListRow);
336  lr->id = sqlite3_column_int(stmt_wl, 0);
337  lr->latency = sqlite3_column_int(stmt_wl, 1);
338  lr->next = *wl_rows;
339  *wl_rows = lr;
340  }
341  while (1);
342  sqlite3_finalize(stmt_wl);
343  return nrows;
344 }
345 
346 
355 static void
356 run(void *cls, char *const *args, const char *cfgfile,
357  const struct GNUNET_CONFIGURATION_Handle *c)
358 {
359  char *dbfile;
360  struct WhiteListRow *wl_head;
361  struct WhiteListRow *wl_entry;
362  struct GNUNET_PeerIdentity identity;
363  struct GNUNET_ATS_Properties prop;
364  struct GNUNET_TIME_Relative delay;
365  unsigned long long pid;
366  unsigned int nrows;
367  int ret;
368 
369  if (GNUNET_OK !=
371  "PEERID", &pid))
372  {
373  GNUNET_break(0);
374  return;
375  }
376  if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename(c, "TESTBED-UNDERLAY",
377  "DBFILE",
378  &dbfile))
379  {
380  GNUNET_break(0);
381  return;
382  }
383  if (SQLITE_OK != (ret = sqlite3_open_v2(dbfile, &db, SQLITE_OPEN_READONLY, NULL)))
384  {
385  if (NULL != db)
386  {
387  LOG_SQLITE(db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite_open_v2");
388  GNUNET_break(SQLITE_OK == sqlite3_close(db));
389  }
390  else
391  LOG(GNUNET_ERROR_TYPE_ERROR, "Cannot open sqlite file %s\n", dbfile);
392  GNUNET_free(dbfile);
393  return;
394  }
395  DEBUG("Opened database %s\n", dbfile);
396  GNUNET_free(dbfile);
397  dbfile = NULL;
398  wl_head = NULL;
399  if (GNUNET_OK != load_keys(c))
400  goto close_db;
401 
403  if (NULL == transport)
404  {
405  GNUNET_break(0);
406  return;
407  }
408  /* read and process whitelist */
409  nrows = 0;
410  wl_head = NULL;
411  nrows = db_read_whitelist(db, pid, &wl_head);
412  if ((GNUNET_SYSERR == nrows) || (0 == nrows))
413  {
415  goto close_db;
416  }
418  while (NULL != (wl_entry = wl_head))
419  {
420  wl_head = wl_entry->next;
421  delay.rel_value_us = wl_entry->latency;
422  memset(&prop, 0, sizeof(prop));
423  GNUNET_assert(GNUNET_OK == get_identity(wl_entry->id, &identity));
425  GNUNET_CONTAINER_multipeermap_put(map, &identity, &identity,
427  DEBUG("Setting %u ms latency to peer `%s'\n",
428  wl_entry->latency,
429  GNUNET_i2s(&identity));
431  &identity,
432  &prop,
433  delay,
434  delay);
435  GNUNET_free(wl_entry);
436  }
439 
440 close_db:
441  GNUNET_break(SQLITE_OK == sqlite3_close(db));
442 }
443 
444 
452 int
453 main(int argc, char *const *argv)
454 {
455  static const struct GNUNET_GETOPT_CommandLineOption options[] = {
457  };
458  int ret;
459 
460  if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args(argc, argv, &argc, &argv))
461  return 2;
462 #ifdef SQLITE_CONFIG_MMAP_SIZE
463  (void)sqlite3_config(SQLITE_CONFIG_MMAP_SIZE, 512000, 256000000);
464 #endif
465  ret =
466  (GNUNET_OK ==
467  GNUNET_PROGRAM_run(argc, argv, "testbed-underlay",
468  _
469  ("Daemon to restrict underlay network in testbed deployments"),
470  options, &run, NULL)) ? 0 : 1;
471  GNUNET_free((void*)argv);
472  return ret;
473 }
static int iterator(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Iterator over hash map entries.
Open the file for reading.
#define DEBUG(...)
Debug logging shorthand.
int GNUNET_DISK_file_close(struct GNUNET_DISK_FileHandle *h)
Close an open file.
Definition: disk.c:1339
int GNUNET_CONFIGURATION_get_value_number(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long *number)
Get a configuration value that should be a number.
uint64_t rel_value_us
The actual value.
static struct GNUNET_GNS_LookupWithTldRequest * lr
Handle to lookup request.
Definition: gnunet-gns.c:75
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received, or when GNUNET_SCHEDULER_shutdown() is being invoked.
Definition: scheduler.c:1284
int GNUNET_STRINGS_get_utf8_args(int argc, char *const *argv, int *u8argc, char *const **u8argv)
Returns utf-8 encoded arguments.
Definition: strings.c:1439
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
void * GNUNET_DISK_file_map(const struct GNUNET_DISK_FileHandle *h, struct GNUNET_DISK_MapHandle **m, enum GNUNET_DISK_MapType access, size_t len)
Map a file into memory.
Definition: disk.c:1433
Nobody is allowed to do anything to the file.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
static struct GNUNET_CONTAINER_MultiPeerMap * map
The map to store the peer identities to allow/deny.
int GNUNET_CONTAINER_multipeermap_remove(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, const void *value)
Remove the given key-value pair from the map.
#define GNUNET_NO
Definition: gnunet_common.h:78
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
#define LOG(type,...)
Logging shorthand.
static struct GNUNET_DISK_MapHandle * hostkeys_map
The hostkeys map.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
Definition of a command line option.
void GNUNET_TRANSPORT_blacklist_cancel(struct GNUNET_TRANSPORT_Blacklist *br)
Abort the blacklist.
struct GNUNET_CONTAINER_MultiPeerMap * GNUNET_CONTAINER_multipeermap_create(unsigned int len, int do_not_copy_keys)
Create a multi peer map (hash map for public keys of peers).
static int ret
Final status code.
Definition: gnunet-arm.c:89
Handle for the transport service (includes all of the state for the transport service).
#define GNUNET_TESTING_HOSTKEYFILESIZE
Size of each hostkey in the hostkey file (in BYTES).
ATS performance characteristics for an address.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_OPTION_END
Definition: 002.c:13
void GNUNET_CONTAINER_multipeermap_destroy(struct GNUNET_CONTAINER_MultiPeerMap *map)
Destroy a hash map.
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
static void * hostkeys_data
The hostkeys data.
#define GNUNET_log_strerror(level, cmd)
Log an error message at log-level &#39;level&#39; that indicates a failure of the command &#39;cmd&#39; with the mess...
static int check_access(void *cls, const struct GNUNET_PeerIdentity *pid)
Function that decides if a connection is acceptable or not.
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
, &#39; bother checking if a value already exists (faster than GNUNET_CONTAINER_MULTIHASHMAPOPTION_...
static char * value
Value of the record to add/remove.
#define GNUNET_log_strerror_file(level, cmd, filename)
Log an error message at log-level &#39;level&#39; that indicates a failure of the command &#39;cmd&#39; with the mess...
static struct GNUNET_TRANSPORT_Blacklist * bh
The blacklist handle we obtain from transport when we register ourselves for access control...
char * GNUNET_OS_installation_get_path(enum GNUNET_OS_InstallationPathKind dirkind)
Get the path to a specific GNUnet installation directory or, with GNUNET_OS_IPK_SELF_PREFIX, the current running apps installation directory.
struct GNUNET_TRANSPORT_Blacklist * GNUNET_TRANSPORT_blacklist(const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_TRANSPORT_BlacklistCallback cb, void *cb_cls)
Install a blacklist callback.
Read-only memory map.
static unsigned int num_hostkeys
The number of hostkeys in the hostkeys array.
Internal representation of the hash map.
static int get_identity(unsigned int offset, struct GNUNET_PeerIdentity *id)
static struct sqlite3 * db
The database connection.
Handle for blacklisting requests.
struct GNUNET_HashCode key
The key used in the DHT.
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
int GNUNET_DISK_file_unmap(struct GNUNET_DISK_MapHandle *h)
Unmap a file.
Definition: disk.c:1469
struct WhiteListRow * next
Next ptr.
#define LOG_SQLITE(db, msg, level, cmd)
Log an error message at log-level &#39;level&#39; that indicates a failure of the command &#39;cmd&#39; on file &#39;file...
int GNUNET_DISK_file_size(const char *filename, uint64_t *size, int include_symbolic_links, int single_file_mode)
Get the size of the file (or directory) of the given file (in bytes).
Definition: disk.c:254
void GNUNET_CRYPTO_eddsa_key_get_public(const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, struct GNUNET_CRYPTO_EddsaPublicKey *pub)
Extract the public key for the given private key.
Definition: crypto_ecc.c:272
static void run(void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c)
Main function that will be run.
int GNUNET_CONTAINER_multipeermap_put(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
Private ECC key encoded for transmission.
int GNUNET_CONTAINER_multipeermap_iterate(struct GNUNET_CONTAINER_MultiPeerMap *map, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map.
The identity of the host (wraps the signing key of the peer).
struct GNUNET_TRANSPORT_ManipulationHandle * GNUNET_TRANSPORT_manipulation_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Connect to the transport service.
configuration data
Definition: configuration.c:83
Automatic transport selection and outbound bandwidth determination.
int latency
Latency to be assigned to the link.
void GNUNET_TRANSPORT_manipulation_disconnect(struct GNUNET_TRANSPORT_ManipulationHandle *handle)
Disconnect from the transport service.
static void do_shutdown(void *cls)
Shutdown task to cleanup our resources and exit.
int GNUNET_CONFIGURATION_get_value_filename(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be the name of a file or directory.
static void cleanup_map()
Cleaup and destroy the map.
int GNUNET_PROGRAM_run(int argc, char *const *argv, const char *binaryName, const char *binaryHelp, const struct GNUNET_GETOPT_CommandLineOption *options, GNUNET_PROGRAM_Main task, void *task_cls)
Run a standard GNUnet command startup sequence (initialize loggers and configuration, parse options).
Definition: program.c:367
unsigned int id
The offset where to find the hostkey for the peer.
static void unload_keys()
Function to unload keys.
#define GNUNET_YES
Definition: gnunet_common.h:77
static struct GNUNET_PeerIdentity pid
Identity of the peer we transmit to / connect to.
void GNUNET_TRANSPORT_manipulation_set(struct GNUNET_TRANSPORT_ManipulationHandle *handle, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_ATS_Properties *prop, struct GNUNET_TIME_Relative delay_in, struct GNUNET_TIME_Relative delay_out)
Set transport metrics for a peer and a direction.
struct GNUNET_DISK_FileHandle * GNUNET_DISK_file_open(const char *fn, enum GNUNET_DISK_OpenFlags flags, enum GNUNET_DISK_AccessPermissions perm)
Open a file.
Definition: disk.c:1262
int GNUNET_CONTAINER_multipeermap_contains(const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key)
Check if the map contains any value under the given key (including values that are NULL)...
Handle used to access files (and pipes).
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
Handle for a memory-mapping operation.
Definition: disk.c:1406
Return the directory where data is installed (share/gnunet/)
#define GNUNET_free(ptr)
Wrapper around free.
Time for relative time used by GNUnet, in microseconds.
struct GNUNET_CRYPTO_EddsaPublicKey public_key
int main(int argc, char *const *argv)
The main function.
static struct GNUNET_TRANSPORT_ManipulationHandle * transport
Handle to the transport service.
static int load_keys(const struct GNUNET_CONFIGURATION_Handle *c)
Function to load keys.
struct GNUNET_DISK_FileHandle * hostkeys_fd
The hostkeys file.
static int db_read_whitelist(struct sqlite3 *db, int pid, struct WhiteListRow **wl_rows)
Function to read whitelist rows from the database.