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.c898
1 files changed, 0 insertions, 898 deletions
diff --git a/src/hello/hello-uri.c b/src/hello/hello-uri.c
deleted file mode 100644
index dd191738f..000000000
--- a/src/hello/hello-uri.c
+++ /dev/null
@@ -1,898 +0,0 @@
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_log (GNUNET_ERROR_TYPE_DEBUG,
226 "Hashing over %.*s\n",
227 (int) a->uri_len,
228 a->uri);
229 GNUNET_CRYPTO_hash_context_read (hc,
230 a->uri,
231 a->uri_len);
232 }
233 GNUNET_CRYPTO_hash_context_finish (hc,
234 hash);
235
236}
237
238
239/**
240 * Create HELLO signature.
241 *
242 * @param builder the builder to use
243 * @param et expiration time to sign
244 * @param priv key to sign with
245 * @param[out] sig where to write the signature
246 */
247static void
248sign_hello (const struct GNUNET_HELLO_Builder *builder,
249 struct GNUNET_TIME_Timestamp et,
250 const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
251 struct GNUNET_CRYPTO_EddsaSignature *sig)
252{
253 struct HelloSignaturePurpose hsp = {
254 .purpose.size = htonl (sizeof (hsp)),
255 .purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_HELLO),
256 .expiration_time = GNUNET_TIME_absolute_hton (et.abs_time)
257 };
258
259 hash_addresses (builder,
260 &hsp.h_addrs);
261 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
262 "Address hash is %s\n",
263 GNUNET_h2s_full (&hsp.h_addrs));
264 GNUNET_CRYPTO_eddsa_sign (priv,
265 &hsp,
266 sig);
267}
268
269
270/**
271 * Verify HELLO signature.
272 *
273 * @param builder the builder to use
274 * @param et expiration time to verify
275 * @param sig signature to verify
276 * @return #GNUNET_OK if everything is ok, #GNUNET_NO if the
277 * HELLO expired, #GNUNET_SYSERR if the signature is wrong
278 */
279static enum GNUNET_GenericReturnValue
280verify_hello (const struct GNUNET_HELLO_Builder *builder,
281 struct GNUNET_TIME_Absolute et,
282 const struct GNUNET_CRYPTO_EddsaSignature *sig)
283{
284 struct HelloSignaturePurpose hsp = {
285 .purpose.size = htonl (sizeof (hsp)),
286 .purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_HELLO),
287 .expiration_time = GNUNET_TIME_absolute_hton (et)
288 };
289
290 hash_addresses (builder,
291 &hsp.h_addrs);
292 if (GNUNET_OK !=
293 GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_HELLO,
294 &hsp,
295 sig,
296 &builder->pid.public_key))
297 {
298 GNUNET_break_op (0);
299 return GNUNET_SYSERR;
300 }
301 if (GNUNET_TIME_absolute_is_past (et))
302 return GNUNET_NO;
303 return GNUNET_OK;
304}
305
306
307struct GNUNET_HELLO_Builder *
308GNUNET_HELLO_builder_new (const struct GNUNET_PeerIdentity *pid)
309{
310 struct GNUNET_HELLO_Builder *builder;
311
312 builder = GNUNET_new (struct GNUNET_HELLO_Builder);
313 builder->pid = *pid;
314 return builder;
315}
316
317
318void
319GNUNET_HELLO_builder_free (struct GNUNET_HELLO_Builder *builder)
320{
321 struct Address *a;
322
323 while (NULL != (a = builder->a_head))
324 {
325 GNUNET_CONTAINER_DLL_remove (builder->a_head,
326 builder->a_tail,
327 a);
328 builder->a_length--;
329 GNUNET_free (a);
330 }
331 GNUNET_assert (0 == builder->a_length);
332 GNUNET_free (builder);
333}
334
335
336struct GNUNET_HELLO_Builder *
337GNUNET_HELLO_builder_from_msg (const struct GNUNET_MessageHeader *msg)
338{
339 const struct HelloUriMessage *h;
340 uint16_t size = ntohs (msg->size);
341
342 if (GNUNET_MESSAGE_TYPE_HELLO_URI != ntohs (msg->type))
343 {
344 GNUNET_break (0);
345 return NULL;
346 }
347 if (sizeof (struct HelloUriMessage) > size)
348 {
349 GNUNET_break_op (0);
350 return NULL;
351 }
352 h = (const struct HelloUriMessage *) msg;
353 size -= sizeof (*h);
354 return GNUNET_HELLO_builder_from_block (&h[1],
355 size);
356}
357
358
359struct GNUNET_HELLO_Builder *
360GNUNET_HELLO_builder_from_block (const void *block,
361 size_t block_size)
362{
363 const struct BlockHeader *bh = block;
364 struct GNUNET_HELLO_Builder *b;
365
366 if (block_size < sizeof (*bh))
367 {
368 GNUNET_break_op (0);
369 return NULL;
370 }
371 b = GNUNET_HELLO_builder_new (&bh->pid);
372 block += sizeof (*bh);
373 block_size -= sizeof (*bh);
374 while (block_size > 0)
375 {
376 const void *end = memchr (block,
377 '\0',
378 block_size);
379
380 if (NULL == end)
381 {
382 GNUNET_break_op (0);
383 GNUNET_HELLO_builder_free (b);
384 return NULL;
385 }
386 if (GNUNET_OK !=
387 GNUNET_HELLO_builder_add_address (b,
388 block))
389 {
390 GNUNET_break_op (0);
391 GNUNET_HELLO_builder_free (b);
392 return NULL;
393 }
394 end++;
395 block_size -= (end - block);
396 block = end;
397 }
398 {
399 enum GNUNET_GenericReturnValue ret;
400
401 ret = verify_hello (b,
402 GNUNET_TIME_absolute_ntoh (bh->expiration_time),
403 &bh->sig);
404 GNUNET_break (GNUNET_SYSERR != ret);
405 if (GNUNET_OK != ret)
406 {
407 GNUNET_HELLO_builder_free (b);
408 return NULL;
409 }
410 }
411 return b;
412}
413
414
415struct GNUNET_HELLO_Builder *
416GNUNET_HELLO_builder_from_url (const char *url)
417{
418 const char *q;
419 const char *s1;
420 const char *s2;
421 struct GNUNET_PeerIdentity pid;
422 struct GNUNET_CRYPTO_EddsaSignature sig;
423 struct GNUNET_TIME_Absolute et;
424 size_t len;
425 struct GNUNET_HELLO_Builder *b;
426
427 if (0 != strncasecmp (url,
428 "gnunet://hello/",
429 strlen ("gnunet://hello/")))
430 return NULL;
431 url += strlen ("gnunet://hello/");
432 s1 = strchr (url, '/');
433 if (NULL == s1)
434 {
435 GNUNET_break_op (0);
436 return NULL;
437 }
438 s2 = strchr (s1 + 1, '/');
439 if (NULL == s1)
440 {
441 GNUNET_break_op (0);
442 return NULL;
443 }
444 q = strchr (url, '?');
445 if (NULL == q)
446 q = url + strlen (url);
447 if (GNUNET_OK !=
448 GNUNET_STRINGS_string_to_data (url,
449 s1 - url,
450 &pid,
451 sizeof(pid)))
452 {
453 GNUNET_break_op (0);
454 return NULL;
455 }
456 if (GNUNET_OK !=
457 GNUNET_STRINGS_string_to_data (s1 + 1,
458 s2 - (s1 + 1),
459 &sig,
460 sizeof(sig)))
461 {
462 GNUNET_break_op (0);
463 return NULL;
464 }
465 {
466 unsigned long long sec;
467 char dummy = '?';
468
469 if ( (0 == sscanf (s2 + 1,
470 "%llu%c",
471 &sec,
472 &dummy)) ||
473 ('?' != dummy) )
474 {
475 GNUNET_break_op (0);
476 return NULL;
477 }
478 et = GNUNET_TIME_absolute_from_s (sec);
479 }
480
481 b = GNUNET_HELLO_builder_new (&pid);
482 len = strlen (q);
483 while (len > 0)
484 {
485 const char *eq;
486 const char *amp;
487 char *addr = NULL;
488 char *uri;
489
490 /* skip ?/& separator */
491 len--;
492 q++;
493 eq = strchr (q, '=');
494 if ( (eq == q) ||
495 (NULL == eq) )
496 {
497 GNUNET_break_op (0);
498 GNUNET_HELLO_builder_free (b);
499 return NULL;
500 }
501 amp = strchr (eq, '&');
502 if (NULL == amp)
503 amp = &q[len];
504 GNUNET_STRINGS_urldecode (eq + 1,
505 amp - (eq + 1),
506 &addr);
507 if ( (NULL == addr) ||
508 (0 == strlen (addr)) )
509 {
510 GNUNET_free (addr);
511 GNUNET_break_op (0);
512 GNUNET_HELLO_builder_free (b);
513 return NULL;
514 }
515 GNUNET_asprintf (&uri,
516 "%.*s://%s",
517 (int) (eq - q),
518 q,
519 addr);
520 GNUNET_free (addr);
521 if (GNUNET_OK !=
522 GNUNET_HELLO_builder_add_address (b,
523 uri))
524 {
525 GNUNET_break_op (0);
526 GNUNET_free (uri);
527 GNUNET_HELLO_builder_free (b);
528 return NULL;
529 }
530 GNUNET_free (uri);
531 /* move to next URL */
532 len -= (amp - q);
533 q = amp;
534 }
535
536 {
537 enum GNUNET_GenericReturnValue ret;
538
539 ret = verify_hello (b,
540 et,
541 &sig);
542 GNUNET_break (GNUNET_SYSERR != ret);
543 if (GNUNET_OK != ret)
544 {
545 GNUNET_HELLO_builder_free (b);
546 return NULL;
547 }
548 }
549 return b;
550}
551
552
553struct GNUNET_MQ_Envelope *
554GNUNET_HELLO_builder_to_env (const struct GNUNET_HELLO_Builder *builder,
555 const struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
556{
557 struct GNUNET_MQ_Envelope *env;
558 struct HelloUriMessage *msg;
559 size_t blen;
560
561 if (builder->a_length > UINT16_MAX)
562 {
563 GNUNET_break (0);
564 return NULL;
565 }
566 blen = 0;
567 GNUNET_assert (GNUNET_NO ==
568 GNUNET_HELLO_builder_to_block (builder,
569 priv,
570 NULL,
571 &blen));
572 env = GNUNET_MQ_msg_extra (msg,
573 blen,
574 GNUNET_MESSAGE_TYPE_HELLO_URI);
575 msg->url_counter = htons ((uint16_t) builder->a_length);
576 GNUNET_assert (GNUNET_OK ==
577 GNUNET_HELLO_builder_to_block (builder,
578 priv,
579 &msg[1],
580 &blen));
581 return env;
582}
583
584
585struct GNUNET_MessageHeader *
586GNUNET_HELLO_builder_to_dht_hello_msg (
587 const struct GNUNET_HELLO_Builder *builder,
588 const struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
589{
590 struct DhtHelloMessage *msg;
591 size_t blen;
592
593 if (builder->a_length > UINT16_MAX)
594 {
595 GNUNET_break (0);
596 return NULL;
597 }
598 blen = 0;
599 GNUNET_assert (GNUNET_NO ==
600 GNUNET_HELLO_builder_to_block (builder,
601 priv,
602 NULL,
603 &blen));
604 GNUNET_assert (blen < UINT16_MAX);
605 GNUNET_assert (blen >= sizeof (struct BlockHeader));
606 {
607 char buf[blen] GNUNET_ALIGN;
608 const struct BlockHeader *block = (const struct BlockHeader *) buf;
609
610 GNUNET_assert (GNUNET_OK ==
611 GNUNET_HELLO_builder_to_block (builder,
612 priv,
613 buf,
614 &blen));
615 msg = GNUNET_malloc (sizeof (*msg)
616 + blen
617 - sizeof (*block));
618 msg->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_HELLO);
619 msg->header.size = htons (sizeof (*msg)
620 + blen
621 - sizeof (*block));
622 memcpy (&msg[1],
623 &block[1],
624 blen - sizeof (*block));
625 msg->sig = block->sig;
626 msg->expiration_time = block->expiration_time;
627 }
628 msg->url_counter = htons ((uint16_t) builder->a_length);
629 return &msg->header;
630}
631
632
633char *
634GNUNET_HELLO_builder_to_url (const struct GNUNET_HELLO_Builder *builder,
635 const struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
636{
637 struct GNUNET_CRYPTO_EddsaSignature sig;
638 struct GNUNET_TIME_Timestamp et;
639 char *result;
640 char *pids;
641 char *sigs;
642 const char *sep = "?";
643
644 et = GNUNET_TIME_relative_to_timestamp (GNUNET_HELLO_ADDRESS_EXPIRATION);
645 sign_hello (builder,
646 et,
647 priv,
648 &sig);
649 pids = GNUNET_STRINGS_data_to_string_alloc (&builder->pid,
650 sizeof (builder->pid));
651 sigs = GNUNET_STRINGS_data_to_string_alloc (&sig,
652 sizeof (sig));
653 GNUNET_asprintf (&result,
654 "gnunet://hello/%s/%s/%llu",
655 pids,
656 sigs,
657 (unsigned long long) GNUNET_TIME_timestamp_to_s (et));
658 GNUNET_free (sigs);
659 GNUNET_free (pids);
660 for (struct Address *a = builder->a_head;
661 NULL != a;
662 a = a->next)
663 {
664 char *ue;
665 char *tmp;
666 int pfx_len;
667 const char *eou;
668
669 eou = strstr (a->uri,
670 "://");
671 if (NULL == eou)
672 {
673 GNUNET_break (0);
674 GNUNET_free (result);
675 return NULL;
676 }
677 pfx_len = eou - a->uri;
678 eou += 3;
679 GNUNET_STRINGS_urlencode (eou,
680 a->uri_len - 4 - pfx_len,
681 &ue);
682 GNUNET_asprintf (&tmp,
683 "%s%s%.*s=%s",
684 result,
685 sep,
686 pfx_len,
687 a->uri,
688 ue);
689 GNUNET_free (ue);
690 GNUNET_free (result);
691 result = tmp;
692 sep = "&";
693 }
694 return result;
695}
696
697
698enum GNUNET_GenericReturnValue
699GNUNET_HELLO_builder_to_block (const struct GNUNET_HELLO_Builder *builder,
700 const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
701 void *block,
702 size_t *block_size)
703{
704 struct BlockHeader bh;
705 size_t needed = sizeof (bh);
706 char *pos;
707 struct GNUNET_TIME_Timestamp et;
708
709 for (struct Address *a = builder->a_head;
710 NULL != a;
711 a = a->next)
712 {
713 GNUNET_assert (needed + a->uri_len > needed);
714 needed += a->uri_len;
715 }
716 if ( (NULL == block) ||
717 (needed < *block_size) )
718 {
719 *block_size = needed;
720 return GNUNET_NO;
721 }
722 bh.pid = builder->pid;
723 et = GNUNET_TIME_relative_to_timestamp (GNUNET_HELLO_ADDRESS_EXPIRATION);
724 bh.expiration_time = GNUNET_TIME_absolute_hton (et.abs_time);
725 sign_hello (builder,
726 et,
727 priv,
728 &bh.sig);
729 memcpy (block,
730 &bh,
731 sizeof (bh));
732 pos = block + sizeof (bh);
733 for (struct Address *a = builder->a_head;
734 NULL != a;
735 a = a->next)
736 {
737 memcpy (pos,
738 a->uri,
739 a->uri_len);
740 pos += a->uri_len;
741 }
742 *block_size = needed;
743 return GNUNET_OK;
744}
745
746
747enum GNUNET_GenericReturnValue
748GNUNET_HELLO_builder_add_address (struct GNUNET_HELLO_Builder *builder,
749 const char *address)
750{
751 size_t alen = strlen (address) + 1;
752 struct Address *a;
753 const char *e;
754
755 if (NULL == (e = strstr (address,
756 "://")))
757 {
758 GNUNET_break_op (0);
759 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
760 "Invalid address `%s'\n",
761 address);
762 return GNUNET_SYSERR;
763 }
764 if (e == address)
765 {
766 GNUNET_break_op (0);
767 return GNUNET_SYSERR;
768 }
769 for (const char *p = address; p != e; p++)
770 if ( (! isalpha ((unsigned char) *p)) &&
771 ('+' != *p) )
772 {
773 GNUNET_break_op (0);
774 return GNUNET_SYSERR;
775 }
776 /* check for duplicates */
777 for (a = builder->a_head;
778 NULL != a;
779 a = a->next)
780 if (0 == strcmp (address,
781 a->uri))
782 return GNUNET_NO;
783 a = GNUNET_malloc (sizeof (struct Address) + alen);
784 a->uri_len = alen;
785 memcpy (&a[1],
786 address,
787 alen);
788 a->uri = (const char *) &a[1];
789 GNUNET_CONTAINER_DLL_insert_tail (builder->a_head,
790 builder->a_tail,
791 a);
792 builder->a_length++;
793 return GNUNET_OK;
794}
795
796
797enum GNUNET_GenericReturnValue
798GNUNET_HELLO_builder_del_address (struct GNUNET_HELLO_Builder *builder,
799 const char *address)
800{
801 struct Address *a;
802
803 /* check for duplicates */
804 for (a = builder->a_head;
805 NULL != a;
806 a = a->next)
807 if (0 == strcmp (address,
808 a->uri))
809 break;
810 if (NULL == a)
811 return GNUNET_NO;
812 GNUNET_CONTAINER_DLL_remove (builder->a_head,
813 builder->a_tail,
814 a);
815 builder->a_length--;
816 GNUNET_free (a);
817 return GNUNET_OK;
818}
819
820
821void
822GNUNET_HELLO_builder_iterate (const struct GNUNET_HELLO_Builder *builder,
823 struct GNUNET_PeerIdentity *pid,
824 GNUNET_HELLO_UriCallback uc,
825 void *uc_cls)
826{
827 struct Address *nxt;
828
829 *pid = builder->pid;
830 if (NULL == uc)
831 return;
832 for (struct Address *a = builder->a_head;
833 NULL != a;
834 a = nxt)
835 {
836 nxt = a->next;
837 uc (uc_cls,
838 a->uri);
839 }
840}
841
842
843enum GNUNET_GenericReturnValue
844GNUNET_HELLO_dht_msg_to_block (const struct GNUNET_MessageHeader *hello,
845 const struct GNUNET_PeerIdentity *pid,
846 void **block,
847 size_t *block_size,
848 struct GNUNET_TIME_Absolute *block_expiration)
849{
850 const struct DhtHelloMessage *msg
851 = (const struct DhtHelloMessage *) hello;
852 uint16_t len = ntohs (hello->size);
853 struct BlockHeader *bh;
854 struct GNUNET_HELLO_Builder *b;
855 enum GNUNET_GenericReturnValue ret;
856
857 if (GNUNET_MESSAGE_TYPE_DHT_P2P_HELLO != ntohs (hello->type))
858 {
859 GNUNET_break (0);
860 return GNUNET_SYSERR;
861 }
862 if (len < sizeof (*msg))
863 {
864 GNUNET_break_op (0);
865 return GNUNET_SYSERR;
866 }
867 len -= sizeof (*msg);
868 *block_size = len + sizeof (*bh);
869 *block = GNUNET_malloc (*block_size);
870 bh = *block;
871 bh->pid = *pid;
872 bh->sig = msg->sig;
873 bh->expiration_time = msg->expiration_time;
874 *block_expiration = GNUNET_TIME_absolute_ntoh (msg->expiration_time);
875 memcpy (&bh[1],
876 &msg[1],
877 len);
878 b = GNUNET_HELLO_builder_from_block (*block,
879 *block_size);
880 if (NULL == b)
881 {
882 GNUNET_break_op (0);
883 GNUNET_free (*block);
884 *block_size = 0;
885 return GNUNET_SYSERR;
886 }
887 ret = verify_hello (b,
888 *block_expiration,
889 &msg->sig);
890 GNUNET_HELLO_builder_free (b);
891 if (GNUNET_SYSERR == ret)
892 {
893 GNUNET_free (*block);
894 *block_size = 0;
895 return GNUNET_SYSERR;
896 }
897 return ret;
898}