aboutsummaryrefslogtreecommitdiff
path: root/src/hello/hello-uri.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/hello/hello-uri.c')
-rw-r--r--src/hello/hello-uri.c891
1 files changed, 891 insertions, 0 deletions
diff --git a/src/hello/hello-uri.c b/src/hello/hello-uri.c
new file mode 100644
index 000000000..bacaf697e
--- /dev/null
+++ b/src/hello/hello-uri.c
@@ -0,0 +1,891 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2022 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/**
22 * @file hello/hello-uri.c
23 * @brief helper library for handling URI-based HELLOs
24 * @author Christian Grothoff
25 *
26 * Note:
27 * - Current API does not support deserializing HELLO of
28 * another peer and then serializing it into another
29 * format (we always require the private key).
30 * Not sure if we need this, but if we do, we need
31 * to extend the builder and the API.
32 * - Current API does not allow overriding the default
33 * HELLO expiration time. We may want to add a function
34 * that does this to create bootstrap HELLOs shipped with
35 * the TGZ.
36 */
37#include "platform.h"
38#include "gnunet_signatures.h"
39#include "gnunet_hello_uri_lib.h"
40#include "gnunet_protocols.h"
41#include "gnunet_util_lib.h"
42
43
44GNUNET_NETWORK_STRUCT_BEGIN
45
46/**
47 * Message signed as part of a HELLO block/URL.
48 */
49struct HelloSignaturePurpose
50{
51 /**
52 * Purpose must be #GNUNET_SIGNATURE_PURPOSE_HELLO
53 */
54 struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
55
56 /**
57 * When does the signature expire?
58 */
59 struct GNUNET_TIME_AbsoluteNBO expiration_time;
60
61 /**
62 * Hash over all addresses.
63 */
64 struct GNUNET_HashCode h_addrs;
65
66};
67
68/**
69 * Message used when gossiping HELLOs between peers.
70 */
71struct HelloUriMessage
72{
73 /**
74 * Type must be #GNUNET_MESSAGE_TYPE_HELLO_URI
75 */
76 struct GNUNET_MessageHeader header;
77
78 /**
79 * Reserved. 0.
80 */
81 uint16_t reserved GNUNET_PACKED;
82
83 /**
84 * Number of URLs encoded after the end of the struct, in NBO.
85 */
86 uint16_t url_counter GNUNET_PACKED;
87
88 /* followed by a 'block' */
89};
90
91
92/**
93 * Start of a 'block'.
94 */
95struct BlockHeader
96{
97 /**
98 * Public key of the peer.
99 */
100 struct GNUNET_PeerIdentity pid;
101
102 /**
103 * Signature over the block, of purpose #GNUNET_SIGNATURE_PURPOSE_HELLO.
104 */
105 struct GNUNET_CRYPTO_EddsaSignature sig;
106
107 /**
108 * When does the HELLO expire?
109 */
110 struct GNUNET_TIME_AbsoluteNBO expiration_time;
111
112};
113
114
115/**
116 * Message used when a DHT provides its HELLO to direct
117 * neighbours.
118 */
119struct DhtHelloMessage
120{
121 /**
122 * Type must be #GNUNET_MESSAGE_TYPE_DHT_P2P_HELLO
123 */
124 struct GNUNET_MessageHeader header;
125
126 /**
127 * Reserved. 0.
128 */
129 uint16_t reserved GNUNET_PACKED;
130
131 /**
132 * Number of URLs encoded after the end of the struct, in NBO.
133 */
134 uint16_t url_counter GNUNET_PACKED;
135
136 /**
137 * Signature over the block, of purpose #GNUNET_SIGNATURE_PURPOSE_HELLO.
138 */
139 struct GNUNET_CRYPTO_EddsaSignature sig;
140
141 /**
142 * When does the HELLO expire?
143 */
144 struct GNUNET_TIME_AbsoluteNBO expiration_time;
145
146 /* followed by the serialized addresses of the 'block' */
147};
148
149
150GNUNET_NETWORK_STRUCT_END
151
152
153/**
154 * Address of a peer.
155 */
156struct Address
157{
158 /**
159 * Kept in a DLL.
160 */
161 struct Address *next;
162
163 /**
164 * Kept in a DLL.
165 */
166 struct Address *prev;
167
168 /**
169 * Actual URI, allocated at the end of this struct.
170 */
171 const char *uri;
172
173 /**
174 * Length of @a uri including 0-terminator.
175 */
176 size_t uri_len;
177};
178
179
180/**
181 * Context for building (or parsing) HELLO URIs.
182 */
183struct GNUNET_HELLO_Builder
184{
185 /**
186 * Public key of the peer.
187 */
188 struct GNUNET_PeerIdentity pid;
189
190 /**
191 * Head of the addresses DLL.
192 */
193 struct Address *a_head;
194
195 /**
196 * Tail of the addresses DLL.
197 */
198 struct Address *a_tail;
199
200 /**
201 * Length of the @a a_head DLL.
202 */
203 unsigned int a_length;
204
205};
206
207
208/**
209 * Compute @a hash over addresses in @a builder.
210 *
211 * @param builder the builder to hash addresses of
212 * @param[out] hash where to write the hash
213 */
214static void
215hash_addresses (const struct GNUNET_HELLO_Builder *builder,
216 struct GNUNET_HashCode *hash)
217{
218 struct GNUNET_HashContext *hc;
219
220 hc = GNUNET_CRYPTO_hash_context_start ();
221 for (struct Address *a = builder->a_head;
222 NULL != a;
223 a = a->next)
224 {
225 GNUNET_CRYPTO_hash_context_read (hc,
226 a->uri,
227 a->uri_len);
228 }
229 GNUNET_CRYPTO_hash_context_finish (hc,
230 hash);
231
232}
233
234
235/**
236 * Create HELLO signature.
237 *
238 * @param builder the builder to use
239 * @param et expiration time to sign
240 * @param priv key to sign with
241 * @param[out] sig where to write the signature
242 */
243static void
244sign_hello (const struct GNUNET_HELLO_Builder *builder,
245 struct GNUNET_TIME_Timestamp et,
246 const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
247 struct GNUNET_CRYPTO_EddsaSignature *sig)
248{
249 struct HelloSignaturePurpose hsp = {
250 .purpose.size = htonl (sizeof (hsp)),
251 .purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_HELLO),
252 .expiration_time = GNUNET_TIME_absolute_hton (et.abs_time)
253 };
254
255 hash_addresses (builder,
256 &hsp.h_addrs);
257 GNUNET_CRYPTO_eddsa_sign (priv,
258 &hsp,
259 sig);
260}
261
262
263/**
264 * Verify HELLO signature.
265 *
266 * @param builder the builder to use
267 * @param et expiration time to verify
268 * @param sig signature to verify
269 * @return #GNUNET_OK if everything is ok, #GNUNET_NO if the
270 * HELLO expired, #GNUNET_SYSERR if the signature is wrong
271 */
272static enum GNUNET_GenericReturnValue
273verify_hello (const struct GNUNET_HELLO_Builder *builder,
274 struct GNUNET_TIME_Absolute et,
275 const struct GNUNET_CRYPTO_EddsaSignature *sig)
276{
277 struct HelloSignaturePurpose hsp = {
278 .purpose.size = htonl (sizeof (hsp)),
279 .purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_HELLO),
280 .expiration_time = GNUNET_TIME_absolute_hton (et)
281 };
282
283 hash_addresses (builder,
284 &hsp.h_addrs);
285 if (GNUNET_OK !=
286 GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_HELLO,
287 &hsp,
288 sig,
289 &builder->pid.public_key))
290 {
291 GNUNET_break_op (0);
292 return GNUNET_SYSERR;
293 }
294 if (GNUNET_TIME_absolute_is_past (et))
295 return GNUNET_NO;
296 return GNUNET_OK;
297}
298
299
300struct GNUNET_HELLO_Builder *
301GNUNET_HELLO_builder_new (const struct GNUNET_PeerIdentity *pid)
302{
303 struct GNUNET_HELLO_Builder *builder;
304
305 builder = GNUNET_new (struct GNUNET_HELLO_Builder);
306 builder->pid = *pid;
307 return builder;
308}
309
310
311void
312GNUNET_HELLO_builder_free (struct GNUNET_HELLO_Builder *builder)
313{
314 struct Address *a;
315
316 while (NULL != (a = builder->a_head))
317 {
318 GNUNET_CONTAINER_DLL_remove (builder->a_head,
319 builder->a_tail,
320 a);
321 builder->a_length--;
322 GNUNET_free (a);
323 }
324 GNUNET_assert (0 == builder->a_length);
325 GNUNET_free (builder);
326}
327
328
329struct GNUNET_HELLO_Builder *
330GNUNET_HELLO_builder_from_msg (const struct GNUNET_MessageHeader *msg)
331{
332 const struct HelloUriMessage *h;
333 uint16_t size = ntohs (msg->size);
334
335 if (GNUNET_MESSAGE_TYPE_HELLO_URI != ntohs (msg->type))
336 {
337 GNUNET_break (0);
338 return NULL;
339 }
340 if (sizeof (struct HelloUriMessage) > size)
341 {
342 GNUNET_break_op (0);
343 return NULL;
344 }
345 h = (const struct HelloUriMessage *) msg;
346 size -= sizeof (*h);
347 return GNUNET_HELLO_builder_from_block (&h[1],
348 size);
349}
350
351
352struct GNUNET_HELLO_Builder *
353GNUNET_HELLO_builder_from_block (const void *block,
354 size_t block_size)
355{
356 const struct BlockHeader *bh = block;
357 struct GNUNET_HELLO_Builder *b;
358
359 if (block_size < sizeof (*bh))
360 {
361 GNUNET_break_op (0);
362 return NULL;
363 }
364 b = GNUNET_HELLO_builder_new (&bh->pid);
365 block += sizeof (*bh);
366 block_size -= sizeof (*bh);
367 while (block_size > 0)
368 {
369 const void *end = memchr (block,
370 '\0',
371 block_size);
372
373 if (NULL == end)
374 {
375 GNUNET_break_op (0);
376 GNUNET_HELLO_builder_free (b);
377 return NULL;
378 }
379 if (GNUNET_OK !=
380 GNUNET_HELLO_builder_add_address (b,
381 block))
382 {
383 GNUNET_break_op (0);
384 GNUNET_HELLO_builder_free (b);
385 return NULL;
386 }
387 end++;
388 block_size -= (end - block);
389 block = end;
390 }
391 {
392 enum GNUNET_GenericReturnValue ret;
393
394 ret = verify_hello (b,
395 GNUNET_TIME_absolute_ntoh (bh->expiration_time),
396 &bh->sig);
397 GNUNET_break (GNUNET_SYSERR != ret);
398 if (GNUNET_OK != ret)
399 {
400 GNUNET_HELLO_builder_free (b);
401 return NULL;
402 }
403 }
404 return b;
405}
406
407
408struct GNUNET_HELLO_Builder *
409GNUNET_HELLO_builder_from_url (const char *url)
410{
411 const char *q;
412 const char *s1;
413 const char *s2;
414 struct GNUNET_PeerIdentity pid;
415 struct GNUNET_CRYPTO_EddsaSignature sig;
416 struct GNUNET_TIME_Absolute et;
417 size_t len;
418 struct GNUNET_HELLO_Builder *b;
419
420 if (0 != strncasecmp (url,
421 "gnunet://hello/",
422 strlen ("gnunet://hello/")))
423 return NULL;
424 url += strlen ("gnunet://hello/");
425 s1 = strchr (url, '/');
426 if (NULL == s1)
427 {
428 GNUNET_break_op (0);
429 return NULL;
430 }
431 s2 = strchr (s1 + 1, '/');
432 if (NULL == s1)
433 {
434 GNUNET_break_op (0);
435 return NULL;
436 }
437 q = strchr (url, '?');
438 if (NULL == q)
439 q = url + strlen (url);
440 if (GNUNET_OK !=
441 GNUNET_STRINGS_string_to_data (url,
442 s1 - url,
443 &pid,
444 sizeof(pid)))
445 {
446 GNUNET_break_op (0);
447 return NULL;
448 }
449 if (GNUNET_OK !=
450 GNUNET_STRINGS_string_to_data (s1 + 1,
451 s2 - (s1 + 1),
452 &sig,
453 sizeof(sig)))
454 {
455 GNUNET_break_op (0);
456 return NULL;
457 }
458 {
459 unsigned long long sec;
460 char dummy = '?';
461
462 if ( (0 == sscanf (s2 + 1,
463 "%llu%c",
464 &sec,
465 &dummy)) ||
466 ('?' != dummy) )
467 {
468 GNUNET_break_op (0);
469 return NULL;
470 }
471 et = GNUNET_TIME_absolute_from_s (sec);
472 }
473
474 b = GNUNET_HELLO_builder_new (&pid);
475 len = strlen (q);
476 while (len > 0)
477 {
478 const char *eq;
479 const char *amp;
480 char *addr = NULL;
481 char *uri;
482
483 /* skip ?/& separator */
484 len--;
485 q++;
486 eq = strchr (q, '=');
487 if ( (eq == q) ||
488 (NULL == eq) )
489 {
490 GNUNET_break_op (0);
491 GNUNET_HELLO_builder_free (b);
492 return NULL;
493 }
494 amp = strchr (eq, '&');
495 if (NULL == amp)
496 amp = &q[len];
497 GNUNET_STRINGS_urldecode (eq + 1,
498 amp - (eq + 1),
499 &addr);
500 if ( (NULL == addr) ||
501 (0 == strlen (addr)) )
502 {
503 GNUNET_free (addr);
504 GNUNET_break_op (0);
505 GNUNET_HELLO_builder_free (b);
506 return NULL;
507 }
508 GNUNET_asprintf (&uri,
509 "%.*s://%s",
510 (int) (eq - q),
511 q,
512 addr);
513 GNUNET_free (addr);
514 if (GNUNET_OK !=
515 GNUNET_HELLO_builder_add_address (b,
516 uri))
517 {
518 GNUNET_break_op (0);
519 GNUNET_free (uri);
520 GNUNET_HELLO_builder_free (b);
521 return NULL;
522 }
523 GNUNET_free (uri);
524 /* move to next URL */
525 len -= (amp - q);
526 q = amp;
527 }
528
529 {
530 enum GNUNET_GenericReturnValue ret;
531
532 ret = verify_hello (b,
533 et,
534 &sig);
535 GNUNET_break (GNUNET_SYSERR != ret);
536 if (GNUNET_OK != ret)
537 {
538 GNUNET_HELLO_builder_free (b);
539 return NULL;
540 }
541 }
542 return b;
543}
544
545
546struct GNUNET_MQ_Envelope *
547GNUNET_HELLO_builder_to_env (const struct GNUNET_HELLO_Builder *builder,
548 const struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
549{
550 struct GNUNET_MQ_Envelope *env;
551 struct HelloUriMessage *msg;
552 size_t blen;
553
554 if (builder->a_length > UINT16_MAX)
555 {
556 GNUNET_break (0);
557 return NULL;
558 }
559 blen = 0;
560 GNUNET_assert (GNUNET_NO ==
561 GNUNET_HELLO_builder_to_block (builder,
562 priv,
563 NULL,
564 &blen));
565 env = GNUNET_MQ_msg_extra (msg,
566 blen,
567 GNUNET_MESSAGE_TYPE_HELLO_URI);
568 msg->url_counter = htonl ((uint16_t) builder->a_length);
569 GNUNET_assert (GNUNET_OK ==
570 GNUNET_HELLO_builder_to_block (builder,
571 priv,
572 &msg[1],
573 &blen));
574 return env;
575}
576
577
578struct GNUNET_MessageHeader *
579GNUNET_HELLO_builder_to_dht_hello_msg (
580 const struct GNUNET_HELLO_Builder *builder,
581 const struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
582{
583 struct DhtHelloMessage *msg;
584 size_t blen;
585
586 if (builder->a_length > UINT16_MAX)
587 {
588 GNUNET_break (0);
589 return NULL;
590 }
591 blen = 0;
592 GNUNET_assert (GNUNET_NO ==
593 GNUNET_HELLO_builder_to_block (builder,
594 priv,
595 NULL,
596 &blen));
597 GNUNET_assert (blen < UINT16_MAX);
598 GNUNET_assert (blen >= sizeof (struct BlockHeader));
599 {
600 char buf[blen] GNUNET_ALIGN;
601 const struct BlockHeader *block = (const struct BlockHeader *) buf;
602
603 GNUNET_assert (GNUNET_OK ==
604 GNUNET_HELLO_builder_to_block (builder,
605 priv,
606 buf,
607 &blen));
608 msg = GNUNET_malloc (sizeof (*msg)
609 + blen
610 - sizeof (*block));
611 msg->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_HELLO);
612 msg->header.size = htons (sizeof (*msg)
613 + blen
614 - sizeof (*block));
615 memcpy (&msg[1],
616 &block[1],
617 blen - sizeof (*block));
618 msg->sig = block->sig;
619 msg->expiration_time = block->expiration_time;
620 }
621 msg->url_counter = htonl ((uint16_t) builder->a_length);
622 return &msg->header;
623}
624
625
626char *
627GNUNET_HELLO_builder_to_url (const struct GNUNET_HELLO_Builder *builder,
628 const struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
629{
630 struct GNUNET_CRYPTO_EddsaSignature sig;
631 struct GNUNET_TIME_Timestamp et;
632 char *result;
633 char *pids;
634 char *sigs;
635 const char *sep = "?";
636
637 et = GNUNET_TIME_relative_to_timestamp (GNUNET_HELLO_ADDRESS_EXPIRATION);
638 sign_hello (builder,
639 et,
640 priv,
641 &sig);
642 pids = GNUNET_STRINGS_data_to_string_alloc (&builder->pid,
643 sizeof (builder->pid));
644 sigs = GNUNET_STRINGS_data_to_string_alloc (&sig,
645 sizeof (sig));
646 GNUNET_asprintf (&result,
647 "gnunet://hello/%s/%s/%llu",
648 pids,
649 sigs,
650 (unsigned long long) GNUNET_TIME_timestamp_to_s (et));
651 GNUNET_free (sigs);
652 GNUNET_free (pids);
653 for (struct Address *a = builder->a_head;
654 NULL != a;
655 a = a->next)
656 {
657 char *ue;
658 char *tmp;
659 int pfx_len;
660 const char *eou;
661
662 eou = strstr (a->uri,
663 "://");
664 if (NULL == eou)
665 {
666 GNUNET_break (0);
667 GNUNET_free (result);
668 return NULL;
669 }
670 pfx_len = eou - a->uri;
671 eou += 3;
672 GNUNET_STRINGS_urlencode (eou,
673 a->uri_len - 4 - pfx_len,
674 &ue);
675 GNUNET_asprintf (&tmp,
676 "%s%s%.*s=%s",
677 result,
678 sep,
679 pfx_len,
680 a->uri,
681 ue);
682 GNUNET_free (ue);
683 GNUNET_free (result);
684 result = tmp;
685 sep = "&";
686 }
687 return result;
688}
689
690
691enum GNUNET_GenericReturnValue
692GNUNET_HELLO_builder_to_block (const struct GNUNET_HELLO_Builder *builder,
693 const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
694 void *block,
695 size_t *block_size)
696{
697 struct BlockHeader bh;
698 size_t needed = sizeof (bh);
699 char *pos;
700 struct GNUNET_TIME_Timestamp et;
701
702 for (struct Address *a = builder->a_head;
703 NULL != a;
704 a = a->next)
705 {
706 GNUNET_assert (needed + a->uri_len > needed);
707 needed += a->uri_len;
708 }
709 if ( (NULL == block) ||
710 (needed < *block_size) )
711 {
712 *block_size = needed;
713 return GNUNET_NO;
714 }
715 bh.pid = builder->pid;
716 et = GNUNET_TIME_relative_to_timestamp (GNUNET_HELLO_ADDRESS_EXPIRATION);
717 bh.expiration_time = GNUNET_TIME_absolute_hton (et.abs_time);
718 sign_hello (builder,
719 et,
720 priv,
721 &bh.sig);
722 memcpy (block,
723 &bh,
724 sizeof (bh));
725 pos = block + sizeof (bh);
726 for (struct Address *a = builder->a_head;
727 NULL != a;
728 a = a->next)
729 {
730 memcpy (pos,
731 a->uri,
732 a->uri_len);
733 pos += a->uri_len;
734 }
735 *block_size = needed;
736 return GNUNET_OK;
737}
738
739
740enum GNUNET_GenericReturnValue
741GNUNET_HELLO_builder_add_address (struct GNUNET_HELLO_Builder *builder,
742 const char *address)
743{
744 size_t alen = strlen (address) + 1;
745 struct Address *a;
746 const char *e;
747
748 if (NULL == (e = strstr (address,
749 "://")))
750 {
751 GNUNET_break_op (0);
752 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
753 "Invalid address `%s'\n",
754 address);
755 return GNUNET_SYSERR;
756 }
757 if (e == address)
758 {
759 GNUNET_break_op (0);
760 return GNUNET_SYSERR;
761 }
762 for (const char *p = address; p != e; p++)
763 if ( (! isalpha ((unsigned char) *p)) &&
764 ('+' != *p) )
765 {
766 GNUNET_break_op (0);
767 return GNUNET_SYSERR;
768 }
769 /* check for duplicates */
770 for (a = builder->a_head;
771 NULL != a;
772 a = a->next)
773 if (0 == strcmp (address,
774 a->uri))
775 return GNUNET_NO;
776 a = GNUNET_malloc (sizeof (struct Address) + alen);
777 a->uri_len = alen;
778 memcpy (&a[1],
779 address,
780 alen);
781 a->uri = (const char *) &a[1];
782 GNUNET_CONTAINER_DLL_insert_tail (builder->a_head,
783 builder->a_tail,
784 a);
785 builder->a_length++;
786 return GNUNET_OK;
787}
788
789
790enum GNUNET_GenericReturnValue
791GNUNET_HELLO_builder_del_address (struct GNUNET_HELLO_Builder *builder,
792 const char *address)
793{
794 struct Address *a;
795
796 /* check for duplicates */
797 for (a = builder->a_head;
798 NULL != a;
799 a = a->next)
800 if (0 == strcmp (address,
801 a->uri))
802 break;
803 if (NULL == a)
804 return GNUNET_NO;
805 GNUNET_CONTAINER_DLL_remove (builder->a_head,
806 builder->a_tail,
807 a);
808 builder->a_length--;
809 GNUNET_free (a);
810 return GNUNET_OK;
811}
812
813
814void
815GNUNET_HELLO_builder_iterate (const struct GNUNET_HELLO_Builder *builder,
816 struct GNUNET_PeerIdentity *pid,
817 GNUNET_HELLO_UriCallback uc,
818 void *uc_cls)
819{
820 struct Address *nxt;
821
822 *pid = builder->pid;
823 if (NULL == uc)
824 return;
825 for (struct Address *a = builder->a_head;
826 NULL != a;
827 a = nxt)
828 {
829 nxt = a->next;
830 uc (uc_cls,
831 a->uri);
832 }
833}
834
835
836enum GNUNET_GenericReturnValue
837GNUNET_HELLO_dht_msg_to_block (const struct GNUNET_MessageHeader *hello,
838 const struct GNUNET_PeerIdentity *pid,
839 void **block,
840 size_t *block_size,
841 struct GNUNET_TIME_Absolute *block_expiration)
842{
843 const struct DhtHelloMessage *msg
844 = (const struct DhtHelloMessage *) hello;
845 uint16_t len = ntohs (hello->size);
846 struct BlockHeader *bh;
847 struct GNUNET_HELLO_Builder *b;
848 enum GNUNET_GenericReturnValue ret;
849
850 if (GNUNET_MESSAGE_TYPE_DHT_P2P_HELLO != ntohs (hello->type))
851 {
852 GNUNET_break (0);
853 return GNUNET_SYSERR;
854 }
855 if (len < sizeof (*msg))
856 {
857 GNUNET_break_op (0);
858 return GNUNET_SYSERR;
859 }
860 len -= sizeof (*msg);
861 *block_size = len + sizeof (*bh);
862 *block = GNUNET_malloc (*block_size);
863 bh = *block;
864 bh->pid = *pid;
865 bh->sig = msg->sig;
866 bh->expiration_time = msg->expiration_time;
867 *block_expiration = GNUNET_TIME_absolute_ntoh (msg->expiration_time);
868 memcpy (&bh[1],
869 &msg[1],
870 len);
871 b = GNUNET_HELLO_builder_from_block (*block,
872 *block_size);
873 if (NULL == b)
874 {
875 GNUNET_break_op (0);
876 GNUNET_free (*block);
877 *block_size = 0;
878 return GNUNET_SYSERR;
879 }
880 ret = verify_hello (b,
881 *block_expiration,
882 &msg->sig);
883 GNUNET_HELLO_builder_free (b);
884 if (GNUNET_SYSERR == ret)
885 {
886 GNUNET_free (*block);
887 *block_size = 0;
888 return GNUNET_SYSERR;
889 }
890 return ret;
891}