aboutsummaryrefslogtreecommitdiff
path: root/src/gnsrecord/gnsrecord_serialization.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gnsrecord/gnsrecord_serialization.c')
-rw-r--r--src/gnsrecord/gnsrecord_serialization.c158
1 files changed, 126 insertions, 32 deletions
diff --git a/src/gnsrecord/gnsrecord_serialization.c b/src/gnsrecord/gnsrecord_serialization.c
index 190f62fc2..934d36102 100644
--- a/src/gnsrecord/gnsrecord_serialization.c
+++ b/src/gnsrecord/gnsrecord_serialization.c
@@ -2,20 +2,18 @@
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2009-2013 GNUnet e.V. 3 Copyright (C) 2009-2013 GNUnet e.V.
4 4
5 GNUnet is free software; you can redistribute it and/or modify 5 GNUnet is free software: you can redistribute it and/or modify it
6 it under the terms of the GNU General Public License as published 6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation; either version 3, or (at your 7 by the Free Software Foundation, either version 3 of the License,
8 option) any later version. 8 or (at your option) any later version.
9 9
10 GNUnet is distributed in the hope that it will be useful, but 10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of 11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details. 13 Affero General Public License for more details.
14 14
15 You should have received a copy of the GNU General Public License 15 You should have received a copy of the GNU Affero General Public License
16 along with GNUnet; see the file COPYING. If not, write to the 16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/ 17*/
20 18
21/** 19/**
@@ -37,6 +35,12 @@
37 35
38#define LOG(kind,...) GNUNET_log_from (kind, "gnsrecord",__VA_ARGS__) 36#define LOG(kind,...) GNUNET_log_from (kind, "gnsrecord",__VA_ARGS__)
39 37
38/**
39 * Set to 1 to check that all records are well-formed (can be converted
40 * to string) during serialization/deserialization.
41 */
42#define DEBUG_GNSRECORDS 0
43
40GNUNET_NETWORK_STRUCT_BEGIN 44GNUNET_NETWORK_STRUCT_BEGIN
41 45
42 46
@@ -78,22 +82,63 @@ GNUNET_NETWORK_STRUCT_END
78 * 82 *
79 * @param rd_count number of records in the rd array 83 * @param rd_count number of records in the rd array
80 * @param rd array of #GNUNET_GNSRECORD_Data with @a rd_count elements 84 * @param rd array of #GNUNET_GNSRECORD_Data with @a rd_count elements
81 * @return the required size to serialize 85 * @return the required size to serialize, -1 on error
82 */ 86 */
83size_t 87ssize_t
84GNUNET_GNSRECORD_records_get_size (unsigned int rd_count, 88GNUNET_GNSRECORD_records_get_size (unsigned int rd_count,
85 const struct GNUNET_GNSRECORD_Data *rd) 89 const struct GNUNET_GNSRECORD_Data *rd)
86{ 90{
87 unsigned int i;
88 size_t ret; 91 size_t ret;
89 92
93 if (0 == rd_count)
94 return 0;
95
90 ret = sizeof (struct NetworkRecord) * rd_count; 96 ret = sizeof (struct NetworkRecord) * rd_count;
91 for (i=0;i<rd_count;i++) 97 for (unsigned int i=0;i<rd_count;i++)
92 { 98 {
93 GNUNET_assert ((ret + rd[i].data_size) >= ret); 99 if ((ret + rd[i].data_size) < ret)
100 {
101 GNUNET_break (0);
102 return -1;
103 }
94 ret += rd[i].data_size; 104 ret += rd[i].data_size;
105#if DEBUG_GNSRECORDS
106 {
107 char *str;
108
109 str = GNUNET_GNSRECORD_value_to_string (rd[i].record_type,
110 rd[i].data,
111 rd[i].data_size);
112 if (NULL == str)
113 {
114 GNUNET_break_op (0);
115 return -1;
116 }
117 GNUNET_free (str);
118 }
119#endif
95 } 120 }
96 return ret; 121 if (ret > SSIZE_MAX)
122 {
123 GNUNET_break (0);
124 return -1;
125 }
126 //Do not pad PKEY
127 if (GNUNET_GNSRECORD_TYPE_PKEY == rd->record_type)
128 return ret;
129 /**
130 * Efficiently round up to the next
131 * power of 2 for padding
132 * https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
133 */
134 ret--;
135 ret |= ret >> 1;
136 ret |= ret >> 2;
137 ret |= ret >> 4;
138 ret |= ret >> 8;
139 ret |= ret >> 16;
140 ret++;
141 return (ssize_t) ret;
97} 142}
98 143
99 144
@@ -108,16 +153,15 @@ GNUNET_GNSRECORD_records_get_size (unsigned int rd_count,
108 */ 153 */
109ssize_t 154ssize_t
110GNUNET_GNSRECORD_records_serialize (unsigned int rd_count, 155GNUNET_GNSRECORD_records_serialize (unsigned int rd_count,
111 const struct GNUNET_GNSRECORD_Data *rd, 156 const struct GNUNET_GNSRECORD_Data *rd,
112 size_t dest_size, 157 size_t dest_size,
113 char *dest) 158 char *dest)
114{ 159{
115 struct NetworkRecord rec; 160 struct NetworkRecord rec;
116 unsigned int i;
117 size_t off; 161 size_t off;
118 162
119 off = 0; 163 off = 0;
120 for (i=0;i<rd_count;i++) 164 for (unsigned int i=0;i<rd_count;i++)
121 { 165 {
122 LOG (GNUNET_ERROR_TYPE_DEBUG, 166 LOG (GNUNET_ERROR_TYPE_DEBUG,
123 "Serializing record %u with flags %d and expiration time %llu\n", 167 "Serializing record %u with flags %d and expiration time %llu\n",
@@ -128,20 +172,46 @@ GNUNET_GNSRECORD_records_serialize (unsigned int rd_count,
128 rec.data_size = htonl ((uint32_t) rd[i].data_size); 172 rec.data_size = htonl ((uint32_t) rd[i].data_size);
129 rec.record_type = htonl (rd[i].record_type); 173 rec.record_type = htonl (rd[i].record_type);
130 rec.flags = htonl (rd[i].flags); 174 rec.flags = htonl (rd[i].flags);
131 if (off + sizeof (rec) > dest_size) 175 if ( (off + sizeof (rec) > dest_size) ||
176 (off + sizeof (rec) < off) )
177 {
178 GNUNET_break (0);
132 return -1; 179 return -1;
180 }
133 GNUNET_memcpy (&dest[off], 181 GNUNET_memcpy (&dest[off],
134 &rec, 182 &rec,
135 sizeof (rec)); 183 sizeof (rec));
136 off += sizeof (rec); 184 off += sizeof (rec);
137 if (off + rd[i].data_size > dest_size) 185 if ( (off + rd[i].data_size > dest_size) ||
186 (off + rd[i].data_size < off) )
187 {
188 GNUNET_break (0);
138 return -1; 189 return -1;
190 }
139 GNUNET_memcpy (&dest[off], 191 GNUNET_memcpy (&dest[off],
140 rd[i].data, 192 rd[i].data,
141 rd[i].data_size); 193 rd[i].data_size);
142 off += rd[i].data_size; 194 off += rd[i].data_size;
195#if DEBUG_GNSRECORDS
196 {
197 char *str;
198
199 str = GNUNET_GNSRECORD_value_to_string (rd[i].record_type,
200 rd[i].data,
201 rd[i].data_size);
202 if (NULL == str)
203 {
204 GNUNET_break_op (0);
205 return -1;
206 }
207 GNUNET_free (str);
208 }
209#endif
143 } 210 }
144 return off; 211 memset (&dest[off],
212 0,
213 dest_size-off);
214 return dest_size;
145} 215}
146 216
147 217
@@ -156,29 +226,53 @@ GNUNET_GNSRECORD_records_serialize (unsigned int rd_count,
156 */ 226 */
157int 227int
158GNUNET_GNSRECORD_records_deserialize (size_t len, 228GNUNET_GNSRECORD_records_deserialize (size_t len,
159 const char *src, 229 const char *src,
160 unsigned int rd_count, 230 unsigned int rd_count,
161 struct GNUNET_GNSRECORD_Data *dest) 231 struct GNUNET_GNSRECORD_Data *dest)
162{ 232{
163 struct NetworkRecord rec; 233 struct NetworkRecord rec;
164 unsigned int i;
165 size_t off; 234 size_t off;
166 235
167 off = 0; 236 off = 0;
168 for (i=0;i<rd_count;i++) 237 for (unsigned int i=0;i<rd_count;i++)
169 { 238 {
170 if (off + sizeof (rec) > len) 239 if ( (off + sizeof (rec) > len) ||
240 (off + sizeof (rec) < off) )
241 {
242 GNUNET_break_op (0);
171 return GNUNET_SYSERR; 243 return GNUNET_SYSERR;
172 GNUNET_memcpy (&rec, &src[off], sizeof (rec)); 244 }
245 GNUNET_memcpy (&rec,
246 &src[off],
247 sizeof (rec));
173 dest[i].expiration_time = GNUNET_ntohll (rec.expiration_time); 248 dest[i].expiration_time = GNUNET_ntohll (rec.expiration_time);
174 dest[i].data_size = ntohl ((uint32_t) rec.data_size); 249 dest[i].data_size = ntohl ((uint32_t) rec.data_size);
175 dest[i].record_type = ntohl (rec.record_type); 250 dest[i].record_type = ntohl (rec.record_type);
176 dest[i].flags = ntohl (rec.flags); 251 dest[i].flags = ntohl (rec.flags);
177 off += sizeof (rec); 252 off += sizeof (rec);
178 if (off + dest[i].data_size > len) 253 if ( (off + dest[i].data_size > len) ||
254 (off + dest[i].data_size < off) )
255 {
256 GNUNET_break_op (0);
179 return GNUNET_SYSERR; 257 return GNUNET_SYSERR;
258 }
180 dest[i].data = &src[off]; 259 dest[i].data = &src[off];
181 off += dest[i].data_size; 260 off += dest[i].data_size;
261#if GNUNET_EXTRA_LOGGING
262 {
263 char *str;
264
265 str = GNUNET_GNSRECORD_value_to_string (dest[i].record_type,
266 dest[i].data,
267 dest[i].data_size);
268 if (NULL == str)
269 {
270 GNUNET_break_op (0);
271 return GNUNET_SYSERR;
272 }
273 GNUNET_free (str);
274 }
275#endif
182 LOG (GNUNET_ERROR_TYPE_DEBUG, 276 LOG (GNUNET_ERROR_TYPE_DEBUG,
183 "Deserialized record %u with flags %d and expiration time %llu\n", 277 "Deserialized record %u with flags %d and expiration time %llu\n",
184 i, 278 i,