GNUnet  0.11.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", _ ( \
57  "`%s' failed at %s:%d with error: %s\n"), \
58  cmd, __FILE__, __LINE__, sqlite3_errmsg (db)); \
59  if (msg != NULL) \
60  GNUNET_asprintf (msg, _ ("`%s' failed at %s:%u with error: %s"), cmd, \
61  __FILE__, __LINE__, sqlite3_errmsg (db)); \
62  } while (0)
63 
64 
69 
73 static struct sqlite3 *db;
74 
80 
85 
90 
94 static void *hostkeys_data;
95 
100 
104 static unsigned int num_hostkeys;
105 
106 
118 static int
119 iterator (void *cls, const struct GNUNET_PeerIdentity *key, void *value)
120 {
122  value));
123  return GNUNET_YES;
124 }
125 
126 
130 static void
132 {
133  if (NULL != map)
134  {
136  &
137  iterator,
138  NULL));
140  map = NULL;
141  }
142 }
143 
144 
152 static int
153 check_access (void *cls, const struct GNUNET_PeerIdentity *pid)
154 {
155  int contains;
156 
157  GNUNET_assert (NULL != map);
158  contains = GNUNET_CONTAINER_multipeermap_contains (map, pid);
159  if (GNUNET_YES == contains)
160  {
161  DEBUG ("Permitting `%s'\n", GNUNET_i2s (pid));
162  return GNUNET_OK;
163  }
164  DEBUG ("Not permitting `%s'\n", GNUNET_i2s (pid));
165  return GNUNET_SYSERR;
166 }
167 
168 
169 static int
170 get_identity (unsigned int offset,
171  struct GNUNET_PeerIdentity *id)
172 {
173  struct GNUNET_CRYPTO_EddsaPrivateKey private_key;
174 
175  if (offset >= num_hostkeys)
176  return GNUNET_SYSERR;
177  GNUNET_memcpy (&private_key,
179  GNUNET_TESTING_HOSTKEYFILESIZE);
181  &id->public_key);
182  return GNUNET_OK;
183 }
184 
185 
190 {
195 
199  unsigned int id;
200 
204  int latency;
205 };
206 
207 
211 static int
213 {
214  char *data_dir;
215  char *idfile;
216  uint64_t fsize;
217 
218  data_dir = NULL;
219  idfile = NULL;
220  fsize = 0;
222  GNUNET_asprintf (&idfile, "%s/testing_hostkeys.ecc", data_dir);
223  GNUNET_free (data_dir);
224  data_dir = NULL;
225  if (GNUNET_OK !=
226  GNUNET_DISK_file_size (idfile, &fsize, GNUNET_YES, GNUNET_YES))
227  {
228  GNUNET_free (idfile);
229  return GNUNET_SYSERR;
230  }
231  if (0 != (fsize % GNUNET_TESTING_HOSTKEYFILESIZE))
232  {
234  _ ("Incorrect hostkey file format: %s\n"), idfile);
235  GNUNET_free (idfile);
236  return GNUNET_SYSERR;
237  }
238  hostkeys_fd = GNUNET_DISK_file_open (idfile, GNUNET_DISK_OPEN_READ,
240  if (NULL == hostkeys_fd)
241  {
243  GNUNET_free (idfile);
244  return GNUNET_SYSERR;
245  }
246  GNUNET_free (idfile);
247  idfile = NULL;
248  hostkeys_data = GNUNET_DISK_file_map (hostkeys_fd,
249  &hostkeys_map,
251  fsize);
252  if (NULL == hostkeys_data)
253  {
255  return GNUNET_SYSERR;
256  }
258  return GNUNET_OK;
259 }
260 
261 
265 static void
267 {
268  if (NULL != hostkeys_map)
269  {
270  GNUNET_assert (NULL != hostkeys_data);
271  GNUNET_DISK_file_unmap (hostkeys_map);
272  hostkeys_map = NULL;
273  hostkeys_data = NULL;
274  }
275  if (NULL != hostkeys_fd)
276  {
277  GNUNET_DISK_file_close (hostkeys_fd);
278  hostkeys_fd = NULL;
279  }
280 }
281 
282 
288 static void
289 do_shutdown (void *cls)
290 {
291  if (NULL != transport)
292  {
294  transport = NULL;
295  }
296  cleanup_map ();
297  unload_keys ();
298  if (NULL != bh)
300 }
301 
302 
311 static int
312 db_read_whitelist (struct sqlite3 *db, int pid, struct WhiteListRow **wl_rows)
313 {
314  static const char *query_wl =
315  "SELECT oid, latency FROM whitelist WHERE (id == ?);";
316  struct sqlite3_stmt *stmt_wl;
317  struct WhiteListRow *lr;
318  int nrows;
319  int ret;
320 
321  if (SQLITE_OK != (ret = sqlite3_prepare_v2 (db, query_wl, -1, &stmt_wl,
322  NULL)))
323  {
324  LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_prepare_v2");
325  return GNUNET_SYSERR;
326  }
327  if (SQLITE_OK != (ret = sqlite3_bind_int (stmt_wl, 1, pid)))
328  {
329  LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_bind_int");
330  sqlite3_finalize (stmt_wl);
331  return GNUNET_SYSERR;
332  }
333  nrows = 0;
334  do
335  {
336  ret = sqlite3_step (stmt_wl);
337  if (SQLITE_ROW != ret)
338  break;
339  nrows++;
340  lr = GNUNET_new (struct WhiteListRow);
341  lr->id = sqlite3_column_int (stmt_wl, 0);
342  lr->latency = sqlite3_column_int (stmt_wl, 1);
343  lr->next = *wl_rows;
344  *wl_rows = lr;
345  }
346  while (1);
347  sqlite3_finalize (stmt_wl);
348  return nrows;
349 }
350 
351 
360 static void
361 run (void *cls, char *const *args, const char *cfgfile,
362  const struct GNUNET_CONFIGURATION_Handle *c)
363 {
364  char *dbfile;
365  struct WhiteListRow *wl_head;
366  struct WhiteListRow *wl_entry;
367  struct GNUNET_PeerIdentity identity;
368  struct GNUNET_ATS_Properties prop;
369  struct GNUNET_TIME_Relative delay;
370  unsigned long long pid;
371  unsigned int nrows;
372  int ret;
373 
374  if (GNUNET_OK !=
376  "PEERID", &pid))
377  {
378  GNUNET_break (0);
379  return;
380  }
382  "TESTBED-UNDERLAY",
383  "DBFILE",
384  &dbfile))
385  {
386  GNUNET_break (0);
387  return;
388  }
389  if (SQLITE_OK != (ret = sqlite3_open_v2 (dbfile, &db, SQLITE_OPEN_READONLY,
390  NULL)))
391  {
392  if (NULL != db)
393  {
394  LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite_open_v2");
395  GNUNET_break (SQLITE_OK == sqlite3_close (db));
396  }
397  else
398  LOG (GNUNET_ERROR_TYPE_ERROR, "Cannot open sqlite file %s\n", dbfile);
399  GNUNET_free (dbfile);
400  return;
401  }
402  DEBUG ("Opened database %s\n", dbfile);
403  GNUNET_free (dbfile);
404  dbfile = NULL;
405  wl_head = NULL;
406  if (GNUNET_OK != load_keys (c))
407  goto close_db;
408 
410  if (NULL == transport)
411  {
412  GNUNET_break (0);
413  return;
414  }
415  /* read and process whitelist */
416  nrows = 0;
417  wl_head = NULL;
418  nrows = db_read_whitelist (db, pid, &wl_head);
419  if ((GNUNET_SYSERR == nrows) || (0 == nrows))
420  {
422  goto close_db;
423  }
425  while (NULL != (wl_entry = wl_head))
426  {
427  wl_head = wl_entry->next;
428  delay.rel_value_us = wl_entry->latency;
429  memset (&prop, 0, sizeof(prop));
430  GNUNET_assert (GNUNET_OK == get_identity (wl_entry->id, &identity));
432  GNUNET_CONTAINER_multipeermap_put (map, &identity, &identity,
434  DEBUG ("Setting %u ms latency to peer `%s'\n",
435  wl_entry->latency,
436  GNUNET_i2s (&identity));
438  &identity,
439  &prop,
440  delay,
441  delay);
442  GNUNET_free (wl_entry);
443  }
444  bh = GNUNET_TRANSPORT_blacklist (c, &check_access, NULL);
446 
447 close_db:
448  GNUNET_break (SQLITE_OK == sqlite3_close (db));
449 }
450 
451 
459 int
460 main (int argc, char *const *argv)
461 {
462  static const struct GNUNET_GETOPT_CommandLineOption options[] = {
464  };
465  int ret;
466 
467  if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
468  return 2;
469 #ifdef SQLITE_CONFIG_MMAP_SIZE
470  (void) sqlite3_config (SQLITE_CONFIG_MMAP_SIZE, 512000, 256000000);
471 #endif
472  ret =
473  (GNUNET_OK ==
474  GNUNET_PROGRAM_run (argc, argv, "testbed-underlay",
475  _
476  (
477  "Daemon to restrict underlay network in testbed deployments"),
478  options, &run, NULL)) ? 0 : 1;
479  GNUNET_free ((void*) argv);
480  return ret;
481 }
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:1345
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:1300
int GNUNET_STRINGS_get_utf8_args(int argc, char *const *argv, int *u8argc, char *const **u8argv)
Returns utf-8 encoded arguments.
Definition: strings.c:1438
#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:1440
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.
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
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).
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:1477
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:257
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:270
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:85
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:1268
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:1412
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.