LCOV - code coverage report
Current view: top level - trunnel - netinfo.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 99 325 30.5 %
Date: 2021-11-24 03:28:48 Functions: 12 46 26.1 %

          Line data    Source code
       1             : /* netinfo.c -- generated by Trunnel v1.5.3.
       2             :  * https://gitweb.torproject.org/trunnel.git
       3             :  * You probably shouldn't edit this file.
       4             :  */
       5             : #include <stdlib.h>
       6             : #include "trunnel-impl.h"
       7             : 
       8             : #include "netinfo.h"
       9             : 
      10             : #define TRUNNEL_SET_ERROR_CODE(obj) \
      11             :   do {                              \
      12             :     (obj)->trunnel_error_code_ = 1; \
      13             :   } while (0)
      14             : 
      15             : #if defined(__COVERITY__) || defined(__clang_analyzer__)
      16             : /* If we're running a static analysis tool, we don't want it to complain
      17             :  * that some of our remaining-bytes checks are dead-code. */
      18             : int netinfo_deadcode_dummy__ = 0;
      19             : #define OR_DEADCODE_DUMMY || netinfo_deadcode_dummy__
      20             : #else
      21             : #define OR_DEADCODE_DUMMY
      22             : #endif
      23             : 
      24             : #define CHECK_REMAINING(nbytes, label)                           \
      25             :   do {                                                           \
      26             :     if (remaining < (nbytes) OR_DEADCODE_DUMMY) {                \
      27             :       goto label;                                                \
      28             :     }                                                            \
      29             :   } while (0)
      30             : 
      31             : netinfo_addr_t *
      32           2 : netinfo_addr_new(void)
      33             : {
      34           2 :   netinfo_addr_t *val = trunnel_calloc(1, sizeof(netinfo_addr_t));
      35           2 :   if (NULL == val)
      36           0 :     return NULL;
      37             :   return val;
      38             : }
      39             : 
      40             : /** Release all storage held inside 'obj', but do not free 'obj'.
      41             :  */
      42             : static void
      43             : netinfo_addr_clear(netinfo_addr_t *obj)
      44             : {
      45             :   (void) obj;
      46             : }
      47             : 
      48             : void
      49           2 : netinfo_addr_free(netinfo_addr_t *obj)
      50             : {
      51           2 :   if (obj == NULL)
      52             :     return;
      53           2 :   netinfo_addr_clear(obj);
      54           2 :   trunnel_memwipe(obj, sizeof(netinfo_addr_t));
      55           2 :   trunnel_free_(obj);
      56             : }
      57             : 
      58             : uint8_t
      59           1 : netinfo_addr_get_addr_type(const netinfo_addr_t *inp)
      60             : {
      61           1 :   return inp->addr_type;
      62             : }
      63             : int
      64           0 : netinfo_addr_set_addr_type(netinfo_addr_t *inp, uint8_t val)
      65             : {
      66           0 :   inp->addr_type = val;
      67           0 :   return 0;
      68             : }
      69             : uint8_t
      70           1 : netinfo_addr_get_len(const netinfo_addr_t *inp)
      71             : {
      72           1 :   return inp->len;
      73             : }
      74             : int
      75           0 : netinfo_addr_set_len(netinfo_addr_t *inp, uint8_t val)
      76             : {
      77           0 :   inp->len = val;
      78           0 :   return 0;
      79             : }
      80             : uint32_t
      81           0 : netinfo_addr_get_addr_ipv4(const netinfo_addr_t *inp)
      82             : {
      83           0 :   return inp->addr_ipv4;
      84             : }
      85             : int
      86           0 : netinfo_addr_set_addr_ipv4(netinfo_addr_t *inp, uint32_t val)
      87             : {
      88           0 :   inp->addr_ipv4 = val;
      89           0 :   return 0;
      90             : }
      91             : size_t
      92           0 : netinfo_addr_getlen_addr_ipv6(const netinfo_addr_t *inp)
      93             : {
      94           0 :   (void)inp;  return 16;
      95             : }
      96             : 
      97             : uint8_t
      98           0 : netinfo_addr_get_addr_ipv6(netinfo_addr_t *inp, size_t idx)
      99             : {
     100           0 :   trunnel_assert(idx < 16);
     101           0 :   return inp->addr_ipv6[idx];
     102             : }
     103             : 
     104             : uint8_t
     105           0 : netinfo_addr_getconst_addr_ipv6(const netinfo_addr_t *inp, size_t idx)
     106             : {
     107           0 :   return netinfo_addr_get_addr_ipv6((netinfo_addr_t*)inp, idx);
     108             : }
     109             : int
     110           0 : netinfo_addr_set_addr_ipv6(netinfo_addr_t *inp, size_t idx, uint8_t elt)
     111             : {
     112           0 :   trunnel_assert(idx < 16);
     113           0 :   inp->addr_ipv6[idx] = elt;
     114           0 :   return 0;
     115             : }
     116             : 
     117             : uint8_t *
     118           0 : netinfo_addr_getarray_addr_ipv6(netinfo_addr_t *inp)
     119             : {
     120           0 :   return inp->addr_ipv6;
     121             : }
     122             : const uint8_t  *
     123           0 : netinfo_addr_getconstarray_addr_ipv6(const netinfo_addr_t *inp)
     124             : {
     125           0 :   return (const uint8_t  *)netinfo_addr_getarray_addr_ipv6((netinfo_addr_t*)inp);
     126             : }
     127             : const char *
     128           0 : netinfo_addr_check(const netinfo_addr_t *obj)
     129             : {
     130           0 :   if (obj == NULL)
     131             :     return "Object was NULL";
     132           0 :   if (obj->trunnel_error_code_)
     133           0 :     return "A set function failed on this object";
     134             :   switch (obj->addr_type) {
     135             : 
     136             :     case NETINFO_ADDR_TYPE_IPV4:
     137             :       break;
     138             : 
     139             :     case NETINFO_ADDR_TYPE_IPV6:
     140             :       break;
     141             : 
     142             :     default:
     143             :       break;
     144             :   }
     145             :   return NULL;
     146             : }
     147             : 
     148             : ssize_t
     149           0 : netinfo_addr_encoded_len(const netinfo_addr_t *obj)
     150             : {
     151           0 :   ssize_t result = 0;
     152             : 
     153           0 :   if (NULL != netinfo_addr_check(obj))
     154             :      return -1;
     155             : 
     156             : 
     157             :   /* Length of u8 addr_type */
     158           0 :   result += 1;
     159             : 
     160             :   /* Length of u8 len */
     161           0 :   result += 1;
     162           0 :   switch (obj->addr_type) {
     163             : 
     164           0 :     case NETINFO_ADDR_TYPE_IPV4:
     165             : 
     166             :       /* Length of u32 addr_ipv4 */
     167           0 :       result += 4;
     168           0 :       break;
     169             : 
     170           0 :     case NETINFO_ADDR_TYPE_IPV6:
     171             : 
     172             :       /* Length of u8 addr_ipv6[16] */
     173           0 :       result += 16;
     174           0 :       break;
     175             : 
     176             :     default:
     177             :       break;
     178             :   }
     179             :   return result;
     180             : }
     181             : int
     182           0 : netinfo_addr_clear_errors(netinfo_addr_t *obj)
     183             : {
     184           0 :   int r = obj->trunnel_error_code_;
     185           0 :   obj->trunnel_error_code_ = 0;
     186           0 :   return r;
     187             : }
     188             : ssize_t
     189           0 : netinfo_addr_encode(uint8_t *output, const size_t avail, const netinfo_addr_t *obj)
     190             : {
     191           0 :   ssize_t result = 0;
     192           0 :   size_t written = 0;
     193           0 :   uint8_t *ptr = output;
     194           0 :   const char *msg;
     195             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
     196             :   const ssize_t encoded_len = netinfo_addr_encoded_len(obj);
     197             : #endif
     198             : 
     199           0 :   uint8_t *backptr_len = NULL;
     200             : 
     201           0 :   if (NULL != (msg = netinfo_addr_check(obj)))
     202           0 :     goto check_failed;
     203             : 
     204             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
     205             :   trunnel_assert(encoded_len >= 0);
     206             : #endif
     207             : 
     208             :   /* Encode u8 addr_type */
     209           0 :   trunnel_assert(written <= avail);
     210           0 :   if (avail - written < 1)
     211           0 :     goto truncated;
     212           0 :   trunnel_set_uint8(ptr, (obj->addr_type));
     213           0 :   written += 1; ptr += 1;
     214             : 
     215             :   /* Encode u8 len */
     216           0 :   backptr_len = ptr;
     217           0 :   trunnel_assert(written <= avail);
     218           0 :   if (avail - written < 1)
     219           0 :     goto truncated;
     220           0 :   trunnel_set_uint8(ptr, (obj->len));
     221           0 :   written += 1; ptr += 1;
     222             :   {
     223           0 :     size_t written_before_union = written;
     224             : 
     225             :     /* Encode union addr[addr_type] */
     226           0 :     trunnel_assert(written <= avail);
     227           0 :     switch (obj->addr_type) {
     228             : 
     229             :       case NETINFO_ADDR_TYPE_IPV4:
     230             : 
     231             :         /* Encode u32 addr_ipv4 */
     232           0 :         trunnel_assert(written <= avail);
     233           0 :         if (avail - written < 4)
     234           0 :           goto truncated;
     235           0 :         trunnel_set_uint32(ptr, trunnel_htonl(obj->addr_ipv4));
     236           0 :         written += 4; ptr += 4;
     237           0 :         break;
     238             : 
     239             :       case NETINFO_ADDR_TYPE_IPV6:
     240             : 
     241             :         /* Encode u8 addr_ipv6[16] */
     242           0 :         trunnel_assert(written <= avail);
     243           0 :         if (avail - written < 16)
     244           0 :           goto truncated;
     245           0 :         memcpy(ptr, obj->addr_ipv6, 16);
     246           0 :         written += 16; ptr += 16;
     247           0 :         break;
     248             : 
     249             :       default:
     250             :         break;
     251             :     }
     252             :     /* Write the length field back to len */
     253           0 :     trunnel_assert(written >= written_before_union);
     254             : #if UINT8_MAX < SIZE_MAX
     255           0 :     if (written - written_before_union > UINT8_MAX)
     256             :       goto check_failed;
     257             : #endif
     258           0 :     trunnel_set_uint8(backptr_len, (written - written_before_union));
     259             :   }
     260             : 
     261             : 
     262           0 :   trunnel_assert(ptr == output + written);
     263             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
     264             :   {
     265             :     trunnel_assert(encoded_len >= 0);
     266             :     trunnel_assert((size_t)encoded_len == written);
     267             :   }
     268             : 
     269             : #endif
     270             : 
     271           0 :   return written;
     272             : 
     273           0 :  truncated:
     274           0 :   result = -2;
     275           0 :   goto fail;
     276           0 :  check_failed:
     277           0 :   (void)msg;
     278           0 :   result = -1;
     279           0 :   goto fail;
     280             :  fail:
     281             :   trunnel_assert(result < 0);
     282             :   return result;
     283             : }
     284             : 
     285             : /** As netinfo_addr_parse(), but do not allocate the output object.
     286             :  */
     287             : static ssize_t
     288           2 : netinfo_addr_parse_into(netinfo_addr_t *obj, const uint8_t *input, const size_t len_in)
     289             : {
     290           2 :   const uint8_t *ptr = input;
     291           2 :   size_t remaining = len_in;
     292           2 :   ssize_t result = 0;
     293           2 :   (void)result;
     294             : 
     295             :   /* Parse u8 addr_type */
     296           2 :   CHECK_REMAINING(1, truncated);
     297           2 :   obj->addr_type = (trunnel_get_uint8(ptr));
     298           2 :   remaining -= 1; ptr += 1;
     299             : 
     300             :   /* Parse u8 len */
     301           2 :   CHECK_REMAINING(1, truncated);
     302           2 :   obj->len = (trunnel_get_uint8(ptr));
     303           2 :   remaining -= 1; ptr += 1;
     304             :   {
     305           2 :     size_t remaining_after;
     306           2 :     CHECK_REMAINING(obj->len, truncated);
     307           2 :     remaining_after = remaining - obj->len;
     308           2 :     remaining = obj->len;
     309             : 
     310             :     /* Parse union addr[addr_type] */
     311           2 :     switch (obj->addr_type) {
     312             : 
     313           1 :       case NETINFO_ADDR_TYPE_IPV4:
     314             : 
     315             :         /* Parse u32 addr_ipv4 */
     316           1 :         CHECK_REMAINING(4, fail);
     317           1 :         obj->addr_ipv4 = trunnel_ntohl(trunnel_get_uint32(ptr));
     318           1 :         remaining -= 4; ptr += 4;
     319           1 :         break;
     320             : 
     321           0 :       case NETINFO_ADDR_TYPE_IPV6:
     322             : 
     323             :         /* Parse u8 addr_ipv6[16] */
     324           0 :         CHECK_REMAINING(16, fail);
     325           0 :         memcpy(obj->addr_ipv6, ptr, 16);
     326           0 :         remaining -= 16; ptr += 16;
     327           0 :         break;
     328             : 
     329           1 :       default:
     330             :         /* Skip to end of union */
     331           1 :         ptr += remaining; remaining = 0;
     332           1 :         break;
     333             :     }
     334           2 :     if (remaining != 0)
     335           0 :       goto fail;
     336           2 :     remaining = remaining_after;
     337             :   }
     338           2 :   trunnel_assert(ptr + remaining == input + len_in);
     339           2 :   return len_in - remaining;
     340             : 
     341             :  truncated:
     342             :   return -2;
     343             :  fail:
     344           2 :   result = -1;
     345             :   return result;
     346             : }
     347             : 
     348             : ssize_t
     349           2 : netinfo_addr_parse(netinfo_addr_t **output, const uint8_t *input, const size_t len_in)
     350             : {
     351           2 :   ssize_t result;
     352           2 :   *output = netinfo_addr_new();
     353           2 :   if (NULL == *output)
     354             :     return -1;
     355           2 :   result = netinfo_addr_parse_into(*output, input, len_in);
     356           2 :   if (result < 0) {
     357           0 :     netinfo_addr_free(*output);
     358           0 :     *output = NULL;
     359             :   }
     360             :   return result;
     361             : }
     362             : netinfo_cell_t *
     363           1 : netinfo_cell_new(void)
     364             : {
     365           1 :   netinfo_cell_t *val = trunnel_calloc(1, sizeof(netinfo_cell_t));
     366           1 :   if (NULL == val)
     367           0 :     return NULL;
     368             :   return val;
     369             : }
     370             : 
     371             : /** Release all storage held inside 'obj', but do not free 'obj'.
     372             :  */
     373             : static void
     374           1 : netinfo_cell_clear(netinfo_cell_t *obj)
     375             : {
     376           1 :   (void) obj;
     377           1 :   netinfo_addr_free(obj->other_addr);
     378           1 :   obj->other_addr = NULL;
     379             :   {
     380             : 
     381           1 :     unsigned idx;
     382           2 :     for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->my_addrs); ++idx) {
     383           1 :       netinfo_addr_free(TRUNNEL_DYNARRAY_GET(&obj->my_addrs, idx));
     384             :     }
     385             :   }
     386           1 :   TRUNNEL_DYNARRAY_WIPE(&obj->my_addrs);
     387           1 :   TRUNNEL_DYNARRAY_CLEAR(&obj->my_addrs);
     388           1 : }
     389             : 
     390             : void
     391           1 : netinfo_cell_free(netinfo_cell_t *obj)
     392             : {
     393           1 :   if (obj == NULL)
     394             :     return;
     395           1 :   netinfo_cell_clear(obj);
     396           1 :   trunnel_memwipe(obj, sizeof(netinfo_cell_t));
     397           1 :   trunnel_free_(obj);
     398             : }
     399             : 
     400             : uint32_t
     401           0 : netinfo_cell_get_timestamp(const netinfo_cell_t *inp)
     402             : {
     403           0 :   return inp->timestamp;
     404             : }
     405             : int
     406           0 : netinfo_cell_set_timestamp(netinfo_cell_t *inp, uint32_t val)
     407             : {
     408           0 :   inp->timestamp = val;
     409           0 :   return 0;
     410             : }
     411             : struct netinfo_addr_st *
     412           0 : netinfo_cell_get_other_addr(netinfo_cell_t *inp)
     413             : {
     414           0 :   return inp->other_addr;
     415             : }
     416             : const struct netinfo_addr_st *
     417           0 : netinfo_cell_getconst_other_addr(const netinfo_cell_t *inp)
     418             : {
     419           0 :   return netinfo_cell_get_other_addr((netinfo_cell_t*) inp);
     420             : }
     421             : int
     422           0 : netinfo_cell_set_other_addr(netinfo_cell_t *inp, struct netinfo_addr_st *val)
     423             : {
     424           0 :   if (inp->other_addr && inp->other_addr != val)
     425           0 :     netinfo_addr_free(inp->other_addr);
     426           0 :   return netinfo_cell_set0_other_addr(inp, val);
     427             : }
     428             : int
     429           0 : netinfo_cell_set0_other_addr(netinfo_cell_t *inp, struct netinfo_addr_st *val)
     430             : {
     431           0 :   inp->other_addr = val;
     432           0 :   return 0;
     433             : }
     434             : uint8_t
     435           0 : netinfo_cell_get_n_my_addrs(const netinfo_cell_t *inp)
     436             : {
     437           0 :   return inp->n_my_addrs;
     438             : }
     439             : int
     440           0 : netinfo_cell_set_n_my_addrs(netinfo_cell_t *inp, uint8_t val)
     441             : {
     442           0 :   inp->n_my_addrs = val;
     443           0 :   return 0;
     444             : }
     445             : size_t
     446           0 : netinfo_cell_getlen_my_addrs(const netinfo_cell_t *inp)
     447             : {
     448           0 :   return TRUNNEL_DYNARRAY_LEN(&inp->my_addrs);
     449             : }
     450             : 
     451             : struct netinfo_addr_st *
     452           1 : netinfo_cell_get_my_addrs(netinfo_cell_t *inp, size_t idx)
     453             : {
     454           1 :   return TRUNNEL_DYNARRAY_GET(&inp->my_addrs, idx);
     455             : }
     456             : 
     457             :  const struct netinfo_addr_st *
     458           0 : netinfo_cell_getconst_my_addrs(const netinfo_cell_t *inp, size_t idx)
     459             : {
     460           0 :   return netinfo_cell_get_my_addrs((netinfo_cell_t*)inp, idx);
     461             : }
     462             : int
     463           0 : netinfo_cell_set_my_addrs(netinfo_cell_t *inp, size_t idx, struct netinfo_addr_st * elt)
     464             : {
     465           0 :   netinfo_addr_t *oldval = TRUNNEL_DYNARRAY_GET(&inp->my_addrs, idx);
     466           0 :   if (oldval && oldval != elt)
     467           0 :     netinfo_addr_free(oldval);
     468           0 :   return netinfo_cell_set0_my_addrs(inp, idx, elt);
     469             : }
     470             : int
     471           0 : netinfo_cell_set0_my_addrs(netinfo_cell_t *inp, size_t idx, struct netinfo_addr_st * elt)
     472             : {
     473           0 :   TRUNNEL_DYNARRAY_SET(&inp->my_addrs, idx, elt);
     474           0 :   return 0;
     475             : }
     476             : int
     477           0 : netinfo_cell_add_my_addrs(netinfo_cell_t *inp, struct netinfo_addr_st * elt)
     478             : {
     479             : #if SIZE_MAX >= UINT8_MAX
     480           0 :   if (inp->my_addrs.n_ == UINT8_MAX)
     481           0 :     goto trunnel_alloc_failed;
     482             : #endif
     483           0 :   TRUNNEL_DYNARRAY_ADD(struct netinfo_addr_st *, &inp->my_addrs, elt, {});
     484           0 :   return 0;
     485           0 :  trunnel_alloc_failed:
     486           0 :   TRUNNEL_SET_ERROR_CODE(inp);
     487           0 :   return -1;
     488             : }
     489             : 
     490             : struct netinfo_addr_st * *
     491           0 : netinfo_cell_getarray_my_addrs(netinfo_cell_t *inp)
     492             : {
     493           0 :   return inp->my_addrs.elts_;
     494             : }
     495             : const struct netinfo_addr_st *  const  *
     496           0 : netinfo_cell_getconstarray_my_addrs(const netinfo_cell_t *inp)
     497             : {
     498           0 :   return (const struct netinfo_addr_st *  const  *)netinfo_cell_getarray_my_addrs((netinfo_cell_t*)inp);
     499             : }
     500             : int
     501           0 : netinfo_cell_setlen_my_addrs(netinfo_cell_t *inp, size_t newlen)
     502             : {
     503           0 :   struct netinfo_addr_st * *newptr;
     504             : #if UINT8_MAX < SIZE_MAX
     505           0 :   if (newlen > UINT8_MAX)
     506           0 :     goto trunnel_alloc_failed;
     507             : #endif
     508           0 :   newptr = trunnel_dynarray_setlen(&inp->my_addrs.allocated_,
     509           0 :                  &inp->my_addrs.n_, inp->my_addrs.elts_, newlen,
     510             :                  sizeof(inp->my_addrs.elts_[0]), (trunnel_free_fn_t) netinfo_addr_free,
     511             :                  &inp->trunnel_error_code_);
     512           0 :   if (newlen != 0 && newptr == NULL)
     513           0 :     goto trunnel_alloc_failed;
     514           0 :   inp->my_addrs.elts_ = newptr;
     515           0 :   return 0;
     516           0 :  trunnel_alloc_failed:
     517           0 :   TRUNNEL_SET_ERROR_CODE(inp);
     518           0 :   return -1;
     519             : }
     520             : const char *
     521           0 : netinfo_cell_check(const netinfo_cell_t *obj)
     522             : {
     523           0 :   if (obj == NULL)
     524             :     return "Object was NULL";
     525           0 :   if (obj->trunnel_error_code_)
     526             :     return "A set function failed on this object";
     527             :   {
     528           0 :     const char *msg;
     529           0 :     if (NULL != (msg = netinfo_addr_check(obj->other_addr)))
     530             :       return msg;
     531             :   }
     532             :   {
     533             :     const char *msg;
     534             : 
     535             :     unsigned idx;
     536           0 :     for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->my_addrs); ++idx) {
     537           0 :       if (NULL != (msg = netinfo_addr_check(TRUNNEL_DYNARRAY_GET(&obj->my_addrs, idx))))
     538           0 :         return msg;
     539             :     }
     540             :   }
     541           0 :   if (TRUNNEL_DYNARRAY_LEN(&obj->my_addrs) != obj->n_my_addrs)
     542           0 :     return "Length mismatch for my_addrs";
     543             :   return NULL;
     544             : }
     545             : 
     546             : ssize_t
     547           0 : netinfo_cell_encoded_len(const netinfo_cell_t *obj)
     548             : {
     549           0 :   ssize_t result = 0;
     550             : 
     551           0 :   if (NULL != netinfo_cell_check(obj))
     552             :      return -1;
     553             : 
     554             : 
     555             :   /* Length of u32 timestamp */
     556           0 :   result += 4;
     557             : 
     558             :   /* Length of struct netinfo_addr other_addr */
     559           0 :   result += netinfo_addr_encoded_len(obj->other_addr);
     560             : 
     561             :   /* Length of u8 n_my_addrs */
     562           0 :   result += 1;
     563             : 
     564             :   /* Length of struct netinfo_addr my_addrs[n_my_addrs] */
     565             :   {
     566             : 
     567           0 :     unsigned idx;
     568           0 :     for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->my_addrs); ++idx) {
     569           0 :       result += netinfo_addr_encoded_len(TRUNNEL_DYNARRAY_GET(&obj->my_addrs, idx));
     570             :     }
     571             :   }
     572             :   return result;
     573             : }
     574             : int
     575           0 : netinfo_cell_clear_errors(netinfo_cell_t *obj)
     576             : {
     577           0 :   int r = obj->trunnel_error_code_;
     578           0 :   obj->trunnel_error_code_ = 0;
     579           0 :   return r;
     580             : }
     581             : ssize_t
     582           0 : netinfo_cell_encode(uint8_t *output, const size_t avail, const netinfo_cell_t *obj)
     583             : {
     584           0 :   ssize_t result = 0;
     585           0 :   size_t written = 0;
     586           0 :   uint8_t *ptr = output;
     587           0 :   const char *msg;
     588             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
     589             :   const ssize_t encoded_len = netinfo_cell_encoded_len(obj);
     590             : #endif
     591             : 
     592           0 :   if (NULL != (msg = netinfo_cell_check(obj)))
     593           0 :     goto check_failed;
     594             : 
     595             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
     596             :   trunnel_assert(encoded_len >= 0);
     597             : #endif
     598             : 
     599             :   /* Encode u32 timestamp */
     600           0 :   trunnel_assert(written <= avail);
     601           0 :   if (avail - written < 4)
     602           0 :     goto truncated;
     603           0 :   trunnel_set_uint32(ptr, trunnel_htonl(obj->timestamp));
     604           0 :   written += 4; ptr += 4;
     605             : 
     606             :   /* Encode struct netinfo_addr other_addr */
     607           0 :   trunnel_assert(written <= avail);
     608           0 :   result = netinfo_addr_encode(ptr, avail - written, obj->other_addr);
     609           0 :   if (result < 0)
     610           0 :     goto fail; /* XXXXXXX !*/
     611           0 :   written += result; ptr += result;
     612             : 
     613             :   /* Encode u8 n_my_addrs */
     614           0 :   trunnel_assert(written <= avail);
     615           0 :   if (avail - written < 1)
     616           0 :     goto truncated;
     617           0 :   trunnel_set_uint8(ptr, (obj->n_my_addrs));
     618           0 :   written += 1; ptr += 1;
     619             : 
     620             :   /* Encode struct netinfo_addr my_addrs[n_my_addrs] */
     621             :   {
     622             : 
     623           0 :     unsigned idx;
     624           0 :     for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->my_addrs); ++idx) {
     625           0 :       trunnel_assert(written <= avail);
     626           0 :       result = netinfo_addr_encode(ptr, avail - written, TRUNNEL_DYNARRAY_GET(&obj->my_addrs, idx));
     627           0 :       if (result < 0)
     628           0 :         goto fail; /* XXXXXXX !*/
     629           0 :       written += result; ptr += result;
     630             :     }
     631             :   }
     632             : 
     633             : 
     634           0 :   trunnel_assert(ptr == output + written);
     635             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
     636             :   {
     637             :     trunnel_assert(encoded_len >= 0);
     638             :     trunnel_assert((size_t)encoded_len == written);
     639             :   }
     640             : 
     641             : #endif
     642             : 
     643           0 :   return written;
     644             : 
     645           0 :  truncated:
     646           0 :   result = -2;
     647           0 :   goto fail;
     648           0 :  check_failed:
     649           0 :   (void)msg;
     650           0 :   result = -1;
     651           0 :   goto fail;
     652             :  fail:
     653           0 :   trunnel_assert(result < 0);
     654             :   return result;
     655             : }
     656             : 
     657             : /** As netinfo_cell_parse(), but do not allocate the output object.
     658             :  */
     659             : static ssize_t
     660           1 : netinfo_cell_parse_into(netinfo_cell_t *obj, const uint8_t *input, const size_t len_in)
     661             : {
     662           1 :   const uint8_t *ptr = input;
     663           1 :   size_t remaining = len_in;
     664           1 :   ssize_t result = 0;
     665           1 :   (void)result;
     666             : 
     667             :   /* Parse u32 timestamp */
     668           1 :   CHECK_REMAINING(4, truncated);
     669           1 :   obj->timestamp = trunnel_ntohl(trunnel_get_uint32(ptr));
     670           1 :   remaining -= 4; ptr += 4;
     671             : 
     672             :   /* Parse struct netinfo_addr other_addr */
     673           1 :   result = netinfo_addr_parse(&obj->other_addr, ptr, remaining);
     674           1 :   if (result < 0)
     675           0 :     goto relay_fail;
     676           1 :   trunnel_assert((size_t)result <= remaining);
     677           1 :   remaining -= result; ptr += result;
     678             : 
     679             :   /* Parse u8 n_my_addrs */
     680           1 :   CHECK_REMAINING(1, truncated);
     681           1 :   obj->n_my_addrs = (trunnel_get_uint8(ptr));
     682           1 :   remaining -= 1; ptr += 1;
     683             : 
     684             :   /* Parse struct netinfo_addr my_addrs[n_my_addrs] */
     685           1 :   TRUNNEL_DYNARRAY_EXPAND(netinfo_addr_t *, &obj->my_addrs, obj->n_my_addrs, {});
     686             :   {
     687           1 :     netinfo_addr_t * elt;
     688           1 :     unsigned idx;
     689           2 :     for (idx = 0; idx < obj->n_my_addrs; ++idx) {
     690           1 :       result = netinfo_addr_parse(&elt, ptr, remaining);
     691           1 :       if (result < 0)
     692           0 :         goto relay_fail;
     693           1 :       trunnel_assert((size_t)result <= remaining);
     694           1 :       remaining -= result; ptr += result;
     695           1 :       TRUNNEL_DYNARRAY_ADD(netinfo_addr_t *, &obj->my_addrs, elt, {netinfo_addr_free(elt);});
     696             :     }
     697             :   }
     698           1 :   trunnel_assert(ptr + remaining == input + len_in);
     699           1 :   return len_in - remaining;
     700             : 
     701             :  truncated:
     702             :   return -2;
     703             :  relay_fail:
     704             :   trunnel_assert(result < 0);
     705             :   return result;
     706             :  trunnel_alloc_failed:
     707             :   return -1;
     708             : }
     709             : 
     710             : ssize_t
     711           1 : netinfo_cell_parse(netinfo_cell_t **output, const uint8_t *input, const size_t len_in)
     712             : {
     713           1 :   ssize_t result;
     714           1 :   *output = netinfo_cell_new();
     715           1 :   if (NULL == *output)
     716             :     return -1;
     717           1 :   result = netinfo_cell_parse_into(*output, input, len_in);
     718           1 :   if (result < 0) {
     719           0 :     netinfo_cell_free(*output);
     720           0 :     *output = NULL;
     721             :   }
     722             :   return result;
     723             : }

Generated by: LCOV version 1.14