diff options
author | Jfreegman <jfreegman@gmail.com> | 2016-09-07 12:14:31 -0400 |
---|---|---|
committer | Jfreegman <jfreegman@gmail.com> | 2016-09-09 10:37:40 -0400 |
commit | 769db9dd9a73208d32c22c52c8eef7446e026f81 (patch) | |
tree | c8d563d9e070f3443960232b6205211375d5aba6 /toxcore/DHT.c | |
parent | 59075ba325dc91d3fa7760c6b84df0de7854ae7f (diff) |
Separate IP_Port packing from pack_nodes() and unpack_nodes()
Allows us to pack IP_Port structs that are part of arbitrarily structured data.
Diffstat (limited to 'toxcore/DHT.c')
-rw-r--r-- | toxcore/DHT.c | 237 |
1 files changed, 145 insertions, 92 deletions
diff --git a/toxcore/DHT.c b/toxcore/DHT.c index 2e475d01..1d9ad54f 100644 --- a/toxcore/DHT.c +++ b/toxcore/DHT.c | |||
@@ -27,9 +27,7 @@ | |||
27 | #include "config.h" | 27 | #include "config.h" |
28 | #endif | 28 | #endif |
29 | 29 | ||
30 | #ifdef TOX_DEBUG | ||
31 | #include <assert.h> | 30 | #include <assert.h> |
32 | #endif | ||
33 | 31 | ||
34 | #include "logger.h" | 32 | #include "logger.h" |
35 | 33 | ||
@@ -233,6 +231,129 @@ int packed_node_size(uint8_t ip_family) | |||
233 | } | 231 | } |
234 | 232 | ||
235 | 233 | ||
234 | /* Packs an IP_Port structure into data of max size length. | ||
235 | * | ||
236 | * Returns size of packed IP_Port data on success | ||
237 | * Return -1 on failure. | ||
238 | */ | ||
239 | static int pack_ip_port(uint8_t *data, uint16_t length, const IP_Port *ip_port) | ||
240 | { | ||
241 | if (data == NULL) { | ||
242 | return -1; | ||
243 | } | ||
244 | |||
245 | int ipv6 = -1; | ||
246 | uint8_t net_family; | ||
247 | |||
248 | if (ip_port->ip.family == AF_INET) { | ||
249 | // FIXME use functions to convert endianness | ||
250 | ipv6 = 0; | ||
251 | net_family = TOX_AF_INET; | ||
252 | } else if (ip_port->ip.family == TCP_INET) { | ||
253 | ipv6 = 0; | ||
254 | net_family = TOX_TCP_INET; | ||
255 | } else if (ip_port->ip.family == AF_INET6) { | ||
256 | ipv6 = 1; | ||
257 | net_family = TOX_AF_INET6; | ||
258 | } else if (ip_port->ip.family == TCP_INET6) { | ||
259 | ipv6 = 1; | ||
260 | net_family = TOX_TCP_INET6; | ||
261 | } else { | ||
262 | return -1; | ||
263 | } | ||
264 | |||
265 | if (ipv6 == 0) { | ||
266 | uint32_t size = 1 + SIZE_IP4 + sizeof(uint16_t); | ||
267 | |||
268 | if (size > length) { | ||
269 | return -1; | ||
270 | } | ||
271 | |||
272 | data[0] = net_family; | ||
273 | memcpy(data + 1, &ip_port->ip.ip4, SIZE_IP4); | ||
274 | memcpy(data + 1 + SIZE_IP4, &ip_port->port, sizeof(uint16_t)); | ||
275 | return size; | ||
276 | } else if (ipv6 == 1) { | ||
277 | uint32_t size = 1 + SIZE_IP6 + sizeof(uint16_t); | ||
278 | |||
279 | if (size > length) { | ||
280 | return -1; | ||
281 | } | ||
282 | |||
283 | data[0] = net_family; | ||
284 | memcpy(data + 1, &ip_port->ip.ip6, SIZE_IP6); | ||
285 | memcpy(data + 1 + SIZE_IP6, &ip_port->port, sizeof(uint16_t)); | ||
286 | return size; | ||
287 | } else { | ||
288 | return -1; | ||
289 | } | ||
290 | } | ||
291 | |||
292 | /* Unpack IP_Port structure from data of max size length into ip_port. | ||
293 | * | ||
294 | * Return size of unpacked ip_port on success. | ||
295 | * Return -1 on failure. | ||
296 | */ | ||
297 | static int unpack_ip_port(IP_Port *ip_port, const uint8_t *data, uint16_t length, uint8_t tcp_enabled) | ||
298 | { | ||
299 | if (data == NULL) { | ||
300 | return -1; | ||
301 | } | ||
302 | |||
303 | int ipv6 = -1; | ||
304 | uint8_t host_family; | ||
305 | |||
306 | if (data[0] == TOX_AF_INET) { | ||
307 | ipv6 = 0; | ||
308 | host_family = AF_INET; | ||
309 | } else if (data[0] == TOX_TCP_INET) { | ||
310 | if (!tcp_enabled) { | ||
311 | return -1; | ||
312 | } | ||
313 | |||
314 | ipv6 = 0; | ||
315 | host_family = TCP_INET; | ||
316 | } else if (data[0] == TOX_AF_INET6) { | ||
317 | ipv6 = 1; | ||
318 | host_family = AF_INET6; | ||
319 | } else if (data[0] == TOX_TCP_INET6) { | ||
320 | if (!tcp_enabled) { | ||
321 | return -1; | ||
322 | } | ||
323 | |||
324 | ipv6 = 1; | ||
325 | host_family = TCP_INET6; | ||
326 | } else { | ||
327 | return -1; | ||
328 | } | ||
329 | |||
330 | if (ipv6 == 0) { | ||
331 | uint32_t size = 1 + SIZE_IP4 + sizeof(uint16_t); | ||
332 | |||
333 | if (size > length) { | ||
334 | return -1; | ||
335 | } | ||
336 | |||
337 | ip_port->ip.family = host_family; | ||
338 | memcpy(&ip_port->ip.ip4, data + 1, SIZE_IP4); | ||
339 | memcpy(&ip_port->port, data + 1 + SIZE_IP4, sizeof(uint16_t)); | ||
340 | return size; | ||
341 | } else if (ipv6 == 1) { | ||
342 | uint32_t size = 1 + SIZE_IP6 + sizeof(uint16_t); | ||
343 | |||
344 | if (size > length) { | ||
345 | return -1; | ||
346 | } | ||
347 | |||
348 | ip_port->ip.family = host_family; | ||
349 | memcpy(&ip_port->ip.ip6, data + 1, SIZE_IP6); | ||
350 | memcpy(&ip_port->port, data + 1 + SIZE_IP6, sizeof(uint16_t)); | ||
351 | return size; | ||
352 | } else { | ||
353 | return -1; | ||
354 | } | ||
355 | } | ||
356 | |||
236 | /* Pack number of nodes into data of maxlength length. | 357 | /* Pack number of nodes into data of maxlength length. |
237 | * | 358 | * |
238 | * return length of packed nodes on success. | 359 | * return length of packed nodes on success. |
@@ -242,54 +363,24 @@ int pack_nodes(uint8_t *data, uint16_t length, const Node_format *nodes, uint16_ | |||
242 | { | 363 | { |
243 | uint32_t i, packed_length = 0; | 364 | uint32_t i, packed_length = 0; |
244 | 365 | ||
245 | for (i = 0; i < number; ++i) { | 366 | for (i = 0; i < number && packed_length < length; ++i) { |
246 | int ipv6 = -1; | 367 | int ipp_size = pack_ip_port(data + packed_length, length - packed_length, &nodes[i].ip_port); |
247 | uint8_t net_family; | ||
248 | 368 | ||
249 | // FIXME use functions to convert endianness | 369 | if (ipp_size == -1) { |
250 | if (nodes[i].ip_port.ip.family == AF_INET) { | ||
251 | ipv6 = 0; | ||
252 | net_family = TOX_AF_INET; | ||
253 | } else if (nodes[i].ip_port.ip.family == TCP_INET) { | ||
254 | ipv6 = 0; | ||
255 | net_family = TOX_TCP_INET; | ||
256 | } else if (nodes[i].ip_port.ip.family == AF_INET6) { | ||
257 | ipv6 = 1; | ||
258 | net_family = TOX_AF_INET6; | ||
259 | } else if (nodes[i].ip_port.ip.family == TCP_INET6) { | ||
260 | ipv6 = 1; | ||
261 | net_family = TOX_TCP_INET6; | ||
262 | } else { | ||
263 | return -1; | 370 | return -1; |
264 | } | 371 | } |
265 | 372 | ||
266 | if (ipv6 == 0) { | 373 | packed_length += ipp_size; |
267 | uint32_t size = PACKED_NODE_SIZE_IP4; | ||
268 | |||
269 | if (packed_length + size > length) { | ||
270 | return -1; | ||
271 | } | ||
272 | 374 | ||
273 | data[packed_length] = net_family; | 375 | if (packed_length + crypto_box_PUBLICKEYBYTES > length) { |
274 | memcpy(data + packed_length + 1, &nodes[i].ip_port.ip.ip4, SIZE_IP4); | ||
275 | memcpy(data + packed_length + 1 + SIZE_IP4, &nodes[i].ip_port.port, sizeof(uint16_t)); | ||
276 | memcpy(data + packed_length + 1 + SIZE_IP4 + sizeof(uint16_t), nodes[i].public_key, crypto_box_PUBLICKEYBYTES); | ||
277 | packed_length += size; | ||
278 | } else if (ipv6 == 1) { | ||
279 | uint32_t size = PACKED_NODE_SIZE_IP6; | ||
280 | |||
281 | if (packed_length + size > length) { | ||
282 | return -1; | ||
283 | } | ||
284 | |||
285 | data[packed_length] = net_family; | ||
286 | memcpy(data + packed_length + 1, &nodes[i].ip_port.ip.ip6, SIZE_IP6); | ||
287 | memcpy(data + packed_length + 1 + SIZE_IP6, &nodes[i].ip_port.port, sizeof(uint16_t)); | ||
288 | memcpy(data + packed_length + 1 + SIZE_IP6 + sizeof(uint16_t), nodes[i].public_key, crypto_box_PUBLICKEYBYTES); | ||
289 | packed_length += size; | ||
290 | } else { | ||
291 | return -1; | 376 | return -1; |
292 | } | 377 | } |
378 | |||
379 | memcpy(data + packed_length, nodes[i].public_key, crypto_box_PUBLICKEYBYTES); | ||
380 | packed_length += crypto_box_PUBLICKEYBYTES; | ||
381 | |||
382 | uint32_t increment = ipp_size + crypto_box_PUBLICKEYBYTES; | ||
383 | assert(increment == PACKED_NODE_SIZE_IP4 || increment == PACKED_NODE_SIZE_IP6); | ||
293 | } | 384 | } |
294 | 385 | ||
295 | return packed_length; | 386 | return packed_length; |
@@ -308,62 +399,24 @@ int unpack_nodes(Node_format *nodes, uint16_t max_num_nodes, uint16_t *processed | |||
308 | uint32_t num = 0, len_processed = 0; | 399 | uint32_t num = 0, len_processed = 0; |
309 | 400 | ||
310 | while (num < max_num_nodes && len_processed < length) { | 401 | while (num < max_num_nodes && len_processed < length) { |
311 | int ipv6 = -1; | 402 | int ipp_size = unpack_ip_port(&nodes[num].ip_port, data + len_processed, length - len_processed, tcp_enabled); |
312 | uint8_t host_family; | ||
313 | |||
314 | if (data[len_processed] == TOX_AF_INET) { | ||
315 | ipv6 = 0; | ||
316 | host_family = AF_INET; | ||
317 | } else if (data[len_processed] == TOX_TCP_INET) { | ||
318 | if (!tcp_enabled) { | ||
319 | return -1; | ||
320 | } | ||
321 | 403 | ||
322 | ipv6 = 0; | 404 | if (ipp_size == -1) { |
323 | host_family = TCP_INET; | ||
324 | } else if (data[len_processed] == TOX_AF_INET6) { | ||
325 | ipv6 = 1; | ||
326 | host_family = AF_INET6; | ||
327 | } else if (data[len_processed] == TOX_TCP_INET6) { | ||
328 | if (!tcp_enabled) { | ||
329 | return -1; | ||
330 | } | ||
331 | |||
332 | ipv6 = 1; | ||
333 | host_family = TCP_INET6; | ||
334 | } else { | ||
335 | return -1; | 405 | return -1; |
336 | } | 406 | } |
337 | 407 | ||
338 | if (ipv6 == 0) { | 408 | len_processed += ipp_size; |
339 | uint32_t size = PACKED_NODE_SIZE_IP4; | ||
340 | 409 | ||
341 | if (len_processed + size > length) { | 410 | if (len_processed + crypto_box_PUBLICKEYBYTES > length) { |
342 | return -1; | ||
343 | } | ||
344 | |||
345 | nodes[num].ip_port.ip.family = host_family; | ||
346 | memcpy(&nodes[num].ip_port.ip.ip4, data + len_processed + 1, SIZE_IP4); | ||
347 | memcpy(&nodes[num].ip_port.port, data + len_processed + 1 + SIZE_IP4, sizeof(uint16_t)); | ||
348 | memcpy(nodes[num].public_key, data + len_processed + 1 + SIZE_IP4 + sizeof(uint16_t), crypto_box_PUBLICKEYBYTES); | ||
349 | len_processed += size; | ||
350 | ++num; | ||
351 | } else if (ipv6 == 1) { | ||
352 | uint32_t size = PACKED_NODE_SIZE_IP6; | ||
353 | |||
354 | if (len_processed + size > length) { | ||
355 | return -1; | ||
356 | } | ||
357 | |||
358 | nodes[num].ip_port.ip.family = host_family; | ||
359 | memcpy(&nodes[num].ip_port.ip.ip6, data + len_processed + 1, SIZE_IP6); | ||
360 | memcpy(&nodes[num].ip_port.port, data + len_processed + 1 + SIZE_IP6, sizeof(uint16_t)); | ||
361 | memcpy(nodes[num].public_key, data + len_processed + 1 + SIZE_IP6 + sizeof(uint16_t), crypto_box_PUBLICKEYBYTES); | ||
362 | len_processed += size; | ||
363 | ++num; | ||
364 | } else { | ||
365 | return -1; | 411 | return -1; |
366 | } | 412 | } |
413 | |||
414 | memcpy(nodes[num].public_key, data + len_processed, crypto_box_PUBLICKEYBYTES); | ||
415 | len_processed += crypto_box_PUBLICKEYBYTES; | ||
416 | ++num; | ||
417 | |||
418 | uint32_t increment = ipp_size + crypto_box_PUBLICKEYBYTES; | ||
419 | assert(increment == PACKED_NODE_SIZE_IP4 || increment == PACKED_NODE_SIZE_IP6); | ||
367 | } | 420 | } |
368 | 421 | ||
369 | if (processed_data_len) { | 422 | if (processed_data_len) { |