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 
188 {
193 
197  unsigned int id;
198 
202  int latency;
203 
204 };
205 
206 
210 static int
212 {
213  char *data_dir;
214  char *idfile;
215  uint64_t fsize;
216 
217  data_dir = NULL;
218  idfile = NULL;
219  fsize = 0;
221  GNUNET_asprintf (&idfile, "%s/testing_hostkeys.ecc", data_dir);
222  GNUNET_free (data_dir);
223  data_dir = NULL;
224  if (GNUNET_OK !=
225  GNUNET_DISK_file_size (idfile, &fsize, GNUNET_YES, GNUNET_YES))
226  {
227  GNUNET_free (idfile);
228  return GNUNET_SYSERR;
229  }
230  if (0 != (fsize % GNUNET_TESTING_HOSTKEYFILESIZE))
231  {
233  _("Incorrect hostkey file format: %s\n"), idfile);
234  GNUNET_free (idfile);
235  return GNUNET_SYSERR;
236  }
237  hostkeys_fd = GNUNET_DISK_file_open (idfile, GNUNET_DISK_OPEN_READ,
239  if (NULL == hostkeys_fd)
240  {
242  GNUNET_free (idfile);
243  return GNUNET_SYSERR;
244  }
245  GNUNET_free (idfile);
246  idfile = NULL;
247  hostkeys_data = GNUNET_DISK_file_map (hostkeys_fd,
248  &hostkeys_map,
250  fsize);
251  if (NULL == hostkeys_data)
252  {
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 = "SELECT oid, latency FROM whitelist WHERE (id == ?);";
315  struct sqlite3_stmt *stmt_wl;
316  struct WhiteListRow *lr;
317  int nrows;
318  int ret;
319 
320  if (SQLITE_OK != (ret = sqlite3_prepare_v2 (db, query_wl, -1, &stmt_wl, NULL)))
321  {
322  LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_prepare_v2");
323  return GNUNET_SYSERR;
324  }
325  if (SQLITE_OK != (ret = sqlite3_bind_int (stmt_wl, 1, pid)))
326  {
327  LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_bind_int");
328  sqlite3_finalize (stmt_wl);
329  return GNUNET_SYSERR;
330  }
331  nrows = 0;
332  do
333  {
334  ret = sqlite3_step (stmt_wl);
335  if (SQLITE_ROW != ret)
336  break;
337  nrows++;
338  lr = GNUNET_new (struct WhiteListRow);
339  lr->id = sqlite3_column_int (stmt_wl, 0);
340  lr->latency = sqlite3_column_int (stmt_wl, 1);
341  lr->next = *wl_rows;
342  *wl_rows = lr;
343  } while (1);
344  sqlite3_finalize (stmt_wl);
345  return nrows;
346 }
347 
348 
357 static void
358 run (void *cls, char *const *args, const char *cfgfile,
359  const struct GNUNET_CONFIGURATION_Handle *c)
360 {
361  char *dbfile;
362  struct WhiteListRow *wl_head;
363  struct WhiteListRow *wl_entry;
364  struct GNUNET_PeerIdentity identity;
365  struct GNUNET_ATS_Properties prop;
366  struct GNUNET_TIME_Relative delay;
367  unsigned long long pid;
368  unsigned int nrows;
369  int ret;
370 
371  if (GNUNET_OK !=
373  "PEERID", &pid))
374  {
375  GNUNET_break (0);
376  return;
377  }
378  if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (c, "TESTBED-UNDERLAY",
379  "DBFILE",
380  &dbfile))
381  {
382  GNUNET_break (0);
383  return;
384  }
385  if (SQLITE_OK != (ret = sqlite3_open_v2 (dbfile, &db, SQLITE_OPEN_READONLY, NULL)))
386  {
387  if (NULL != db)
388  {
389  LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite_open_v2");
390  GNUNET_break (SQLITE_OK == sqlite3_close (db));
391  }
392  else
393  LOG (GNUNET_ERROR_TYPE_ERROR, "Cannot open sqlite file %s\n", dbfile);
394  GNUNET_free (dbfile);
395  return;
396  }
397  DEBUG ("Opened database %s\n", dbfile);
398  GNUNET_free (dbfile);
399  dbfile = NULL;
400  wl_head = NULL;
401  if (GNUNET_OK != load_keys (c))
402  goto close_db;
403 
405  if (NULL == transport)
406  {
407  GNUNET_break (0);
408  return;
409  }
410  /* read and process whitelist */
411  nrows = 0;
412  wl_head = NULL;
413  nrows = db_read_whitelist (db, pid, &wl_head);
414  if ((GNUNET_SYSERR == nrows) || (0 == nrows))
415  {
417  goto close_db;
418  }
420  while (NULL != (wl_entry = wl_head))
421  {
422  wl_head = wl_entry->next;
423  delay.rel_value_us = wl_entry->latency;
424  memset (&prop, 0, sizeof (prop));
425  GNUNET_assert (GNUNET_OK == get_identity (wl_entry->id, &identity));
427  GNUNET_CONTAINER_multipeermap_put (map, &identity, &identity,
429  DEBUG ("Setting %u ms latency to peer `%s'\n",
430  wl_entry->latency,
431  GNUNET_i2s (&identity));
433  &identity,
434  &prop,
435  delay,
436  delay);
437  GNUNET_free (wl_entry);
438  }
439  bh = GNUNET_TRANSPORT_blacklist (c, &check_access, NULL);
441 
442  close_db:
443  GNUNET_break (SQLITE_OK == sqlite3_close (db));
444 }
445 
446 
454 int
455 main (int argc, char *const *argv)
456 {
457  static const struct GNUNET_GETOPT_CommandLineOption options[] = {
459  };
460  int ret;
461 
462  if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
463  return 2;
464 #ifdef SQLITE_CONFIG_MMAP_SIZE
465  (void) sqlite3_config (SQLITE_CONFIG_MMAP_SIZE, 512000, 256000000);
466 #endif
467  ret =
468  (GNUNET_OK ==
469  GNUNET_PROGRAM_run (argc, argv, "testbed-underlay",
470  _
471  ("Daemon to restrict underlay network in testbed deployments"),
472  options, &run, NULL)) ? 0 : 1;
473  GNUNET_free ((void*) argv);
474  return ret;
475 }
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:1817
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:1293
int GNUNET_STRINGS_get_utf8_args(int argc, char *const *argv, int *u8argc, char *const **u8argv)
Returns utf-8 encoded arguments.
Definition: strings.c:1521
#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:2020
Nobody is allowed to do anything to the file.
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:81
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
#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:208
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.
#define GNUNET_memcpy(dst, src, n)
, &#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:79
int GNUNET_DISK_file_unmap(struct GNUNET_DISK_MapHandle *h)
Unmap a file.
Definition: disk.c:2100
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:289
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: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:361
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:80
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:1673
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:1985
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.