GNUnet  0.19.3
gnsrecord_misc.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2009-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 
28 #include "platform.h"
29 #include "gnunet_util_lib.h"
30 #include "gnunet_constants.h"
31 #include "gnunet_signatures.h"
32 #include "gnunet_arm_service.h"
33 #include "gnunet_gnsrecord_lib.h"
34 
35 
36 #define LOG(kind, ...) GNUNET_log_from (kind, "gnsrecord", __VA_ARGS__)
37 
38 char *
40 {
41  /*FIXME: We may want to follow RFC5890/RFC5891 */
42  return GNUNET_STRINGS_utf8_normalize (src);
43 }
44 
45 
47 GNUNET_GNSRECORD_label_check (const char*label, char **emsg)
48 {
49  if (NULL == label)
50  {
51  *emsg = GNUNET_strdup (_ ("Label is NULL which is not allowed\n"));
52  return GNUNET_NO;
53  }
54  if (0 != strchr (label, '.'))
55  {
56  *emsg = GNUNET_strdup (_ ("Label contains `.' which is not allowed\n"));
57  return GNUNET_NO;
58  }
59  return GNUNET_OK;
60 }
61 
62 
63 const char *
65 {
66  static char buf[sizeof(struct GNUNET_IDENTITY_PublicKey) * 8];
67  char *end;
68 
69  end = GNUNET_STRINGS_data_to_string ((const unsigned char *) z,
70  sizeof(struct
72  buf, sizeof(buf));
73  if (NULL == end)
74  {
75  GNUNET_break (0);
76  return NULL;
77  }
78  *end = '\0';
79  return buf;
80 }
81 
82 
92 int
94  const struct GNUNET_GNSRECORD_Data *b)
95 {
97  "Comparing records\n");
98  if (a->record_type != b->record_type)
99  {
101  "Record type %u != %u\n", a->record_type, b->record_type);
102  return GNUNET_NO;
103  }
104  if ((a->expiration_time != b->expiration_time) &&
105  ((a->expiration_time != 0) && (b->expiration_time != 0)))
106  {
108  "Expiration time %llu != %llu\n",
109  (unsigned long long) a->expiration_time,
110  (unsigned long long) b->expiration_time);
111  return GNUNET_NO;
112  }
115  {
117  "Flags %u (%u) != %u (%u)\n", a->flags,
120  return GNUNET_NO;
121  }
122  if (a->data_size != b->data_size)
123  {
125  "Data size %lu != %lu\n",
126  a->data_size,
127  b->data_size);
128  return GNUNET_NO;
129  }
130  if (0 != memcmp (a->data, b->data, a->data_size))
131  {
133  "Data contents do not match\n");
134  return GNUNET_NO;
135  }
137  "Records are equal\n");
138  return GNUNET_YES;
139 }
140 
141 
144  const struct
146  struct GNUNET_TIME_Absolute min)
147 {
149  struct GNUNET_TIME_Absolute at;
150  struct GNUNET_TIME_Relative rt;
151  struct GNUNET_TIME_Absolute at_shadow;
152  struct GNUNET_TIME_Relative rt_shadow;
153 
154  if (0 == rd_count)
157  for (unsigned int c = 0; c < rd_count; c++)
158  {
159  if (0 != (rd[c].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION))
160  {
161  rt.rel_value_us = rd[c].expiration_time;
163  }
164  else
165  {
166  at.abs_value_us = rd[c].expiration_time;
167  }
168 
169  for (unsigned int c2 = 0; c2 < rd_count; c2++)
170  {
171  /* Check for shadow record */
172  if ((c == c2) ||
173  (rd[c].record_type != rd[c2].record_type) ||
174  (0 == (rd[c2].flags & GNUNET_GNSRECORD_RF_SHADOW)))
175  continue;
176  /* We have a shadow record */
177  if (0 != (rd[c2].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION))
178  {
179  rt_shadow.rel_value_us = rd[c2].expiration_time;
180  at_shadow = GNUNET_TIME_relative_to_absolute (rt_shadow);
181  }
182  else
183  {
184  at_shadow.abs_value_us = rd[c2].expiration_time;
185  }
186  at = GNUNET_TIME_absolute_max (at,
187  at_shadow);
188  }
190  expire);
191  }
194  "Determined expiration time for block with %u records to be %s\n",
195  rd_count,
197  return expire;
198 }
199 
200 
207 int
209 {
210  struct GNUNET_TIME_Absolute at;
211 
213  return GNUNET_NO;
215  return (0 == GNUNET_TIME_absolute_get_remaining (at).rel_value_us) ?
217 }
218 
219 
230 const char *
232 {
233  static char ret[128];
234  char *pkeys;
235 
238  sizeof(ret),
239  "%s",
240  pkeys);
241  GNUNET_free (pkeys);
242  return ret;
243 }
244 
245 
255 int
258 {
259  if (GNUNET_OK !=
261  pkey))
262  return GNUNET_SYSERR;
263  return GNUNET_OK;
264 }
265 
266 
269  size_t data_size,
270  uint32_t type,
272 {
274  return GNUNET_SYSERR;
275  switch (type)
276  {
278  if (data_size > sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey))
279  return GNUNET_SYSERR;
280  memcpy (&key->ecdsa_key, data, data_size);
281  break;
283  if (data_size > sizeof (struct GNUNET_CRYPTO_EddsaPublicKey))
284  return GNUNET_SYSERR;
285  memcpy (&key->eddsa_key, data, data_size);
286  break;
287  default:
288  return GNUNET_NO;
289  }
290  key->type = htonl (type);
291 
292  return GNUNET_YES;
293 }
294 
295 
299  char **data,
300  size_t *data_size,
301  uint32_t *type)
302 {
303  char *tmp;
304  *type = ntohl (key->type);
306  if (0 == *data_size)
307  return GNUNET_SYSERR;
308  tmp = GNUNET_malloc (*data_size);
309  memcpy (tmp, ((char*) key) + sizeof (key->type), *data_size);
310  *data = tmp;
311  return GNUNET_OK;
312 }
313 
314 
317 {
318  switch (type)
319  {
322  return GNUNET_YES;
323  default:
324  return GNUNET_NO;
325  }
326 }
327 
328 
329 size_t
331 {
332  return ntohl (block->size);
333 }
334 
335 
338  GNUNET_GNSRECORD_Block *block)
339 {
340 
341  switch (ntohl (block->type))
342  {
344  return GNUNET_TIME_absolute_ntoh (block->ecdsa_block.expiration_time);
346  return GNUNET_TIME_absolute_ntoh (block->eddsa_block.expiration_time);
347  default:
348  GNUNET_break (0); /* Hopefully we never get here, but we might */
349  }
351 
352 }
353 
354 
357  struct GNUNET_HashCode *query)
358 {
359  switch (ntohl (block->type))
360  {
363  sizeof (block->ecdsa_block.derived_key),
364  query);
365  return GNUNET_OK;
368  sizeof (block->eddsa_block.derived_key),
369  query);
370  return GNUNET_OK;
371  default:
372  return GNUNET_SYSERR;
373  }
374  return GNUNET_SYSERR;
375 
376 }
377 
378 
382 {
384  "Got record of type %u\n",
385  rd->record_type);
386  switch (rd->record_type)
387  {
389  key->type = htonl (rd->record_type);
390  memcpy (&key->ecdsa_key, rd->data, sizeof (key->ecdsa_key));
391  return GNUNET_OK;
393  key->type = htonl (rd->record_type);
394  memcpy (&key->eddsa_key, rd->data, sizeof (key->eddsa_key));
395  return GNUNET_OK;
396  default:
397  return GNUNET_SYSERR;
398  }
399  return GNUNET_SYSERR;
400 
401 
402 }
403 
404 
406 GNUNET_GNSRECORD_normalize_record_set (const char *label,
407  const struct
409  unsigned int rd_count,
410  struct GNUNET_GNSRECORD_Data *
411  rd_public,
412  unsigned int *rd_count_public,
413  struct GNUNET_TIME_Absolute *expiry,
415  char **emsg)
416 {
417  struct GNUNET_TIME_Absolute now;
418  struct GNUNET_TIME_Absolute minimum_expiration;
419  int have_zone_delegation = GNUNET_NO;
420  int have_gns2dns = GNUNET_NO;
421  int have_other = GNUNET_NO;
422  int have_redirect = GNUNET_NO;
423  int have_empty_label = (0 == strcmp (GNUNET_GNS_EMPTY_LABEL_AT, label));
424  unsigned int rd_count_tmp;
425 
426  minimum_expiration = GNUNET_TIME_UNIT_ZERO_ABS;
427  now = GNUNET_TIME_absolute_get ();
428  rd_count_tmp = 0;
429  for (unsigned int i = 0; i < rd_count; i++)
430  {
431  /* Ignore private records for public record set */
433  (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_PRIVATE)))
434  {
436  "Filtering private record filter=%u...\n", filter);
437  continue;
438  }
439  /* Skip expired records */
440  if ((0 == (rd[i].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION)) &&
441  (rd[i].expiration_time < now.abs_value_us))
442  {
444  "Filtering expired record...\n");
445  continue; /* record already expired, skip it */
446  }
447  /* Ignore the tombstone unless filter permits explicitly.
448  * Remember expiration time. */
449  if (GNUNET_GNSRECORD_TYPE_TOMBSTONE == rd[i].record_type)
450  {
451  minimum_expiration.abs_value_us = rd[i].expiration_time;
453  {
454  rd_public[rd_count_tmp] = rd[i];
455  rd_count_tmp++;
456  }
457  continue;
458  }
459  /* No NICK records unless empty label */
460  if (have_empty_label &&
461  (GNUNET_GNSRECORD_TYPE_NICK == rd[i].record_type))
462  continue;
463 
473  if (GNUNET_YES == GNUNET_GNSRECORD_is_zonekey_type (rd[i].record_type))
474  {
475  /* No delegation records under empty label*/
476  if (have_empty_label)
477  {
478  *emsg = GNUNET_strdup (_ (
479  "Zone delegation record not allowed in apex."));
480  return GNUNET_SYSERR;
481  }
482  if ((GNUNET_YES == have_other) ||
483  (GNUNET_YES == have_redirect) ||
484  (GNUNET_YES == have_gns2dns))
485  {
486  *emsg = GNUNET_strdup (_ (
487  "Zone delegation record set contains mutually exclusive records."));
488  return GNUNET_SYSERR;
489  }
490  have_zone_delegation = GNUNET_YES;
491  }
492  else if (GNUNET_GNSRECORD_TYPE_REDIRECT == rd[i].record_type)
493  {
494  if (GNUNET_YES == have_redirect)
495  {
496  *emsg = GNUNET_strdup (_ (
497  "Multiple REDIRECT records."));
498  return GNUNET_SYSERR;
499 
500  }
501  if ((GNUNET_YES == have_other) ||
502  (GNUNET_YES == have_zone_delegation) ||
503  (GNUNET_YES == have_gns2dns))
504  {
505  *emsg = GNUNET_strdup (_ (
506  "Redirection record set contains mutually exclusive records."));
507  return GNUNET_SYSERR;
508  }
509  /* No redirection records under empty label*/
510  if (have_empty_label)
511  {
512  *emsg = GNUNET_strdup (_ (
513  "Redirection records not allowed in apex."));
514  return GNUNET_SYSERR;
515  }
516  have_redirect = GNUNET_YES;
517  }
518  else if (GNUNET_GNSRECORD_TYPE_GNS2DNS == rd[i].record_type)
519  {
520  /* No gns2dns records under empty label*/
521  if (have_empty_label)
522  {
523  *emsg = GNUNET_strdup (_ (
524  "Redirection records not allowed in apex.."));
525  return GNUNET_SYSERR;
526  }
527  if ((GNUNET_YES == have_other) ||
528  (GNUNET_YES == have_redirect) ||
529  (GNUNET_YES == have_zone_delegation))
530  {
531  *emsg = GNUNET_strdup (_ (
532  "Redirection record set contains mutually exclusive records."));
533  return GNUNET_SYSERR;
534  }
535  have_gns2dns = GNUNET_YES;
536  }
537  else
538  {
539  /* Some other record.
540  * Not allowed for zone delegations or redirections */
541  if ((GNUNET_YES == have_zone_delegation) ||
542  (GNUNET_YES == have_redirect) ||
543  (GNUNET_YES == have_gns2dns))
544  {
545  *emsg = GNUNET_strdup (_ (
546  "Mutually exclusive records."));
547  return GNUNET_SYSERR;
548  }
549  have_other = GNUNET_YES;
550  }
551 
552  rd_public[rd_count_tmp] = rd[i];
553  /* Make sure critical record types are marked as such */
554  if (GNUNET_YES == GNUNET_GNSRECORD_is_critical (rd[i].record_type))
555  rd_public[rd_count_tmp].flags |= GNUNET_GNSRECORD_RF_CRITICAL;
556  rd_count_tmp++;
557  }
558 
559  *expiry = GNUNET_GNSRECORD_record_get_expiration_time (rd_count_tmp,
560  rd_public,
561  minimum_expiration);
562  *rd_count_public = rd_count_tmp;
563  return GNUNET_OK;
564 }
565 
566 
567 /* end of gnsrecord_misc.c */
#define GNUNET_GNSRECORD_TYPE_NICK
GNS nick names.
#define GNUNET_GNSRECORD_TYPE_TOMBSTONE
Record type to indicate a previously delete record (PRIVATE only)
#define GNUNET_GNSRECORD_TYPE_GNS2DNS
Delegation to DNS.
#define GNUNET_GNSRECORD_TYPE_REDIRECT
Resolver redirects.
#define GNUNET_GNSRECORD_TYPE_PKEY
WARNING: This header is generated! In order to add GNS record types, you must register them in GANA,...
#define GNUNET_GNSRECORD_TYPE_EDKEY
Record type for EDKEY zone delegations.
enum GNUNET_GenericReturnValue GNUNET_GNSRECORD_record_to_identity_key(const struct GNUNET_GNSRECORD_Data *rd, struct GNUNET_IDENTITY_PublicKey *key)
#define LOG(kind,...)
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
static size_t data_size
Number of bytes in data.
Definition: gnunet-abd.c:187
static int end
Set if we are to shutdown all services (including ARM).
Definition: gnunet-arm.c:34
struct GNUNET_HashCode key
The key used in the DHT.
static char * expire
DID Document expiration Date Attribut String.
Definition: gnunet-did.c:101
uint32_t data
The data value.
static char * pkey
Public key of the zone to look in, in ASCII.
static unsigned int rd_count
Number of records for currently parsed set.
static struct GNUNET_GNSRECORD_Data rd[50]
The record data under a single label.
static struct GNUNET_CONTAINER_BloomFilter * filter
Bloomfilter to quickly tell if we don't have the content.
static char buf[2048]
API that can be used to manipulate GNS record data.
char * GNUNET_GNSRECORD_string_normalize(const char *src)
Normalize a UTF-8 string to a GNS name.
enum GNUNET_GenericReturnValue GNUNET_GNSRECORD_label_check(const char *label, char **emsg)
Check label for invalid characters.
#define GNUNET_GNSRECORD_RF_RCMP_FLAGS
Include the record types generated from GANA.
@ GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION
This expiration time of the record is a relative time (not an absolute time).
@ GNUNET_GNSRECORD_RF_CRITICAL
This record is critical.
@ GNUNET_GNSRECORD_RF_SHADOW
This record should not be used unless all (other) records in the set with an absolute expiration time...
@ GNUNET_GNSRECORD_RF_PRIVATE
This is a private record of this peer and it should thus not be published.
enum GNUNET_GenericReturnValue GNUNET_GNSRECORD_identity_from_data(const char *data, size_t data_size, uint32_t type, struct GNUNET_IDENTITY_PublicKey *key)
Build a #GNUNET_GNSRECORD_PublicKey from zone delegation resource record data.
enum GNUNET_GenericReturnValue GNUNET_GNSRECORD_data_from_identity(const struct GNUNET_IDENTITY_PublicKey *key, char **data, size_t *data_size, uint32_t *type)
Create record data and size from an identity key.
struct GNUNET_TIME_Absolute GNUNET_GNSRECORD_record_get_expiration_time(unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd, struct GNUNET_TIME_Absolute min)
Returns the expiration time of the given block of records.
size_t GNUNET_GNSRECORD_block_get_size(const struct GNUNET_GNSRECORD_Block *block)
Returns the length of this block in bytes.
enum GNUNET_GenericReturnValue GNUNET_GNSRECORD_query_from_block(const struct GNUNET_GNSRECORD_Block *block, struct GNUNET_HashCode *query)
Builds the query hash from a block.
int GNUNET_GNSRECORD_is_expired(const struct GNUNET_GNSRECORD_Data *rd)
Test if a given record is expired.
#define GNUNET_GNS_EMPTY_LABEL_AT
String we use to indicate an empty label (top-level entry in the zone).
enum GNUNET_GenericReturnValue GNUNET_GNSRECORD_is_critical(uint32_t type)
Check if this type is a critical record.
Definition: gnsrecord.c:247
int GNUNET_GNSRECORD_zkey_to_pkey(const char *zkey, struct GNUNET_IDENTITY_PublicKey *pkey)
Convert an absolute domain name to the respective public key.
enum GNUNET_GenericReturnValue GNUNET_GNSRECORD_is_zonekey_type(uint32_t type)
Check if this type is one of the supported GNS zone types.
const char * GNUNET_GNSRECORD_z2s(const struct GNUNET_IDENTITY_PublicKey *z)
Convert a zone to a string (for printing debug messages).
GNUNET_GNSRECORD_Filter
Filter for GNUNET_GNSRECORD_normalize_record_set().
enum GNUNET_GenericReturnValue GNUNET_GNSRECORD_normalize_record_set(const char *label, const struct GNUNET_GNSRECORD_Data *rd, unsigned int rd_count, struct GNUNET_GNSRECORD_Data *rd_public, unsigned int *rd_count_public, struct GNUNET_TIME_Absolute *expiry, enum GNUNET_GNSRECORD_Filter filter, char **emsg)
Normalize namestore records: Check for consistency and expirations.
int GNUNET_GNSRECORD_records_cmp(const struct GNUNET_GNSRECORD_Data *a, const struct GNUNET_GNSRECORD_Data *b)
Compares if two records are equal (ignoring flags such as authority, private and pending,...
struct GNUNET_TIME_Absolute GNUNET_GNSRECORD_block_get_expiration(const struct GNUNET_GNSRECORD_Block *block)
Returns the expiration of a block.
const char * GNUNET_GNSRECORD_pkey_to_zkey(const struct GNUNET_IDENTITY_PublicKey *pkey)
Convert public key to the respective absolute domain name in the ".zkey" pTLD.
@ GNUNET_GNSRECORD_FILTER_INCLUDE_MAINTENANCE
Include maintenance records (TOMBSTONE etc).
@ GNUNET_GNSRECORD_FILTER_OMIT_PRIVATE
Filter private records.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:41
enum GNUNET_GenericReturnValue GNUNET_IDENTITY_public_key_from_string(const char *str, struct GNUNET_IDENTITY_PublicKey *key)
Parses a (Base32) string representation of the public key.
ssize_t GNUNET_IDENTITY_public_key_get_length(const struct GNUNET_IDENTITY_PublicKey *key)
Get the compacted length of a GNUNET_IDENTITY_PublicKey.
Definition: identity_api.c:830
char * GNUNET_IDENTITY_public_key_to_string(const struct GNUNET_IDENTITY_PublicKey *key)
Creates a (Base32) string representation of the public key.
#define GNUNET_log(kind,...)
GNUNET_GenericReturnValue
Named constants for return values.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
@ GNUNET_ERROR_TYPE_DEBUG
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
int GNUNET_snprintf(char *buf, size_t size, const char *format,...) __attribute__((format(printf
Like snprintf, just aborts if the buffer is of insufficient size.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
char * GNUNET_STRINGS_data_to_string(const void *data, size_t size, char *out, size_t out_size)
Convert binary data to ASCII encoding using CrockfordBase32.
Definition: strings.c:708
char * GNUNET_STRINGS_utf8_normalize(const char *input)
Normalize the utf-8 input string to NFC.
Definition: strings.c:429
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get_zero_(void)
Return absolute time of 0ms.
Definition: time.c:142
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_remaining(struct GNUNET_TIME_Absolute future)
Given a timestamp in the future, how much time remains until then?
Definition: time.c:405
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_max(struct GNUNET_TIME_Absolute t1, struct GNUNET_TIME_Absolute t2)
Return the maximum of two absolute time values.
Definition: time.c:367
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:111
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
Like asctime, except for GNUnet time.
Definition: strings.c:616
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_ntoh(struct GNUNET_TIME_AbsoluteNBO a)
Convert absolute time from network byte order.
Definition: time.c:737
struct GNUNET_TIME_Absolute GNUNET_TIME_relative_to_absolute(struct GNUNET_TIME_Relative rel)
Convert relative time to an absolute time in the future.
Definition: time.c:316
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_min(struct GNUNET_TIME_Absolute t1, struct GNUNET_TIME_Absolute t2)
Return the minimum of two absolute time values.
Definition: time.c:359
#define GNUNET_TIME_UNIT_ZERO_ABS
Absolute time zero.
#define GNUNET_TIME_UNIT_FOREVER_ABS
Constant used to specify "forever".
#define min(x, y)
#define _(String)
GNU gettext support macro.
Definition: platform.h:177
Public ECC key (always for Curve25519) encoded in a format suitable for network transmission and ECDS...
Public ECC key (always for curve Ed25519) encoded in a format suitable for network transmission and E...
uint32_t type
The zone type (GNUNET_GNSRECORD_TYPE_PKEY)
struct GNUNET_GNSRECORD_EcdsaBlock ecdsa_block
struct GNUNET_GNSRECORD_EddsaBlock eddsa_block
uint32_t size
Size of the block.
uint32_t record_type
Type of the GNS/DNS record.
const void * data
Binary value stored in the DNS record.
size_t data_size
Number of bytes in data.
enum GNUNET_GNSRECORD_Flags flags
Flags for the record.
uint64_t expiration_time
Expiration time for the DNS record.
struct GNUNET_CRYPTO_EcdsaPublicKey derived_key
Derived key used for signing; hash of this is the query.
struct GNUNET_CRYPTO_EddsaPublicKey derived_key
Derived key used for signing; hash of this is the query.
A 512-bit hashcode.
An identity key as per LSD0001.
Time for absolute times used by GNUnet, in microseconds.
uint64_t abs_value_us
The actual value.
Time for relative time used by GNUnet, in microseconds.
enum GNUNET_TESTBED_UnderlayLinkModelType type
the type of this model