GNUnet  0.17.6
gnsrecord_serialization.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 #include "gnunet_dnsparser_lib.h"
35 #include "gnunet_tun_lib.h"
36 
37 
38 #define LOG(kind, ...) GNUNET_log_from (kind, "gnsrecord", __VA_ARGS__)
39 
44 #define DEBUG_GNSRECORDS 0
45 
47 
48 
53 {
59 
64 
68  uint16_t flags GNUNET_PACKED;
69 
74 
75 };
76 
78 
79 
88 ssize_t
89 GNUNET_GNSRECORD_records_get_size (unsigned int rd_count,
90  const struct GNUNET_GNSRECORD_Data *rd)
91 {
92  size_t ret;
93 
94  if (0 == rd_count)
95  return 0;
96 
97  ret = sizeof(struct NetworkRecord) * rd_count;
98  for (unsigned int i = 0; i < rd_count; i++)
99  {
100  if ((ret + rd[i].data_size) < ret)
101  {
102  GNUNET_break (0);
103  return -1;
104  }
105  ret += rd[i].data_size;
106 #if DEBUG_GNSRECORDS
107  {
108  char *str;
109 
111  rd[i].data,
112  rd[i].data_size);
113  if (NULL == str)
114  {
115  GNUNET_break_op (0);
116  return -1;
117  }
118  GNUNET_free (str);
119  }
120 #endif
121  }
122  if (ret > SSIZE_MAX)
123  {
124  GNUNET_break (0);
125  return -1;
126  }
127  // Do not pad PKEY
130  return ret;ret--;
136  ret |= ret >> 1;
137  ret |= ret >> 2;
138  ret |= ret >> 4;
139  ret |= ret >> 8;
140  ret |= ret >> 16;
141  ret++;
142  return (ssize_t) ret;
143 }
144 
145 
155 ssize_t
156 GNUNET_GNSRECORD_records_serialize (unsigned int rd_count,
157  const struct GNUNET_GNSRECORD_Data *rd,
158  size_t dest_size,
159  char *dest)
160 {
161  struct NetworkRecord rec;
162  size_t off;
163 
164  off = 0;
165  for (unsigned int i = 0; i < rd_count; i++)
166  {
168  "Serializing record %u with flags %d and expiration time %llu\n",
169  i,
170  rd[i].flags,
171  (unsigned long long) rd[i].expiration_time);
173  rec.data_size = htons ((uint16_t) rd[i].data_size);
174  rec.record_type = htonl (rd[i].record_type);
175  rec.flags = htons (rd[i].flags);
176  if ((off + sizeof(rec) > dest_size) ||
177  (off + sizeof(rec) < off))
178  {
179  GNUNET_break (0);
180  return -1;
181  }
182  GNUNET_memcpy (&dest[off],
183  &rec,
184  sizeof(rec));
185  off += sizeof(rec);
186  if ((off + rd[i].data_size > dest_size) ||
187  (off + rd[i].data_size < off))
188  {
189  GNUNET_break (0);
190  return -1;
191  }
192  GNUNET_memcpy (&dest[off],
193  rd[i].data,
194  rd[i].data_size);
195  off += rd[i].data_size;
196 #if DEBUG_GNSRECORDS
197  {
198  char *str;
199 
201  rd[i].data,
202  rd[i].data_size);
203  if (NULL == str)
204  {
205  GNUNET_break_op (0);
206  return -1;
207  }
208  GNUNET_free (str);
209  }
210 #endif
211  }
212  memset (&dest[off],
213  0,
214  dest_size - off);
215  return dest_size;
216 }
217 
218 unsigned int
220  const char *src)
221 {
222  struct NetworkRecord rec;
223  struct NetworkRecord rec_zero;
224  size_t off;
225  unsigned int rd_count = 0;
226 
227  memset (&rec_zero, 0, sizeof (rec_zero));
228 
229  off = 0;
230  for (off = 0; (off + sizeof(rec) <= len) && (off + sizeof(rec) >= off);)
231  {
232  GNUNET_memcpy (&rec,
233  &src[off],
234  sizeof(rec));
235  /*
236  * If we have found a byte string of zeroes, we have reached
237  * the padding
238  */
239  if (0 == GNUNET_memcmp (&rec, &rec_zero))
240  break;
241  off += sizeof(rec);
242  if ((off + ntohs ((uint16_t) rec.data_size) > len) ||
243  (off + ntohs ((uint16_t) rec.data_size) < off))
244  {
245  GNUNET_break_op (0);
246  return 0;
247  }
248  off += ntohs ((uint16_t) rec.data_size);
249  rd_count++;
250  }
251  return rd_count;
252 }
253 
263 int
265  const char *src,
266  unsigned int rd_count,
267  struct GNUNET_GNSRECORD_Data *dest)
268 {
269  struct NetworkRecord rec;
270  size_t off;
271 
272  off = 0;
273  for (unsigned int i = 0; i < rd_count; i++)
274  {
275  if ((off + sizeof(rec) > len) ||
276  (off + sizeof(rec) < off))
277  {
278  GNUNET_break_op (0);
279  return GNUNET_SYSERR;
280  }
281  GNUNET_memcpy (&rec,
282  &src[off],
283  sizeof(rec));
284  dest[i].expiration_time = GNUNET_ntohll (rec.expiration_time);
285  dest[i].data_size = ntohs ((uint16_t) rec.data_size);
286  dest[i].record_type = ntohl (rec.record_type);
287  dest[i].flags = ntohs (rec.flags);
288  off += sizeof(rec);
289  if ((off + dest[i].data_size > len) ||
290  (off + dest[i].data_size < off))
291  {
292  GNUNET_break_op (0);
293  return GNUNET_SYSERR;
294  }
295  dest[i].data = &src[off];
296  off += dest[i].data_size;
297 #if GNUNET_EXTRA_LOGGING
298  {
299  char *str;
300 
302  dest[i].data,
303  dest[i].data_size);
304  if (NULL == str)
305  {
306  GNUNET_break_op (0);
307  return GNUNET_SYSERR;
308  }
309  GNUNET_free (str);
310  }
311 #endif
313  "Deserialized record %u with flags %d and expiration time %llu\n",
314  i,
315  dest[i].flags,
316  (unsigned long long) dest[i].expiration_time);
317  }
318  return GNUNET_OK;
319 }
320 
321 
322 /* end of gnsrecord_serialization.c */
#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.
#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
uint32_t data
The data value.
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...
API for helper library to parse DNS packets.
API that can be used to manipulate GNS record data.
Standard TCP/IP network structs and IP checksum calculations for TUN interaction.
char * GNUNET_GNSRECORD_value_to_string(uint32_t type, const void *data, size_t data_size)
Convert the 'value' of a record to a string.
Definition: gnsrecord.c:156
int GNUNET_GNSRECORD_records_deserialize(size_t len, const char *src, unsigned int rd_count, struct GNUNET_GNSRECORD_Data *dest)
Deserialize the given records to the given destination.
ssize_t GNUNET_GNSRECORD_records_serialize(unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd, size_t dest_size, char *dest)
Serialize the given records to the given destination buffer.
unsigned int GNUNET_GNSRECORD_records_deserialize_get_size(size_t len, const char *src)
GNUNET_NETWORK_STRUCT_END ssize_t GNUNET_GNSRECORD_records_get_size(unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
Calculate how many bytes we will need to serialize the given records.
#define GNUNET_NETWORK_STRUCT_BEGIN
Define as empty, GNUNET_PACKED should suffice, but this won't work on W32.
uint64_t GNUNET_ntohll(uint64_t n)
Convert unsigned 64-bit integer to host byte order.
Definition: common_endian.c:53
#define GNUNET_NETWORK_STRUCT_END
Define as empty, GNUNET_PACKED should suffice, but this won't work on W32;.
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
uint64_t GNUNET_htonll(uint64_t n)
Convert unsigned 64-bit integer to network byte order.
Definition: common_endian.c:36
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
#define GNUNET_PACKED
gcc-ism to get packed structs.
@ GNUNET_OK
Definition: gnunet_common.h:99
@ GNUNET_SYSERR
Definition: gnunet_common.h:97
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
#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_free(ptr)
Wrapper around free.
uint32_t record_type
Type of the GNS/DNS record.
size_t data_size
Number of bytes in data.
Internal format of a record in the serialized form.
uint64_t expiration_time
Expiration time for the DNS record; relative or absolute depends on flags, network byte order.
uint32_t record_type
Type of the GNS/DNS record, network byte order.
uint16_t flags
Flags for the record, network byte order.
uint16_t data_size
Number of bytes in 'data', network byte order.