LCOV - code coverage report
Current view: top level - trunnel - socks5.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 463 1429 32.4 %
Date: 2021-11-24 03:28:48 Functions: 71 203 35.0 %

          Line data    Source code
       1             : /* socks5.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 "socks5.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 socks_deadcode_dummy__ = 0;
      19             : #define OR_DEADCODE_DUMMY || socks_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             : domainname_t *
      32         290 : domainname_new(void)
      33             : {
      34         290 :   domainname_t *val = trunnel_calloc(1, sizeof(domainname_t));
      35         290 :   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         290 : domainname_clear(domainname_t *obj)
      44             : {
      45         290 :   (void) obj;
      46         290 :   TRUNNEL_DYNARRAY_WIPE(&obj->name);
      47         290 :   TRUNNEL_DYNARRAY_CLEAR(&obj->name);
      48         290 : }
      49             : 
      50             : void
      51         615 : domainname_free(domainname_t *obj)
      52             : {
      53         615 :   if (obj == NULL)
      54             :     return;
      55         290 :   domainname_clear(obj);
      56         290 :   trunnel_memwipe(obj, sizeof(domainname_t));
      57         290 :   trunnel_free_(obj);
      58             : }
      59             : 
      60             : uint8_t
      61           0 : domainname_get_len(const domainname_t *inp)
      62             : {
      63           0 :   return inp->len;
      64             : }
      65             : int
      66           0 : domainname_set_len(domainname_t *inp, uint8_t val)
      67             : {
      68           0 :   inp->len = val;
      69           0 :   return 0;
      70             : }
      71             : size_t
      72           0 : domainname_getlen_name(const domainname_t *inp)
      73             : {
      74           0 :   return TRUNNEL_DYNARRAY_LEN(&inp->name);
      75             : }
      76             : 
      77             : char
      78           0 : domainname_get_name(domainname_t *inp, size_t idx)
      79             : {
      80           0 :   return TRUNNEL_DYNARRAY_GET(&inp->name, idx);
      81             : }
      82             : 
      83             : char
      84           0 : domainname_getconst_name(const domainname_t *inp, size_t idx)
      85             : {
      86           0 :   return domainname_get_name((domainname_t*)inp, idx);
      87             : }
      88             : int
      89           0 : domainname_set_name(domainname_t *inp, size_t idx, char elt)
      90             : {
      91           0 :   TRUNNEL_DYNARRAY_SET(&inp->name, idx, elt);
      92           0 :   return 0;
      93             : }
      94             : int
      95           0 : domainname_add_name(domainname_t *inp, char elt)
      96             : {
      97             : #if SIZE_MAX >= UINT8_MAX
      98           0 :   if (inp->name.n_ == UINT8_MAX)
      99           0 :     goto trunnel_alloc_failed;
     100             : #endif
     101           0 :   TRUNNEL_DYNARRAY_ADD(char, &inp->name, elt, {});
     102           0 :   return 0;
     103           0 :  trunnel_alloc_failed:
     104           0 :   TRUNNEL_SET_ERROR_CODE(inp);
     105           0 :   return -1;
     106             : }
     107             : 
     108             : char *
     109           9 : domainname_getarray_name(domainname_t *inp)
     110             : {
     111           9 :   return inp->name.elts_;
     112             : }
     113             : const char  *
     114           9 : domainname_getconstarray_name(const domainname_t *inp)
     115             : {
     116           9 :   return (const char  *)domainname_getarray_name((domainname_t*)inp);
     117             : }
     118             : int
     119           0 : domainname_setlen_name(domainname_t *inp, size_t newlen)
     120             : {
     121             : #if UINT8_MAX < SIZE_MAX
     122           0 :   if (newlen > UINT8_MAX)
     123           0 :     goto trunnel_alloc_failed;
     124             : #endif
     125           0 :   return trunnel_string_setlen(&inp->name, newlen,
     126             :             &inp->trunnel_error_code_);
     127           0 :  trunnel_alloc_failed:
     128           0 :   TRUNNEL_SET_ERROR_CODE(inp);
     129           0 :   return -1;
     130             : }
     131             : const char *
     132           0 : domainname_getstr_name(domainname_t *inp)
     133             : {
     134           0 :   return trunnel_string_getstr(&inp->name);
     135             : }
     136             : int
     137          15 : domainname_setstr0_name(domainname_t *inp, const char *val, size_t len)
     138             : {
     139             : #if UINT8_MAX < SIZE_MAX
     140          15 :   if (len > UINT8_MAX) {
     141           0 :     TRUNNEL_SET_ERROR_CODE(inp);
     142           0 :     return -1;
     143             :   }
     144             : #endif
     145          15 :   return trunnel_string_setstr0(&inp->name, val, len, &inp->trunnel_error_code_);
     146             : }
     147             : int
     148           0 : domainname_setstr_name(domainname_t *inp, const char *val)
     149             : {
     150           0 :   return domainname_setstr0_name(inp, val, strlen(val));
     151             : }
     152             : const char *
     153           0 : domainname_check(const domainname_t *obj)
     154             : {
     155           0 :   if (obj == NULL)
     156             :     return "Object was NULL";
     157           0 :   if (obj->trunnel_error_code_)
     158             :     return "A set function failed on this object";
     159           0 :   if (TRUNNEL_DYNARRAY_LEN(&obj->name) != obj->len)
     160           0 :     return "Length mismatch for name";
     161             :   return NULL;
     162             : }
     163             : 
     164             : ssize_t
     165           0 : domainname_encoded_len(const domainname_t *obj)
     166             : {
     167           0 :   ssize_t result = 0;
     168             : 
     169           0 :   if (NULL != domainname_check(obj))
     170             :      return -1;
     171             : 
     172             : 
     173             :   /* Length of u8 len */
     174           0 :   result += 1;
     175             : 
     176             :   /* Length of char name[len] */
     177           0 :   result += TRUNNEL_DYNARRAY_LEN(&obj->name);
     178           0 :   return result;
     179             : }
     180             : int
     181           0 : domainname_clear_errors(domainname_t *obj)
     182             : {
     183           0 :   int r = obj->trunnel_error_code_;
     184           0 :   obj->trunnel_error_code_ = 0;
     185           0 :   return r;
     186             : }
     187             : ssize_t
     188           0 : domainname_encode(uint8_t *output, const size_t avail, const domainname_t *obj)
     189             : {
     190           0 :   ssize_t result = 0;
     191           0 :   size_t written = 0;
     192           0 :   uint8_t *ptr = output;
     193           0 :   const char *msg;
     194             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
     195             :   const ssize_t encoded_len = domainname_encoded_len(obj);
     196             : #endif
     197             : 
     198           0 :   if (NULL != (msg = domainname_check(obj)))
     199           0 :     goto check_failed;
     200             : 
     201             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
     202             :   trunnel_assert(encoded_len >= 0);
     203             : #endif
     204             : 
     205             :   /* Encode u8 len */
     206           0 :   trunnel_assert(written <= avail);
     207           0 :   if (avail - written < 1)
     208           0 :     goto truncated;
     209           0 :   trunnel_set_uint8(ptr, (obj->len));
     210           0 :   written += 1; ptr += 1;
     211             : 
     212             :   /* Encode char name[len] */
     213             :   {
     214           0 :     size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->name);
     215           0 :     trunnel_assert(obj->len == elt_len);
     216           0 :     trunnel_assert(written <= avail);
     217           0 :     if (avail - written < elt_len)
     218           0 :       goto truncated;
     219           0 :     if (elt_len)
     220           0 :       memcpy(ptr, obj->name.elts_, elt_len);
     221           0 :     written += elt_len; ptr += elt_len;
     222             :   }
     223             : 
     224             : 
     225           0 :   trunnel_assert(ptr == output + written);
     226             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
     227             :   {
     228             :     trunnel_assert(encoded_len >= 0);
     229             :     trunnel_assert((size_t)encoded_len == written);
     230             :   }
     231             : 
     232             : #endif
     233             : 
     234           0 :   return written;
     235             : 
     236           0 :  truncated:
     237           0 :   result = -2;
     238           0 :   goto fail;
     239           0 :  check_failed:
     240           0 :   (void)msg;
     241           0 :   result = -1;
     242           0 :   goto fail;
     243             :  fail:
     244             :   trunnel_assert(result < 0);
     245             :   return result;
     246             : }
     247             : 
     248             : /** As domainname_parse(), but do not allocate the output object.
     249             :  */
     250             : static ssize_t
     251         290 : domainname_parse_into(domainname_t *obj, const uint8_t *input, const size_t len_in)
     252             : {
     253         290 :   const uint8_t *ptr = input;
     254         290 :   size_t remaining = len_in;
     255         290 :   ssize_t result = 0;
     256         290 :   (void)result;
     257             : 
     258             :   /* Parse u8 len */
     259         290 :   CHECK_REMAINING(1, truncated);
     260         287 :   obj->len = (trunnel_get_uint8(ptr));
     261         287 :   remaining -= 1; ptr += 1;
     262             : 
     263             :   /* Parse char name[len] */
     264         287 :   CHECK_REMAINING(obj->len, truncated);
     265          15 :   if (domainname_setstr0_name(obj, (const char*)ptr, obj->len))
     266           0 :     goto fail;
     267          15 :   ptr += obj->len; remaining -= obj->len;
     268          15 :   trunnel_assert(ptr + remaining == input + len_in);
     269          15 :   return len_in - remaining;
     270             : 
     271             :  truncated:
     272             :   return -2;
     273           0 :  fail:
     274           0 :   result = -1;
     275           0 :   return result;
     276             : }
     277             : 
     278             : ssize_t
     279         290 : domainname_parse(domainname_t **output, const uint8_t *input, const size_t len_in)
     280             : {
     281         290 :   ssize_t result;
     282         290 :   *output = domainname_new();
     283         290 :   if (NULL == *output)
     284             :     return -1;
     285         290 :   result = domainname_parse_into(*output, input, len_in);
     286         290 :   if (result < 0) {
     287         275 :     domainname_free(*output);
     288         275 :     *output = NULL;
     289             :   }
     290             :   return result;
     291             : }
     292             : socks4_client_request_t *
     293          53 : socks4_client_request_new(void)
     294             : {
     295          53 :   socks4_client_request_t *val = trunnel_calloc(1, sizeof(socks4_client_request_t));
     296          53 :   if (NULL == val)
     297             :     return NULL;
     298          53 :   val->version = 4;
     299          53 :   val->command = CMD_BIND;
     300          53 :   return val;
     301             : }
     302             : 
     303             : /** Release all storage held inside 'obj', but do not free 'obj'.
     304             :  */
     305             : static void
     306          53 : socks4_client_request_clear(socks4_client_request_t *obj)
     307             : {
     308          53 :   (void) obj;
     309          53 :   trunnel_wipestr(obj->username);
     310          53 :   trunnel_free(obj->username);
     311          53 :   trunnel_wipestr(obj->socks4a_addr_hostname);
     312          53 :   trunnel_free(obj->socks4a_addr_hostname);
     313          53 : }
     314             : 
     315             : void
     316          98 : socks4_client_request_free(socks4_client_request_t *obj)
     317             : {
     318          98 :   if (obj == NULL)
     319             :     return;
     320          53 :   socks4_client_request_clear(obj);
     321          53 :   trunnel_memwipe(obj, sizeof(socks4_client_request_t));
     322          53 :   trunnel_free_(obj);
     323             : }
     324             : 
     325             : uint8_t
     326           0 : socks4_client_request_get_version(const socks4_client_request_t *inp)
     327             : {
     328           0 :   return inp->version;
     329             : }
     330             : int
     331           0 : socks4_client_request_set_version(socks4_client_request_t *inp, uint8_t val)
     332             : {
     333           0 :   if (! ((val == 4))) {
     334           0 :      TRUNNEL_SET_ERROR_CODE(inp);
     335           0 :      return -1;
     336             :   }
     337           0 :   inp->version = val;
     338           0 :   return 0;
     339             : }
     340             : uint8_t
     341           8 : socks4_client_request_get_command(const socks4_client_request_t *inp)
     342             : {
     343           8 :   return inp->command;
     344             : }
     345             : int
     346           0 : socks4_client_request_set_command(socks4_client_request_t *inp, uint8_t val)
     347             : {
     348           0 :   if (! ((val == CMD_BIND || val == CMD_CONNECT || val == CMD_RESOLVE || val == CMD_RESOLVE_PTR))) {
     349           0 :      TRUNNEL_SET_ERROR_CODE(inp);
     350           0 :      return -1;
     351             :   }
     352           0 :   inp->command = val;
     353           0 :   return 0;
     354             : }
     355             : uint16_t
     356           8 : socks4_client_request_get_port(const socks4_client_request_t *inp)
     357             : {
     358           8 :   return inp->port;
     359             : }
     360             : int
     361           0 : socks4_client_request_set_port(socks4_client_request_t *inp, uint16_t val)
     362             : {
     363           0 :   inp->port = val;
     364           0 :   return 0;
     365             : }
     366             : uint32_t
     367           8 : socks4_client_request_get_addr(const socks4_client_request_t *inp)
     368             : {
     369           8 :   return inp->addr;
     370             : }
     371             : int
     372           0 : socks4_client_request_set_addr(socks4_client_request_t *inp, uint32_t val)
     373             : {
     374           0 :   inp->addr = val;
     375           0 :   return 0;
     376             : }
     377             : const char *
     378           6 : socks4_client_request_get_username(const socks4_client_request_t *inp)
     379             : {
     380           6 :   return inp->username;
     381             : }
     382             : int
     383           0 : socks4_client_request_set_username(socks4_client_request_t *inp, const char *val)
     384             : {
     385           0 :   trunnel_free(inp->username);
     386           0 :   if (NULL == (inp->username = trunnel_strdup(val))) {
     387           0 :     TRUNNEL_SET_ERROR_CODE(inp);
     388           0 :     return -1;
     389             :   }
     390             :   return 0;
     391             : }
     392             : const char *
     393           2 : socks4_client_request_get_socks4a_addr_hostname(const socks4_client_request_t *inp)
     394             : {
     395           2 :   return inp->socks4a_addr_hostname;
     396             : }
     397             : int
     398           0 : socks4_client_request_set_socks4a_addr_hostname(socks4_client_request_t *inp, const char *val)
     399             : {
     400           0 :   trunnel_free(inp->socks4a_addr_hostname);
     401           0 :   if (NULL == (inp->socks4a_addr_hostname = trunnel_strdup(val))) {
     402           0 :     TRUNNEL_SET_ERROR_CODE(inp);
     403           0 :     return -1;
     404             :   }
     405             :   return 0;
     406             : }
     407             : const char *
     408           0 : socks4_client_request_check(const socks4_client_request_t *obj)
     409             : {
     410           0 :   if (obj == NULL)
     411             :     return "Object was NULL";
     412           0 :   if (obj->trunnel_error_code_)
     413             :     return "A set function failed on this object";
     414           0 :   if (! (obj->version == 4))
     415             :     return "Integer out of bounds";
     416           0 :   if (! (obj->command == CMD_BIND || obj->command == CMD_CONNECT || obj->command == CMD_RESOLVE || obj->command == CMD_RESOLVE_PTR))
     417             :     return "Integer out of bounds";
     418           0 :   if (NULL == obj->username)
     419             :     return "Missing username";
     420           0 :   switch (obj->addr) {
     421             : 
     422           0 :     case 1:
     423             :     case 2:
     424             :     case 3:
     425             :     case 4:
     426             :     case 5:
     427             :     case 6:
     428             :     case 7:
     429             :     case 8:
     430             :     case 9:
     431             :     case 10:
     432             :     case 11:
     433             :     case 12:
     434             :     case 13:
     435             :     case 14:
     436             :     case 15:
     437             :     case 16:
     438             :     case 17:
     439             :     case 18:
     440             :     case 19:
     441             :     case 20:
     442             :     case 21:
     443             :     case 22:
     444             :     case 23:
     445             :     case 24:
     446             :     case 25:
     447             :     case 26:
     448             :     case 27:
     449             :     case 28:
     450             :     case 29:
     451             :     case 30:
     452             :     case 31:
     453             :     case 32:
     454             :     case 33:
     455             :     case 34:
     456             :     case 35:
     457             :     case 36:
     458             :     case 37:
     459             :     case 38:
     460             :     case 39:
     461             :     case 40:
     462             :     case 41:
     463             :     case 42:
     464             :     case 43:
     465             :     case 44:
     466             :     case 45:
     467             :     case 46:
     468             :     case 47:
     469             :     case 48:
     470             :     case 49:
     471             :     case 50:
     472             :     case 51:
     473             :     case 52:
     474             :     case 53:
     475             :     case 54:
     476             :     case 55:
     477             :     case 56:
     478             :     case 57:
     479             :     case 58:
     480             :     case 59:
     481             :     case 60:
     482             :     case 61:
     483             :     case 62:
     484             :     case 63:
     485             :     case 64:
     486             :     case 65:
     487             :     case 66:
     488             :     case 67:
     489             :     case 68:
     490             :     case 69:
     491             :     case 70:
     492             :     case 71:
     493             :     case 72:
     494             :     case 73:
     495             :     case 74:
     496             :     case 75:
     497             :     case 76:
     498             :     case 77:
     499             :     case 78:
     500             :     case 79:
     501             :     case 80:
     502             :     case 81:
     503             :     case 82:
     504             :     case 83:
     505             :     case 84:
     506             :     case 85:
     507             :     case 86:
     508             :     case 87:
     509             :     case 88:
     510             :     case 89:
     511             :     case 90:
     512             :     case 91:
     513             :     case 92:
     514             :     case 93:
     515             :     case 94:
     516             :     case 95:
     517             :     case 96:
     518             :     case 97:
     519             :     case 98:
     520             :     case 99:
     521             :     case 100:
     522             :     case 101:
     523             :     case 102:
     524             :     case 103:
     525             :     case 104:
     526             :     case 105:
     527             :     case 106:
     528             :     case 107:
     529             :     case 108:
     530             :     case 109:
     531             :     case 110:
     532             :     case 111:
     533             :     case 112:
     534             :     case 113:
     535             :     case 114:
     536             :     case 115:
     537             :     case 116:
     538             :     case 117:
     539             :     case 118:
     540             :     case 119:
     541             :     case 120:
     542             :     case 121:
     543             :     case 122:
     544             :     case 123:
     545             :     case 124:
     546             :     case 125:
     547             :     case 126:
     548             :     case 127:
     549             :     case 128:
     550             :     case 129:
     551             :     case 130:
     552             :     case 131:
     553             :     case 132:
     554             :     case 133:
     555             :     case 134:
     556             :     case 135:
     557             :     case 136:
     558             :     case 137:
     559             :     case 138:
     560             :     case 139:
     561             :     case 140:
     562             :     case 141:
     563             :     case 142:
     564             :     case 143:
     565             :     case 144:
     566             :     case 145:
     567             :     case 146:
     568             :     case 147:
     569             :     case 148:
     570             :     case 149:
     571             :     case 150:
     572             :     case 151:
     573             :     case 152:
     574             :     case 153:
     575             :     case 154:
     576             :     case 155:
     577             :     case 156:
     578             :     case 157:
     579             :     case 158:
     580             :     case 159:
     581             :     case 160:
     582             :     case 161:
     583             :     case 162:
     584             :     case 163:
     585             :     case 164:
     586             :     case 165:
     587             :     case 166:
     588             :     case 167:
     589             :     case 168:
     590             :     case 169:
     591             :     case 170:
     592             :     case 171:
     593             :     case 172:
     594             :     case 173:
     595             :     case 174:
     596             :     case 175:
     597             :     case 176:
     598             :     case 177:
     599             :     case 178:
     600             :     case 179:
     601             :     case 180:
     602             :     case 181:
     603             :     case 182:
     604             :     case 183:
     605             :     case 184:
     606             :     case 185:
     607             :     case 186:
     608             :     case 187:
     609             :     case 188:
     610             :     case 189:
     611             :     case 190:
     612             :     case 191:
     613             :     case 192:
     614             :     case 193:
     615             :     case 194:
     616             :     case 195:
     617             :     case 196:
     618             :     case 197:
     619             :     case 198:
     620             :     case 199:
     621             :     case 200:
     622             :     case 201:
     623             :     case 202:
     624             :     case 203:
     625             :     case 204:
     626             :     case 205:
     627             :     case 206:
     628             :     case 207:
     629             :     case 208:
     630             :     case 209:
     631             :     case 210:
     632             :     case 211:
     633             :     case 212:
     634             :     case 213:
     635             :     case 214:
     636             :     case 215:
     637             :     case 216:
     638             :     case 217:
     639             :     case 218:
     640             :     case 219:
     641             :     case 220:
     642             :     case 221:
     643             :     case 222:
     644             :     case 223:
     645             :     case 224:
     646             :     case 225:
     647             :     case 226:
     648             :     case 227:
     649             :     case 228:
     650             :     case 229:
     651             :     case 230:
     652             :     case 231:
     653             :     case 232:
     654             :     case 233:
     655             :     case 234:
     656             :     case 235:
     657             :     case 236:
     658             :     case 237:
     659             :     case 238:
     660             :     case 239:
     661             :     case 240:
     662             :     case 241:
     663             :     case 242:
     664             :     case 243:
     665             :     case 244:
     666             :     case 245:
     667             :     case 246:
     668             :     case 247:
     669             :     case 248:
     670             :     case 249:
     671             :     case 250:
     672             :     case 251:
     673             :     case 252:
     674             :     case 253:
     675             :     case 254:
     676             :     case 255:
     677           0 :       if (NULL == obj->socks4a_addr_hostname)
     678           0 :         return "Missing socks4a_addr_hostname";
     679             :       break;
     680             : 
     681             :     default:
     682             :       break;
     683             :   }
     684             :   return NULL;
     685             : }
     686             : 
     687             : ssize_t
     688           0 : socks4_client_request_encoded_len(const socks4_client_request_t *obj)
     689             : {
     690           0 :   ssize_t result = 0;
     691             : 
     692           0 :   if (NULL != socks4_client_request_check(obj))
     693             :      return -1;
     694             : 
     695             : 
     696             :   /* Length of u8 version IN [4] */
     697           0 :   result += 1;
     698             : 
     699             :   /* Length of u8 command IN [CMD_BIND, CMD_CONNECT, CMD_RESOLVE, CMD_RESOLVE_PTR] */
     700           0 :   result += 1;
     701             : 
     702             :   /* Length of u16 port */
     703           0 :   result += 2;
     704             : 
     705             :   /* Length of u32 addr */
     706           0 :   result += 4;
     707             : 
     708             :   /* Length of nulterm username */
     709           0 :   result += strlen(obj->username) + 1;
     710           0 :   switch (obj->addr) {
     711             : 
     712           0 :     case 1:
     713             :     case 2:
     714             :     case 3:
     715             :     case 4:
     716             :     case 5:
     717             :     case 6:
     718             :     case 7:
     719             :     case 8:
     720             :     case 9:
     721             :     case 10:
     722             :     case 11:
     723             :     case 12:
     724             :     case 13:
     725             :     case 14:
     726             :     case 15:
     727             :     case 16:
     728             :     case 17:
     729             :     case 18:
     730             :     case 19:
     731             :     case 20:
     732             :     case 21:
     733             :     case 22:
     734             :     case 23:
     735             :     case 24:
     736             :     case 25:
     737             :     case 26:
     738             :     case 27:
     739             :     case 28:
     740             :     case 29:
     741             :     case 30:
     742             :     case 31:
     743             :     case 32:
     744             :     case 33:
     745             :     case 34:
     746             :     case 35:
     747             :     case 36:
     748             :     case 37:
     749             :     case 38:
     750             :     case 39:
     751             :     case 40:
     752             :     case 41:
     753             :     case 42:
     754             :     case 43:
     755             :     case 44:
     756             :     case 45:
     757             :     case 46:
     758             :     case 47:
     759             :     case 48:
     760             :     case 49:
     761             :     case 50:
     762             :     case 51:
     763             :     case 52:
     764             :     case 53:
     765             :     case 54:
     766             :     case 55:
     767             :     case 56:
     768             :     case 57:
     769             :     case 58:
     770             :     case 59:
     771             :     case 60:
     772             :     case 61:
     773             :     case 62:
     774             :     case 63:
     775             :     case 64:
     776             :     case 65:
     777             :     case 66:
     778             :     case 67:
     779             :     case 68:
     780             :     case 69:
     781             :     case 70:
     782             :     case 71:
     783             :     case 72:
     784             :     case 73:
     785             :     case 74:
     786             :     case 75:
     787             :     case 76:
     788             :     case 77:
     789             :     case 78:
     790             :     case 79:
     791             :     case 80:
     792             :     case 81:
     793             :     case 82:
     794             :     case 83:
     795             :     case 84:
     796             :     case 85:
     797             :     case 86:
     798             :     case 87:
     799             :     case 88:
     800             :     case 89:
     801             :     case 90:
     802             :     case 91:
     803             :     case 92:
     804             :     case 93:
     805             :     case 94:
     806             :     case 95:
     807             :     case 96:
     808             :     case 97:
     809             :     case 98:
     810             :     case 99:
     811             :     case 100:
     812             :     case 101:
     813             :     case 102:
     814             :     case 103:
     815             :     case 104:
     816             :     case 105:
     817             :     case 106:
     818             :     case 107:
     819             :     case 108:
     820             :     case 109:
     821             :     case 110:
     822             :     case 111:
     823             :     case 112:
     824             :     case 113:
     825             :     case 114:
     826             :     case 115:
     827             :     case 116:
     828             :     case 117:
     829             :     case 118:
     830             :     case 119:
     831             :     case 120:
     832             :     case 121:
     833             :     case 122:
     834             :     case 123:
     835             :     case 124:
     836             :     case 125:
     837             :     case 126:
     838             :     case 127:
     839             :     case 128:
     840             :     case 129:
     841             :     case 130:
     842             :     case 131:
     843             :     case 132:
     844             :     case 133:
     845             :     case 134:
     846             :     case 135:
     847             :     case 136:
     848             :     case 137:
     849             :     case 138:
     850             :     case 139:
     851             :     case 140:
     852             :     case 141:
     853             :     case 142:
     854             :     case 143:
     855             :     case 144:
     856             :     case 145:
     857             :     case 146:
     858             :     case 147:
     859             :     case 148:
     860             :     case 149:
     861             :     case 150:
     862             :     case 151:
     863             :     case 152:
     864             :     case 153:
     865             :     case 154:
     866             :     case 155:
     867             :     case 156:
     868             :     case 157:
     869             :     case 158:
     870             :     case 159:
     871             :     case 160:
     872             :     case 161:
     873             :     case 162:
     874             :     case 163:
     875             :     case 164:
     876             :     case 165:
     877             :     case 166:
     878             :     case 167:
     879             :     case 168:
     880             :     case 169:
     881             :     case 170:
     882             :     case 171:
     883             :     case 172:
     884             :     case 173:
     885             :     case 174:
     886             :     case 175:
     887             :     case 176:
     888             :     case 177:
     889             :     case 178:
     890             :     case 179:
     891             :     case 180:
     892             :     case 181:
     893             :     case 182:
     894             :     case 183:
     895             :     case 184:
     896             :     case 185:
     897             :     case 186:
     898             :     case 187:
     899             :     case 188:
     900             :     case 189:
     901             :     case 190:
     902             :     case 191:
     903             :     case 192:
     904             :     case 193:
     905             :     case 194:
     906             :     case 195:
     907             :     case 196:
     908             :     case 197:
     909             :     case 198:
     910             :     case 199:
     911             :     case 200:
     912             :     case 201:
     913             :     case 202:
     914             :     case 203:
     915             :     case 204:
     916             :     case 205:
     917             :     case 206:
     918             :     case 207:
     919             :     case 208:
     920             :     case 209:
     921             :     case 210:
     922             :     case 211:
     923             :     case 212:
     924             :     case 213:
     925             :     case 214:
     926             :     case 215:
     927             :     case 216:
     928             :     case 217:
     929             :     case 218:
     930             :     case 219:
     931             :     case 220:
     932             :     case 221:
     933             :     case 222:
     934             :     case 223:
     935             :     case 224:
     936             :     case 225:
     937             :     case 226:
     938             :     case 227:
     939             :     case 228:
     940             :     case 229:
     941             :     case 230:
     942             :     case 231:
     943             :     case 232:
     944             :     case 233:
     945             :     case 234:
     946             :     case 235:
     947             :     case 236:
     948             :     case 237:
     949             :     case 238:
     950             :     case 239:
     951             :     case 240:
     952             :     case 241:
     953             :     case 242:
     954             :     case 243:
     955             :     case 244:
     956             :     case 245:
     957             :     case 246:
     958             :     case 247:
     959             :     case 248:
     960             :     case 249:
     961             :     case 250:
     962             :     case 251:
     963             :     case 252:
     964             :     case 253:
     965             :     case 254:
     966             :     case 255:
     967             : 
     968             :       /* Length of nulterm socks4a_addr_hostname */
     969           0 :       result += strlen(obj->socks4a_addr_hostname) + 1;
     970           0 :       break;
     971             : 
     972             :     default:
     973             :       break;
     974             :   }
     975             :   return result;
     976             : }
     977             : int
     978           0 : socks4_client_request_clear_errors(socks4_client_request_t *obj)
     979             : {
     980           0 :   int r = obj->trunnel_error_code_;
     981           0 :   obj->trunnel_error_code_ = 0;
     982           0 :   return r;
     983             : }
     984             : ssize_t
     985           0 : socks4_client_request_encode(uint8_t *output, const size_t avail, const socks4_client_request_t *obj)
     986             : {
     987           0 :   ssize_t result = 0;
     988           0 :   size_t written = 0;
     989           0 :   uint8_t *ptr = output;
     990           0 :   const char *msg;
     991             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
     992             :   const ssize_t encoded_len = socks4_client_request_encoded_len(obj);
     993             : #endif
     994             : 
     995           0 :   if (NULL != (msg = socks4_client_request_check(obj)))
     996           0 :     goto check_failed;
     997             : 
     998             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
     999             :   trunnel_assert(encoded_len >= 0);
    1000             : #endif
    1001             : 
    1002             :   /* Encode u8 version IN [4] */
    1003           0 :   trunnel_assert(written <= avail);
    1004           0 :   if (avail - written < 1)
    1005           0 :     goto truncated;
    1006           0 :   trunnel_set_uint8(ptr, (obj->version));
    1007           0 :   written += 1; ptr += 1;
    1008             : 
    1009             :   /* Encode u8 command IN [CMD_BIND, CMD_CONNECT, CMD_RESOLVE, CMD_RESOLVE_PTR] */
    1010           0 :   trunnel_assert(written <= avail);
    1011           0 :   if (avail - written < 1)
    1012           0 :     goto truncated;
    1013           0 :   trunnel_set_uint8(ptr, (obj->command));
    1014           0 :   written += 1; ptr += 1;
    1015             : 
    1016             :   /* Encode u16 port */
    1017           0 :   trunnel_assert(written <= avail);
    1018           0 :   if (avail - written < 2)
    1019           0 :     goto truncated;
    1020           0 :   trunnel_set_uint16(ptr, trunnel_htons(obj->port));
    1021           0 :   written += 2; ptr += 2;
    1022             : 
    1023             :   /* Encode u32 addr */
    1024           0 :   trunnel_assert(written <= avail);
    1025           0 :   if (avail - written < 4)
    1026           0 :     goto truncated;
    1027           0 :   trunnel_set_uint32(ptr, trunnel_htonl(obj->addr));
    1028           0 :   written += 4; ptr += 4;
    1029             : 
    1030             :   /* Encode nulterm username */
    1031             :   {
    1032           0 :     size_t len = strlen(obj->username);
    1033           0 :     trunnel_assert(written <= avail);
    1034           0 :     if (avail - written < len + 1)
    1035           0 :       goto truncated;
    1036           0 :     memcpy(ptr, obj->username, len + 1);
    1037           0 :     ptr += len + 1; written += len + 1;
    1038             :   }
    1039             : 
    1040             :   /* Encode union socks4a_addr[addr] */
    1041           0 :   trunnel_assert(written <= avail);
    1042           0 :   switch (obj->addr) {
    1043             : 
    1044           0 :     case 1:
    1045             :     case 2:
    1046             :     case 3:
    1047             :     case 4:
    1048             :     case 5:
    1049             :     case 6:
    1050             :     case 7:
    1051             :     case 8:
    1052             :     case 9:
    1053             :     case 10:
    1054             :     case 11:
    1055             :     case 12:
    1056             :     case 13:
    1057             :     case 14:
    1058             :     case 15:
    1059             :     case 16:
    1060             :     case 17:
    1061             :     case 18:
    1062             :     case 19:
    1063             :     case 20:
    1064             :     case 21:
    1065             :     case 22:
    1066             :     case 23:
    1067             :     case 24:
    1068             :     case 25:
    1069             :     case 26:
    1070             :     case 27:
    1071             :     case 28:
    1072             :     case 29:
    1073             :     case 30:
    1074             :     case 31:
    1075             :     case 32:
    1076             :     case 33:
    1077             :     case 34:
    1078             :     case 35:
    1079             :     case 36:
    1080             :     case 37:
    1081             :     case 38:
    1082             :     case 39:
    1083             :     case 40:
    1084             :     case 41:
    1085             :     case 42:
    1086             :     case 43:
    1087             :     case 44:
    1088             :     case 45:
    1089             :     case 46:
    1090             :     case 47:
    1091             :     case 48:
    1092             :     case 49:
    1093             :     case 50:
    1094             :     case 51:
    1095             :     case 52:
    1096             :     case 53:
    1097             :     case 54:
    1098             :     case 55:
    1099             :     case 56:
    1100             :     case 57:
    1101             :     case 58:
    1102             :     case 59:
    1103             :     case 60:
    1104             :     case 61:
    1105             :     case 62:
    1106             :     case 63:
    1107             :     case 64:
    1108             :     case 65:
    1109             :     case 66:
    1110             :     case 67:
    1111             :     case 68:
    1112             :     case 69:
    1113             :     case 70:
    1114             :     case 71:
    1115             :     case 72:
    1116             :     case 73:
    1117             :     case 74:
    1118             :     case 75:
    1119             :     case 76:
    1120             :     case 77:
    1121             :     case 78:
    1122             :     case 79:
    1123             :     case 80:
    1124             :     case 81:
    1125             :     case 82:
    1126             :     case 83:
    1127             :     case 84:
    1128             :     case 85:
    1129             :     case 86:
    1130             :     case 87:
    1131             :     case 88:
    1132             :     case 89:
    1133             :     case 90:
    1134             :     case 91:
    1135             :     case 92:
    1136             :     case 93:
    1137             :     case 94:
    1138             :     case 95:
    1139             :     case 96:
    1140             :     case 97:
    1141             :     case 98:
    1142             :     case 99:
    1143             :     case 100:
    1144             :     case 101:
    1145             :     case 102:
    1146             :     case 103:
    1147             :     case 104:
    1148             :     case 105:
    1149             :     case 106:
    1150             :     case 107:
    1151             :     case 108:
    1152             :     case 109:
    1153             :     case 110:
    1154             :     case 111:
    1155             :     case 112:
    1156             :     case 113:
    1157             :     case 114:
    1158             :     case 115:
    1159             :     case 116:
    1160             :     case 117:
    1161             :     case 118:
    1162             :     case 119:
    1163             :     case 120:
    1164             :     case 121:
    1165             :     case 122:
    1166             :     case 123:
    1167             :     case 124:
    1168             :     case 125:
    1169             :     case 126:
    1170             :     case 127:
    1171             :     case 128:
    1172             :     case 129:
    1173             :     case 130:
    1174             :     case 131:
    1175             :     case 132:
    1176             :     case 133:
    1177             :     case 134:
    1178             :     case 135:
    1179             :     case 136:
    1180             :     case 137:
    1181             :     case 138:
    1182             :     case 139:
    1183             :     case 140:
    1184             :     case 141:
    1185             :     case 142:
    1186             :     case 143:
    1187             :     case 144:
    1188             :     case 145:
    1189             :     case 146:
    1190             :     case 147:
    1191             :     case 148:
    1192             :     case 149:
    1193             :     case 150:
    1194             :     case 151:
    1195             :     case 152:
    1196             :     case 153:
    1197             :     case 154:
    1198             :     case 155:
    1199             :     case 156:
    1200             :     case 157:
    1201             :     case 158:
    1202             :     case 159:
    1203             :     case 160:
    1204             :     case 161:
    1205             :     case 162:
    1206             :     case 163:
    1207             :     case 164:
    1208             :     case 165:
    1209             :     case 166:
    1210             :     case 167:
    1211             :     case 168:
    1212             :     case 169:
    1213             :     case 170:
    1214             :     case 171:
    1215             :     case 172:
    1216             :     case 173:
    1217             :     case 174:
    1218             :     case 175:
    1219             :     case 176:
    1220             :     case 177:
    1221             :     case 178:
    1222             :     case 179:
    1223             :     case 180:
    1224             :     case 181:
    1225             :     case 182:
    1226             :     case 183:
    1227             :     case 184:
    1228             :     case 185:
    1229             :     case 186:
    1230             :     case 187:
    1231             :     case 188:
    1232             :     case 189:
    1233             :     case 190:
    1234             :     case 191:
    1235             :     case 192:
    1236             :     case 193:
    1237             :     case 194:
    1238             :     case 195:
    1239             :     case 196:
    1240             :     case 197:
    1241             :     case 198:
    1242             :     case 199:
    1243             :     case 200:
    1244             :     case 201:
    1245             :     case 202:
    1246             :     case 203:
    1247             :     case 204:
    1248             :     case 205:
    1249             :     case 206:
    1250             :     case 207:
    1251             :     case 208:
    1252             :     case 209:
    1253             :     case 210:
    1254             :     case 211:
    1255             :     case 212:
    1256             :     case 213:
    1257             :     case 214:
    1258             :     case 215:
    1259             :     case 216:
    1260             :     case 217:
    1261             :     case 218:
    1262             :     case 219:
    1263             :     case 220:
    1264             :     case 221:
    1265             :     case 222:
    1266             :     case 223:
    1267             :     case 224:
    1268             :     case 225:
    1269             :     case 226:
    1270             :     case 227:
    1271             :     case 228:
    1272             :     case 229:
    1273             :     case 230:
    1274             :     case 231:
    1275             :     case 232:
    1276             :     case 233:
    1277             :     case 234:
    1278             :     case 235:
    1279             :     case 236:
    1280             :     case 237:
    1281             :     case 238:
    1282             :     case 239:
    1283             :     case 240:
    1284             :     case 241:
    1285             :     case 242:
    1286             :     case 243:
    1287             :     case 244:
    1288             :     case 245:
    1289             :     case 246:
    1290             :     case 247:
    1291             :     case 248:
    1292             :     case 249:
    1293             :     case 250:
    1294             :     case 251:
    1295             :     case 252:
    1296             :     case 253:
    1297             :     case 254:
    1298             :     case 255:
    1299             : 
    1300             :       /* Encode nulterm socks4a_addr_hostname */
    1301             :       {
    1302           0 :         size_t len = strlen(obj->socks4a_addr_hostname);
    1303           0 :         trunnel_assert(written <= avail);
    1304           0 :         if (avail - written < len + 1)
    1305           0 :           goto truncated;
    1306           0 :         memcpy(ptr, obj->socks4a_addr_hostname, len + 1);
    1307           0 :         ptr += len + 1; written += len + 1;
    1308             :       }
    1309           0 :       break;
    1310             : 
    1311             :     default:
    1312             :       break;
    1313             :   }
    1314             : 
    1315             : 
    1316           0 :   trunnel_assert(ptr == output + written);
    1317             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
    1318             :   {
    1319             :     trunnel_assert(encoded_len >= 0);
    1320             :     trunnel_assert((size_t)encoded_len == written);
    1321             :   }
    1322             : 
    1323             : #endif
    1324             : 
    1325           0 :   return written;
    1326             : 
    1327           0 :  truncated:
    1328           0 :   result = -2;
    1329           0 :   goto fail;
    1330           0 :  check_failed:
    1331           0 :   (void)msg;
    1332           0 :   result = -1;
    1333           0 :   goto fail;
    1334             :  fail:
    1335             :   trunnel_assert(result < 0);
    1336             :   return result;
    1337             : }
    1338             : 
    1339             : /** As socks4_client_request_parse(), but do not allocate the output
    1340             :  * object.
    1341             :  */
    1342             : static ssize_t
    1343          53 : socks4_client_request_parse_into(socks4_client_request_t *obj, const uint8_t *input, const size_t len_in)
    1344             : {
    1345          53 :   const uint8_t *ptr = input;
    1346          53 :   size_t remaining = len_in;
    1347          53 :   ssize_t result = 0;
    1348          53 :   (void)result;
    1349             : 
    1350             :   /* Parse u8 version IN [4] */
    1351          53 :   CHECK_REMAINING(1, truncated);
    1352          53 :   obj->version = (trunnel_get_uint8(ptr));
    1353          53 :   remaining -= 1; ptr += 1;
    1354          53 :   if (! (obj->version == 4))
    1355           0 :     goto fail;
    1356             : 
    1357             :   /* Parse u8 command IN [CMD_BIND, CMD_CONNECT, CMD_RESOLVE, CMD_RESOLVE_PTR] */
    1358          53 :   CHECK_REMAINING(1, truncated);
    1359          53 :   obj->command = (trunnel_get_uint8(ptr));
    1360          53 :   remaining -= 1; ptr += 1;
    1361          53 :   if (! (obj->command == CMD_BIND || obj->command == CMD_CONNECT || obj->command == CMD_RESOLVE || obj->command == CMD_RESOLVE_PTR))
    1362           0 :     goto fail;
    1363             : 
    1364             :   /* Parse u16 port */
    1365          53 :   CHECK_REMAINING(2, truncated);
    1366          53 :   obj->port = trunnel_ntohs(trunnel_get_uint16(ptr));
    1367          53 :   remaining -= 2; ptr += 2;
    1368             : 
    1369             :   /* Parse u32 addr */
    1370          53 :   CHECK_REMAINING(4, truncated);
    1371          53 :   obj->addr = trunnel_ntohl(trunnel_get_uint32(ptr));
    1372          53 :   remaining -= 4; ptr += 4;
    1373             : 
    1374             :   /* Parse nulterm username */
    1375             :   {
    1376          53 :     uint8_t *eos = (uint8_t*)memchr(ptr, 0, remaining);
    1377          53 :     size_t memlen;
    1378          53 :     if (eos == NULL)
    1379          12 :       goto truncated;
    1380          41 :     trunnel_assert(eos >= ptr);
    1381          41 :     trunnel_assert((size_t)(eos - ptr) < SIZE_MAX - 1);
    1382          41 :     memlen = ((size_t)(eos - ptr)) + 1;
    1383          41 :     if (!(obj->username = trunnel_malloc(memlen)))
    1384           0 :       goto fail;
    1385          41 :     memcpy(obj->username, ptr, memlen);
    1386          41 :     remaining -= memlen; ptr += memlen;
    1387             :   }
    1388             : 
    1389             :   /* Parse union socks4a_addr[addr] */
    1390          41 :   switch (obj->addr) {
    1391             : 
    1392          36 :     case 1:
    1393             :     case 2:
    1394             :     case 3:
    1395             :     case 4:
    1396             :     case 5:
    1397             :     case 6:
    1398             :     case 7:
    1399             :     case 8:
    1400             :     case 9:
    1401             :     case 10:
    1402             :     case 11:
    1403             :     case 12:
    1404             :     case 13:
    1405             :     case 14:
    1406             :     case 15:
    1407             :     case 16:
    1408             :     case 17:
    1409             :     case 18:
    1410             :     case 19:
    1411             :     case 20:
    1412             :     case 21:
    1413             :     case 22:
    1414             :     case 23:
    1415             :     case 24:
    1416             :     case 25:
    1417             :     case 26:
    1418             :     case 27:
    1419             :     case 28:
    1420             :     case 29:
    1421             :     case 30:
    1422             :     case 31:
    1423             :     case 32:
    1424             :     case 33:
    1425             :     case 34:
    1426             :     case 35:
    1427             :     case 36:
    1428             :     case 37:
    1429             :     case 38:
    1430             :     case 39:
    1431             :     case 40:
    1432             :     case 41:
    1433             :     case 42:
    1434             :     case 43:
    1435             :     case 44:
    1436             :     case 45:
    1437             :     case 46:
    1438             :     case 47:
    1439             :     case 48:
    1440             :     case 49:
    1441             :     case 50:
    1442             :     case 51:
    1443             :     case 52:
    1444             :     case 53:
    1445             :     case 54:
    1446             :     case 55:
    1447             :     case 56:
    1448             :     case 57:
    1449             :     case 58:
    1450             :     case 59:
    1451             :     case 60:
    1452             :     case 61:
    1453             :     case 62:
    1454             :     case 63:
    1455             :     case 64:
    1456             :     case 65:
    1457             :     case 66:
    1458             :     case 67:
    1459             :     case 68:
    1460             :     case 69:
    1461             :     case 70:
    1462             :     case 71:
    1463             :     case 72:
    1464             :     case 73:
    1465             :     case 74:
    1466             :     case 75:
    1467             :     case 76:
    1468             :     case 77:
    1469             :     case 78:
    1470             :     case 79:
    1471             :     case 80:
    1472             :     case 81:
    1473             :     case 82:
    1474             :     case 83:
    1475             :     case 84:
    1476             :     case 85:
    1477             :     case 86:
    1478             :     case 87:
    1479             :     case 88:
    1480             :     case 89:
    1481             :     case 90:
    1482             :     case 91:
    1483             :     case 92:
    1484             :     case 93:
    1485             :     case 94:
    1486             :     case 95:
    1487             :     case 96:
    1488             :     case 97:
    1489             :     case 98:
    1490             :     case 99:
    1491             :     case 100:
    1492             :     case 101:
    1493             :     case 102:
    1494             :     case 103:
    1495             :     case 104:
    1496             :     case 105:
    1497             :     case 106:
    1498             :     case 107:
    1499             :     case 108:
    1500             :     case 109:
    1501             :     case 110:
    1502             :     case 111:
    1503             :     case 112:
    1504             :     case 113:
    1505             :     case 114:
    1506             :     case 115:
    1507             :     case 116:
    1508             :     case 117:
    1509             :     case 118:
    1510             :     case 119:
    1511             :     case 120:
    1512             :     case 121:
    1513             :     case 122:
    1514             :     case 123:
    1515             :     case 124:
    1516             :     case 125:
    1517             :     case 126:
    1518             :     case 127:
    1519             :     case 128:
    1520             :     case 129:
    1521             :     case 130:
    1522             :     case 131:
    1523             :     case 132:
    1524             :     case 133:
    1525             :     case 134:
    1526             :     case 135:
    1527             :     case 136:
    1528             :     case 137:
    1529             :     case 138:
    1530             :     case 139:
    1531             :     case 140:
    1532             :     case 141:
    1533             :     case 142:
    1534             :     case 143:
    1535             :     case 144:
    1536             :     case 145:
    1537             :     case 146:
    1538             :     case 147:
    1539             :     case 148:
    1540             :     case 149:
    1541             :     case 150:
    1542             :     case 151:
    1543             :     case 152:
    1544             :     case 153:
    1545             :     case 154:
    1546             :     case 155:
    1547             :     case 156:
    1548             :     case 157:
    1549             :     case 158:
    1550             :     case 159:
    1551             :     case 160:
    1552             :     case 161:
    1553             :     case 162:
    1554             :     case 163:
    1555             :     case 164:
    1556             :     case 165:
    1557             :     case 166:
    1558             :     case 167:
    1559             :     case 168:
    1560             :     case 169:
    1561             :     case 170:
    1562             :     case 171:
    1563             :     case 172:
    1564             :     case 173:
    1565             :     case 174:
    1566             :     case 175:
    1567             :     case 176:
    1568             :     case 177:
    1569             :     case 178:
    1570             :     case 179:
    1571             :     case 180:
    1572             :     case 181:
    1573             :     case 182:
    1574             :     case 183:
    1575             :     case 184:
    1576             :     case 185:
    1577             :     case 186:
    1578             :     case 187:
    1579             :     case 188:
    1580             :     case 189:
    1581             :     case 190:
    1582             :     case 191:
    1583             :     case 192:
    1584             :     case 193:
    1585             :     case 194:
    1586             :     case 195:
    1587             :     case 196:
    1588             :     case 197:
    1589             :     case 198:
    1590             :     case 199:
    1591             :     case 200:
    1592             :     case 201:
    1593             :     case 202:
    1594             :     case 203:
    1595             :     case 204:
    1596             :     case 205:
    1597             :     case 206:
    1598             :     case 207:
    1599             :     case 208:
    1600             :     case 209:
    1601             :     case 210:
    1602             :     case 211:
    1603             :     case 212:
    1604             :     case 213:
    1605             :     case 214:
    1606             :     case 215:
    1607             :     case 216:
    1608             :     case 217:
    1609             :     case 218:
    1610             :     case 219:
    1611             :     case 220:
    1612             :     case 221:
    1613             :     case 222:
    1614             :     case 223:
    1615             :     case 224:
    1616             :     case 225:
    1617             :     case 226:
    1618             :     case 227:
    1619             :     case 228:
    1620             :     case 229:
    1621             :     case 230:
    1622             :     case 231:
    1623             :     case 232:
    1624             :     case 233:
    1625             :     case 234:
    1626             :     case 235:
    1627             :     case 236:
    1628             :     case 237:
    1629             :     case 238:
    1630             :     case 239:
    1631             :     case 240:
    1632             :     case 241:
    1633             :     case 242:
    1634             :     case 243:
    1635             :     case 244:
    1636             :     case 245:
    1637             :     case 246:
    1638             :     case 247:
    1639             :     case 248:
    1640             :     case 249:
    1641             :     case 250:
    1642             :     case 251:
    1643             :     case 252:
    1644             :     case 253:
    1645             :     case 254:
    1646             :     case 255:
    1647             : 
    1648             :       /* Parse nulterm socks4a_addr_hostname */
    1649             :       {
    1650          36 :         uint8_t *eos = (uint8_t*)memchr(ptr, 0, remaining);
    1651          36 :         size_t memlen;
    1652          36 :         if (eos == NULL)
    1653          33 :           goto truncated;
    1654           3 :         trunnel_assert(eos >= ptr);
    1655           3 :         trunnel_assert((size_t)(eos - ptr) < SIZE_MAX - 1);
    1656           3 :         memlen = ((size_t)(eos - ptr)) + 1;
    1657           3 :         if (!(obj->socks4a_addr_hostname = trunnel_malloc(memlen)))
    1658           0 :           goto fail;
    1659           3 :         memcpy(obj->socks4a_addr_hostname, ptr, memlen);
    1660           3 :         remaining -= memlen; ptr += memlen;
    1661             :       }
    1662           3 :       break;
    1663             : 
    1664             :     default:
    1665             :       break;
    1666             :   }
    1667           8 :   trunnel_assert(ptr + remaining == input + len_in);
    1668           8 :   return len_in - remaining;
    1669             : 
    1670             :  truncated:
    1671             :   return -2;
    1672             :  fail:
    1673          53 :   result = -1;
    1674             :   return result;
    1675             : }
    1676             : 
    1677             : ssize_t
    1678          53 : socks4_client_request_parse(socks4_client_request_t **output, const uint8_t *input, const size_t len_in)
    1679             : {
    1680          53 :   ssize_t result;
    1681          53 :   *output = socks4_client_request_new();
    1682          53 :   if (NULL == *output)
    1683             :     return -1;
    1684          53 :   result = socks4_client_request_parse_into(*output, input, len_in);
    1685          53 :   if (result < 0) {
    1686          45 :     socks4_client_request_free(*output);
    1687          45 :     *output = NULL;
    1688             :   }
    1689             :   return result;
    1690             : }
    1691             : socks4_server_reply_t *
    1692           0 : socks4_server_reply_new(void)
    1693             : {
    1694           0 :   socks4_server_reply_t *val = trunnel_calloc(1, sizeof(socks4_server_reply_t));
    1695           0 :   if (NULL == val)
    1696           0 :     return NULL;
    1697             :   return val;
    1698             : }
    1699             : 
    1700             : /** Release all storage held inside 'obj', but do not free 'obj'.
    1701             :  */
    1702             : static void
    1703             : socks4_server_reply_clear(socks4_server_reply_t *obj)
    1704             : {
    1705             :   (void) obj;
    1706             : }
    1707             : 
    1708             : void
    1709           0 : socks4_server_reply_free(socks4_server_reply_t *obj)
    1710             : {
    1711           0 :   if (obj == NULL)
    1712             :     return;
    1713           0 :   socks4_server_reply_clear(obj);
    1714           0 :   trunnel_memwipe(obj, sizeof(socks4_server_reply_t));
    1715           0 :   trunnel_free_(obj);
    1716             : }
    1717             : 
    1718             : uint8_t
    1719           0 : socks4_server_reply_get_version(const socks4_server_reply_t *inp)
    1720             : {
    1721           0 :   return inp->version;
    1722             : }
    1723             : int
    1724           0 : socks4_server_reply_set_version(socks4_server_reply_t *inp, uint8_t val)
    1725             : {
    1726           0 :   if (! ((val == 0 || val == 4))) {
    1727           0 :      TRUNNEL_SET_ERROR_CODE(inp);
    1728           0 :      return -1;
    1729             :   }
    1730           0 :   inp->version = val;
    1731           0 :   return 0;
    1732             : }
    1733             : uint8_t
    1734           0 : socks4_server_reply_get_status(const socks4_server_reply_t *inp)
    1735             : {
    1736           0 :   return inp->status;
    1737             : }
    1738             : int
    1739           0 : socks4_server_reply_set_status(socks4_server_reply_t *inp, uint8_t val)
    1740             : {
    1741           0 :   inp->status = val;
    1742           0 :   return 0;
    1743             : }
    1744             : uint16_t
    1745           0 : socks4_server_reply_get_port(const socks4_server_reply_t *inp)
    1746             : {
    1747           0 :   return inp->port;
    1748             : }
    1749             : int
    1750           0 : socks4_server_reply_set_port(socks4_server_reply_t *inp, uint16_t val)
    1751             : {
    1752           0 :   inp->port = val;
    1753           0 :   return 0;
    1754             : }
    1755             : uint32_t
    1756           0 : socks4_server_reply_get_addr(const socks4_server_reply_t *inp)
    1757             : {
    1758           0 :   return inp->addr;
    1759             : }
    1760             : int
    1761           0 : socks4_server_reply_set_addr(socks4_server_reply_t *inp, uint32_t val)
    1762             : {
    1763           0 :   inp->addr = val;
    1764           0 :   return 0;
    1765             : }
    1766             : const char *
    1767           0 : socks4_server_reply_check(const socks4_server_reply_t *obj)
    1768             : {
    1769           0 :   if (obj == NULL)
    1770             :     return "Object was NULL";
    1771           0 :   if (obj->trunnel_error_code_)
    1772             :     return "A set function failed on this object";
    1773           0 :   if (! (obj->version == 0 || obj->version == 4))
    1774           0 :     return "Integer out of bounds";
    1775             :   return NULL;
    1776             : }
    1777             : 
    1778             : ssize_t
    1779           0 : socks4_server_reply_encoded_len(const socks4_server_reply_t *obj)
    1780             : {
    1781           0 :   ssize_t result = 0;
    1782             : 
    1783           0 :   if (NULL != socks4_server_reply_check(obj))
    1784           0 :      return -1;
    1785             : 
    1786             : 
    1787             :   /* Length of u8 version IN [0, 4] */
    1788             :   result += 1;
    1789             : 
    1790             :   /* Length of u8 status */
    1791             :   result += 1;
    1792             : 
    1793             :   /* Length of u16 port */
    1794             :   result += 2;
    1795             : 
    1796             :   /* Length of u32 addr */
    1797           0 :   result += 4;
    1798             :   return result;
    1799             : }
    1800             : int
    1801           0 : socks4_server_reply_clear_errors(socks4_server_reply_t *obj)
    1802             : {
    1803           0 :   int r = obj->trunnel_error_code_;
    1804           0 :   obj->trunnel_error_code_ = 0;
    1805           0 :   return r;
    1806             : }
    1807             : ssize_t
    1808           0 : socks4_server_reply_encode(uint8_t *output, const size_t avail, const socks4_server_reply_t *obj)
    1809             : {
    1810           0 :   ssize_t result = 0;
    1811           0 :   size_t written = 0;
    1812           0 :   uint8_t *ptr = output;
    1813           0 :   const char *msg;
    1814             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
    1815             :   const ssize_t encoded_len = socks4_server_reply_encoded_len(obj);
    1816             : #endif
    1817             : 
    1818           0 :   if (NULL != (msg = socks4_server_reply_check(obj)))
    1819           0 :     goto check_failed;
    1820             : 
    1821             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
    1822             :   trunnel_assert(encoded_len >= 0);
    1823             : #endif
    1824             : 
    1825             :   /* Encode u8 version IN [0, 4] */
    1826           0 :   trunnel_assert(written <= avail);
    1827           0 :   if (avail - written < 1)
    1828           0 :     goto truncated;
    1829           0 :   trunnel_set_uint8(ptr, (obj->version));
    1830           0 :   written += 1; ptr += 1;
    1831             : 
    1832             :   /* Encode u8 status */
    1833           0 :   trunnel_assert(written <= avail);
    1834           0 :   if (avail - written < 1)
    1835           0 :     goto truncated;
    1836           0 :   trunnel_set_uint8(ptr, (obj->status));
    1837           0 :   written += 1; ptr += 1;
    1838             : 
    1839             :   /* Encode u16 port */
    1840           0 :   trunnel_assert(written <= avail);
    1841           0 :   if (avail - written < 2)
    1842           0 :     goto truncated;
    1843           0 :   trunnel_set_uint16(ptr, trunnel_htons(obj->port));
    1844           0 :   written += 2; ptr += 2;
    1845             : 
    1846             :   /* Encode u32 addr */
    1847           0 :   trunnel_assert(written <= avail);
    1848           0 :   if (avail - written < 4)
    1849           0 :     goto truncated;
    1850           0 :   trunnel_set_uint32(ptr, trunnel_htonl(obj->addr));
    1851           0 :   written += 4; ptr += 4;
    1852             : 
    1853             : 
    1854           0 :   trunnel_assert(ptr == output + written);
    1855             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
    1856             :   {
    1857             :     trunnel_assert(encoded_len >= 0);
    1858             :     trunnel_assert((size_t)encoded_len == written);
    1859             :   }
    1860             : 
    1861             : #endif
    1862             : 
    1863             :   return written;
    1864             : 
    1865           0 :  truncated:
    1866           0 :   result = -2;
    1867           0 :   goto fail;
    1868           0 :  check_failed:
    1869           0 :   (void)msg;
    1870           0 :   result = -1;
    1871           0 :   goto fail;
    1872             :  fail:
    1873             :   trunnel_assert(result < 0);
    1874             :   return result;
    1875             : }
    1876             : 
    1877             : /** As socks4_server_reply_parse(), but do not allocate the output
    1878             :  * object.
    1879             :  */
    1880             : static ssize_t
    1881           0 : socks4_server_reply_parse_into(socks4_server_reply_t *obj, const uint8_t *input, const size_t len_in)
    1882             : {
    1883           0 :   const uint8_t *ptr = input;
    1884           0 :   size_t remaining = len_in;
    1885           0 :   ssize_t result = 0;
    1886           0 :   (void)result;
    1887             : 
    1888             :   /* Parse u8 version IN [0, 4] */
    1889           0 :   CHECK_REMAINING(1, truncated);
    1890           0 :   obj->version = (trunnel_get_uint8(ptr));
    1891           0 :   remaining -= 1; ptr += 1;
    1892           0 :   if (! (obj->version == 0 || obj->version == 4))
    1893           0 :     goto fail;
    1894             : 
    1895             :   /* Parse u8 status */
    1896           0 :   CHECK_REMAINING(1, truncated);
    1897           0 :   obj->status = (trunnel_get_uint8(ptr));
    1898           0 :   remaining -= 1; ptr += 1;
    1899             : 
    1900             :   /* Parse u16 port */
    1901           0 :   CHECK_REMAINING(2, truncated);
    1902           0 :   obj->port = trunnel_ntohs(trunnel_get_uint16(ptr));
    1903           0 :   remaining -= 2; ptr += 2;
    1904             : 
    1905             :   /* Parse u32 addr */
    1906           0 :   CHECK_REMAINING(4, truncated);
    1907           0 :   obj->addr = trunnel_ntohl(trunnel_get_uint32(ptr));
    1908           0 :   remaining -= 4; ptr += 4;
    1909           0 :   trunnel_assert(ptr + remaining == input + len_in);
    1910             :   return len_in - remaining;
    1911             : 
    1912             :  truncated:
    1913             :   return -2;
    1914           0 :  fail:
    1915           0 :   result = -1;
    1916           0 :   return result;
    1917             : }
    1918             : 
    1919             : ssize_t
    1920           0 : socks4_server_reply_parse(socks4_server_reply_t **output, const uint8_t *input, const size_t len_in)
    1921             : {
    1922           0 :   ssize_t result;
    1923           0 :   *output = socks4_server_reply_new();
    1924           0 :   if (NULL == *output)
    1925             :     return -1;
    1926           0 :   result = socks4_server_reply_parse_into(*output, input, len_in);
    1927           0 :   if (result < 0) {
    1928           0 :     socks4_server_reply_free(*output);
    1929           0 :     *output = NULL;
    1930             :   }
    1931             :   return result;
    1932             : }
    1933             : socks5_client_userpass_auth_t *
    1934         520 : socks5_client_userpass_auth_new(void)
    1935             : {
    1936         520 :   socks5_client_userpass_auth_t *val = trunnel_calloc(1, sizeof(socks5_client_userpass_auth_t));
    1937         520 :   if (NULL == val)
    1938             :     return NULL;
    1939         520 :   val->version = 1;
    1940         520 :   return val;
    1941             : }
    1942             : 
    1943             : /** Release all storage held inside 'obj', but do not free 'obj'.
    1944             :  */
    1945             : static void
    1946         520 : socks5_client_userpass_auth_clear(socks5_client_userpass_auth_t *obj)
    1947             : {
    1948         520 :   (void) obj;
    1949         520 :   TRUNNEL_DYNARRAY_WIPE(&obj->username);
    1950         520 :   TRUNNEL_DYNARRAY_CLEAR(&obj->username);
    1951         520 :   TRUNNEL_DYNARRAY_WIPE(&obj->passwd);
    1952         520 :   TRUNNEL_DYNARRAY_CLEAR(&obj->passwd);
    1953         520 : }
    1954             : 
    1955             : void
    1956        1035 : socks5_client_userpass_auth_free(socks5_client_userpass_auth_t *obj)
    1957             : {
    1958        1035 :   if (obj == NULL)
    1959             :     return;
    1960         520 :   socks5_client_userpass_auth_clear(obj);
    1961         520 :   trunnel_memwipe(obj, sizeof(socks5_client_userpass_auth_t));
    1962         520 :   trunnel_free_(obj);
    1963             : }
    1964             : 
    1965             : uint8_t
    1966           0 : socks5_client_userpass_auth_get_version(const socks5_client_userpass_auth_t *inp)
    1967             : {
    1968           0 :   return inp->version;
    1969             : }
    1970             : int
    1971           0 : socks5_client_userpass_auth_set_version(socks5_client_userpass_auth_t *inp, uint8_t val)
    1972             : {
    1973           0 :   if (! ((val == 1))) {
    1974           0 :      TRUNNEL_SET_ERROR_CODE(inp);
    1975           0 :      return -1;
    1976             :   }
    1977           0 :   inp->version = val;
    1978           0 :   return 0;
    1979             : }
    1980             : uint8_t
    1981           5 : socks5_client_userpass_auth_get_username_len(const socks5_client_userpass_auth_t *inp)
    1982             : {
    1983           5 :   return inp->username_len;
    1984             : }
    1985             : int
    1986           0 : socks5_client_userpass_auth_set_username_len(socks5_client_userpass_auth_t *inp, uint8_t val)
    1987             : {
    1988           0 :   inp->username_len = val;
    1989           0 :   return 0;
    1990             : }
    1991             : size_t
    1992           0 : socks5_client_userpass_auth_getlen_username(const socks5_client_userpass_auth_t *inp)
    1993             : {
    1994           0 :   return TRUNNEL_DYNARRAY_LEN(&inp->username);
    1995             : }
    1996             : 
    1997             : char
    1998           0 : socks5_client_userpass_auth_get_username(socks5_client_userpass_auth_t *inp, size_t idx)
    1999             : {
    2000           0 :   return TRUNNEL_DYNARRAY_GET(&inp->username, idx);
    2001             : }
    2002             : 
    2003             : char
    2004           0 : socks5_client_userpass_auth_getconst_username(const socks5_client_userpass_auth_t *inp, size_t idx)
    2005             : {
    2006           0 :   return socks5_client_userpass_auth_get_username((socks5_client_userpass_auth_t*)inp, idx);
    2007             : }
    2008             : int
    2009           0 : socks5_client_userpass_auth_set_username(socks5_client_userpass_auth_t *inp, size_t idx, char elt)
    2010             : {
    2011           0 :   TRUNNEL_DYNARRAY_SET(&inp->username, idx, elt);
    2012           0 :   return 0;
    2013             : }
    2014             : int
    2015           0 : socks5_client_userpass_auth_add_username(socks5_client_userpass_auth_t *inp, char elt)
    2016             : {
    2017             : #if SIZE_MAX >= UINT8_MAX
    2018           0 :   if (inp->username.n_ == UINT8_MAX)
    2019           0 :     goto trunnel_alloc_failed;
    2020             : #endif
    2021           0 :   TRUNNEL_DYNARRAY_ADD(char, &inp->username, elt, {});
    2022           0 :   return 0;
    2023           0 :  trunnel_alloc_failed:
    2024           0 :   TRUNNEL_SET_ERROR_CODE(inp);
    2025           0 :   return -1;
    2026             : }
    2027             : 
    2028             : char *
    2029           5 : socks5_client_userpass_auth_getarray_username(socks5_client_userpass_auth_t *inp)
    2030             : {
    2031           5 :   return inp->username.elts_;
    2032             : }
    2033             : const char  *
    2034           5 : socks5_client_userpass_auth_getconstarray_username(const socks5_client_userpass_auth_t *inp)
    2035             : {
    2036           5 :   return (const char  *)socks5_client_userpass_auth_getarray_username((socks5_client_userpass_auth_t*)inp);
    2037             : }
    2038             : int
    2039           0 : socks5_client_userpass_auth_setlen_username(socks5_client_userpass_auth_t *inp, size_t newlen)
    2040             : {
    2041             : #if UINT8_MAX < SIZE_MAX
    2042           0 :   if (newlen > UINT8_MAX)
    2043           0 :     goto trunnel_alloc_failed;
    2044             : #endif
    2045           0 :   return trunnel_string_setlen(&inp->username, newlen,
    2046             :             &inp->trunnel_error_code_);
    2047           0 :  trunnel_alloc_failed:
    2048           0 :   TRUNNEL_SET_ERROR_CODE(inp);
    2049           0 :   return -1;
    2050             : }
    2051             : const char *
    2052           0 : socks5_client_userpass_auth_getstr_username(socks5_client_userpass_auth_t *inp)
    2053             : {
    2054           0 :   return trunnel_string_getstr(&inp->username);
    2055             : }
    2056             : int
    2057         264 : socks5_client_userpass_auth_setstr0_username(socks5_client_userpass_auth_t *inp, const char *val, size_t len)
    2058             : {
    2059             : #if UINT8_MAX < SIZE_MAX
    2060         264 :   if (len > UINT8_MAX) {
    2061           0 :     TRUNNEL_SET_ERROR_CODE(inp);
    2062           0 :     return -1;
    2063             :   }
    2064             : #endif
    2065         264 :   return trunnel_string_setstr0(&inp->username, val, len, &inp->trunnel_error_code_);
    2066             : }
    2067             : int
    2068           0 : socks5_client_userpass_auth_setstr_username(socks5_client_userpass_auth_t *inp, const char *val)
    2069             : {
    2070           0 :   return socks5_client_userpass_auth_setstr0_username(inp, val, strlen(val));
    2071             : }
    2072             : uint8_t
    2073           5 : socks5_client_userpass_auth_get_passwd_len(const socks5_client_userpass_auth_t *inp)
    2074             : {
    2075           5 :   return inp->passwd_len;
    2076             : }
    2077             : int
    2078           0 : socks5_client_userpass_auth_set_passwd_len(socks5_client_userpass_auth_t *inp, uint8_t val)
    2079             : {
    2080           0 :   inp->passwd_len = val;
    2081           0 :   return 0;
    2082             : }
    2083             : size_t
    2084           0 : socks5_client_userpass_auth_getlen_passwd(const socks5_client_userpass_auth_t *inp)
    2085             : {
    2086           0 :   return TRUNNEL_DYNARRAY_LEN(&inp->passwd);
    2087             : }
    2088             : 
    2089             : char
    2090           0 : socks5_client_userpass_auth_get_passwd(socks5_client_userpass_auth_t *inp, size_t idx)
    2091             : {
    2092           0 :   return TRUNNEL_DYNARRAY_GET(&inp->passwd, idx);
    2093             : }
    2094             : 
    2095             : char
    2096           0 : socks5_client_userpass_auth_getconst_passwd(const socks5_client_userpass_auth_t *inp, size_t idx)
    2097             : {
    2098           0 :   return socks5_client_userpass_auth_get_passwd((socks5_client_userpass_auth_t*)inp, idx);
    2099             : }
    2100             : int
    2101           0 : socks5_client_userpass_auth_set_passwd(socks5_client_userpass_auth_t *inp, size_t idx, char elt)
    2102             : {
    2103           0 :   TRUNNEL_DYNARRAY_SET(&inp->passwd, idx, elt);
    2104           0 :   return 0;
    2105             : }
    2106             : int
    2107           0 : socks5_client_userpass_auth_add_passwd(socks5_client_userpass_auth_t *inp, char elt)
    2108             : {
    2109             : #if SIZE_MAX >= UINT8_MAX
    2110           0 :   if (inp->passwd.n_ == UINT8_MAX)
    2111           0 :     goto trunnel_alloc_failed;
    2112             : #endif
    2113           0 :   TRUNNEL_DYNARRAY_ADD(char, &inp->passwd, elt, {});
    2114           0 :   return 0;
    2115           0 :  trunnel_alloc_failed:
    2116           0 :   TRUNNEL_SET_ERROR_CODE(inp);
    2117           0 :   return -1;
    2118             : }
    2119             : 
    2120             : char *
    2121           5 : socks5_client_userpass_auth_getarray_passwd(socks5_client_userpass_auth_t *inp)
    2122             : {
    2123           5 :   return inp->passwd.elts_;
    2124             : }
    2125             : const char  *
    2126           5 : socks5_client_userpass_auth_getconstarray_passwd(const socks5_client_userpass_auth_t *inp)
    2127             : {
    2128           5 :   return (const char  *)socks5_client_userpass_auth_getarray_passwd((socks5_client_userpass_auth_t*)inp);
    2129             : }
    2130             : int
    2131           0 : socks5_client_userpass_auth_setlen_passwd(socks5_client_userpass_auth_t *inp, size_t newlen)
    2132             : {
    2133             : #if UINT8_MAX < SIZE_MAX
    2134           0 :   if (newlen > UINT8_MAX)
    2135           0 :     goto trunnel_alloc_failed;
    2136             : #endif
    2137           0 :   return trunnel_string_setlen(&inp->passwd, newlen,
    2138             :             &inp->trunnel_error_code_);
    2139           0 :  trunnel_alloc_failed:
    2140           0 :   TRUNNEL_SET_ERROR_CODE(inp);
    2141           0 :   return -1;
    2142             : }
    2143             : const char *
    2144           0 : socks5_client_userpass_auth_getstr_passwd(socks5_client_userpass_auth_t *inp)
    2145             : {
    2146           0 :   return trunnel_string_getstr(&inp->passwd);
    2147             : }
    2148             : int
    2149           5 : socks5_client_userpass_auth_setstr0_passwd(socks5_client_userpass_auth_t *inp, const char *val, size_t len)
    2150             : {
    2151             : #if UINT8_MAX < SIZE_MAX
    2152           5 :   if (len > UINT8_MAX) {
    2153           0 :     TRUNNEL_SET_ERROR_CODE(inp);
    2154           0 :     return -1;
    2155             :   }
    2156             : #endif
    2157           5 :   return trunnel_string_setstr0(&inp->passwd, val, len, &inp->trunnel_error_code_);
    2158             : }
    2159             : int
    2160           0 : socks5_client_userpass_auth_setstr_passwd(socks5_client_userpass_auth_t *inp, const char *val)
    2161             : {
    2162           0 :   return socks5_client_userpass_auth_setstr0_passwd(inp, val, strlen(val));
    2163             : }
    2164             : const char *
    2165           0 : socks5_client_userpass_auth_check(const socks5_client_userpass_auth_t *obj)
    2166             : {
    2167           0 :   if (obj == NULL)
    2168             :     return "Object was NULL";
    2169           0 :   if (obj->trunnel_error_code_)
    2170             :     return "A set function failed on this object";
    2171           0 :   if (! (obj->version == 1))
    2172             :     return "Integer out of bounds";
    2173           0 :   if (TRUNNEL_DYNARRAY_LEN(&obj->username) != obj->username_len)
    2174             :     return "Length mismatch for username";
    2175           0 :   if (TRUNNEL_DYNARRAY_LEN(&obj->passwd) != obj->passwd_len)
    2176           0 :     return "Length mismatch for passwd";
    2177             :   return NULL;
    2178             : }
    2179             : 
    2180             : ssize_t
    2181           0 : socks5_client_userpass_auth_encoded_len(const socks5_client_userpass_auth_t *obj)
    2182             : {
    2183           0 :   ssize_t result = 0;
    2184             : 
    2185           0 :   if (NULL != socks5_client_userpass_auth_check(obj))
    2186             :      return -1;
    2187             : 
    2188             : 
    2189             :   /* Length of u8 version IN [1] */
    2190           0 :   result += 1;
    2191             : 
    2192             :   /* Length of u8 username_len */
    2193           0 :   result += 1;
    2194             : 
    2195             :   /* Length of char username[username_len] */
    2196           0 :   result += TRUNNEL_DYNARRAY_LEN(&obj->username);
    2197             : 
    2198             :   /* Length of u8 passwd_len */
    2199           0 :   result += 1;
    2200             : 
    2201             :   /* Length of char passwd[passwd_len] */
    2202           0 :   result += TRUNNEL_DYNARRAY_LEN(&obj->passwd);
    2203           0 :   return result;
    2204             : }
    2205             : int
    2206           0 : socks5_client_userpass_auth_clear_errors(socks5_client_userpass_auth_t *obj)
    2207             : {
    2208           0 :   int r = obj->trunnel_error_code_;
    2209           0 :   obj->trunnel_error_code_ = 0;
    2210           0 :   return r;
    2211             : }
    2212             : ssize_t
    2213           0 : socks5_client_userpass_auth_encode(uint8_t *output, const size_t avail, const socks5_client_userpass_auth_t *obj)
    2214             : {
    2215           0 :   ssize_t result = 0;
    2216           0 :   size_t written = 0;
    2217           0 :   uint8_t *ptr = output;
    2218           0 :   const char *msg;
    2219             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
    2220             :   const ssize_t encoded_len = socks5_client_userpass_auth_encoded_len(obj);
    2221             : #endif
    2222             : 
    2223           0 :   if (NULL != (msg = socks5_client_userpass_auth_check(obj)))
    2224           0 :     goto check_failed;
    2225             : 
    2226             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
    2227             :   trunnel_assert(encoded_len >= 0);
    2228             : #endif
    2229             : 
    2230             :   /* Encode u8 version IN [1] */
    2231           0 :   trunnel_assert(written <= avail);
    2232           0 :   if (avail - written < 1)
    2233           0 :     goto truncated;
    2234           0 :   trunnel_set_uint8(ptr, (obj->version));
    2235           0 :   written += 1; ptr += 1;
    2236             : 
    2237             :   /* Encode u8 username_len */
    2238           0 :   trunnel_assert(written <= avail);
    2239           0 :   if (avail - written < 1)
    2240           0 :     goto truncated;
    2241           0 :   trunnel_set_uint8(ptr, (obj->username_len));
    2242           0 :   written += 1; ptr += 1;
    2243             : 
    2244             :   /* Encode char username[username_len] */
    2245             :   {
    2246           0 :     size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->username);
    2247           0 :     trunnel_assert(obj->username_len == elt_len);
    2248           0 :     trunnel_assert(written <= avail);
    2249           0 :     if (avail - written < elt_len)
    2250           0 :       goto truncated;
    2251           0 :     if (elt_len)
    2252           0 :       memcpy(ptr, obj->username.elts_, elt_len);
    2253           0 :     written += elt_len; ptr += elt_len;
    2254             :   }
    2255             : 
    2256             :   /* Encode u8 passwd_len */
    2257           0 :   trunnel_assert(written <= avail);
    2258           0 :   if (avail - written < 1)
    2259           0 :     goto truncated;
    2260           0 :   trunnel_set_uint8(ptr, (obj->passwd_len));
    2261           0 :   written += 1; ptr += 1;
    2262             : 
    2263             :   /* Encode char passwd[passwd_len] */
    2264             :   {
    2265           0 :     size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->passwd);
    2266           0 :     trunnel_assert(obj->passwd_len == elt_len);
    2267           0 :     trunnel_assert(written <= avail);
    2268           0 :     if (avail - written < elt_len)
    2269           0 :       goto truncated;
    2270           0 :     if (elt_len)
    2271           0 :       memcpy(ptr, obj->passwd.elts_, elt_len);
    2272           0 :     written += elt_len; ptr += elt_len;
    2273             :   }
    2274             : 
    2275             : 
    2276           0 :   trunnel_assert(ptr == output + written);
    2277             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
    2278             :   {
    2279             :     trunnel_assert(encoded_len >= 0);
    2280             :     trunnel_assert((size_t)encoded_len == written);
    2281             :   }
    2282             : 
    2283             : #endif
    2284             : 
    2285           0 :   return written;
    2286             : 
    2287           0 :  truncated:
    2288           0 :   result = -2;
    2289           0 :   goto fail;
    2290           0 :  check_failed:
    2291           0 :   (void)msg;
    2292           0 :   result = -1;
    2293           0 :   goto fail;
    2294             :  fail:
    2295             :   trunnel_assert(result < 0);
    2296             :   return result;
    2297             : }
    2298             : 
    2299             : /** As socks5_client_userpass_auth_parse(), but do not allocate the
    2300             :  * output object.
    2301             :  */
    2302             : static ssize_t
    2303         520 : socks5_client_userpass_auth_parse_into(socks5_client_userpass_auth_t *obj, const uint8_t *input, const size_t len_in)
    2304             : {
    2305         520 :   const uint8_t *ptr = input;
    2306         520 :   size_t remaining = len_in;
    2307         520 :   ssize_t result = 0;
    2308         520 :   (void)result;
    2309             : 
    2310             :   /* Parse u8 version IN [1] */
    2311         520 :   CHECK_REMAINING(1, truncated);
    2312         520 :   obj->version = (trunnel_get_uint8(ptr));
    2313         520 :   remaining -= 1; ptr += 1;
    2314         520 :   if (! (obj->version == 1))
    2315           0 :     goto fail;
    2316             : 
    2317             :   /* Parse u8 username_len */
    2318         520 :   CHECK_REMAINING(1, truncated);
    2319         520 :   obj->username_len = (trunnel_get_uint8(ptr));
    2320         520 :   remaining -= 1; ptr += 1;
    2321             : 
    2322             :   /* Parse char username[username_len] */
    2323         520 :   CHECK_REMAINING(obj->username_len, truncated);
    2324         264 :   if (socks5_client_userpass_auth_setstr0_username(obj, (const char*)ptr, obj->username_len))
    2325           0 :     goto fail;
    2326         264 :   ptr += obj->username_len; remaining -= obj->username_len;
    2327             : 
    2328             :   /* Parse u8 passwd_len */
    2329         264 :   CHECK_REMAINING(1, truncated);
    2330         261 :   obj->passwd_len = (trunnel_get_uint8(ptr));
    2331         261 :   remaining -= 1; ptr += 1;
    2332             : 
    2333             :   /* Parse char passwd[passwd_len] */
    2334         261 :   CHECK_REMAINING(obj->passwd_len, truncated);
    2335           5 :   if (socks5_client_userpass_auth_setstr0_passwd(obj, (const char*)ptr, obj->passwd_len))
    2336           0 :     goto fail;
    2337           5 :   ptr += obj->passwd_len; remaining -= obj->passwd_len;
    2338           5 :   trunnel_assert(ptr + remaining == input + len_in);
    2339           5 :   return len_in - remaining;
    2340             : 
    2341             :  truncated:
    2342             :   return -2;
    2343             :  fail:
    2344         520 :   result = -1;
    2345             :   return result;
    2346             : }
    2347             : 
    2348             : ssize_t
    2349         520 : socks5_client_userpass_auth_parse(socks5_client_userpass_auth_t **output, const uint8_t *input, const size_t len_in)
    2350             : {
    2351         520 :   ssize_t result;
    2352         520 :   *output = socks5_client_userpass_auth_new();
    2353         520 :   if (NULL == *output)
    2354             :     return -1;
    2355         520 :   result = socks5_client_userpass_auth_parse_into(*output, input, len_in);
    2356         520 :   if (result < 0) {
    2357         515 :     socks5_client_userpass_auth_free(*output);
    2358         515 :     *output = NULL;
    2359             :   }
    2360             :   return result;
    2361             : }
    2362             : socks5_client_version_t *
    2363         872 : socks5_client_version_new(void)
    2364             : {
    2365         872 :   socks5_client_version_t *val = trunnel_calloc(1, sizeof(socks5_client_version_t));
    2366         872 :   if (NULL == val)
    2367             :     return NULL;
    2368         872 :   val->version = 5;
    2369         872 :   return val;
    2370             : }
    2371             : 
    2372             : /** Release all storage held inside 'obj', but do not free 'obj'.
    2373             :  */
    2374             : static void
    2375         872 : socks5_client_version_clear(socks5_client_version_t *obj)
    2376             : {
    2377         872 :   (void) obj;
    2378         872 :   TRUNNEL_DYNARRAY_WIPE(&obj->methods);
    2379         872 :   TRUNNEL_DYNARRAY_CLEAR(&obj->methods);
    2380         872 : }
    2381             : 
    2382             : void
    2383         875 : socks5_client_version_free(socks5_client_version_t *obj)
    2384             : {
    2385         875 :   if (obj == NULL)
    2386             :     return;
    2387         872 :   socks5_client_version_clear(obj);
    2388         872 :   trunnel_memwipe(obj, sizeof(socks5_client_version_t));
    2389         872 :   trunnel_free_(obj);
    2390             : }
    2391             : 
    2392             : uint8_t
    2393           0 : socks5_client_version_get_version(const socks5_client_version_t *inp)
    2394             : {
    2395           0 :   return inp->version;
    2396             : }
    2397             : int
    2398           0 : socks5_client_version_set_version(socks5_client_version_t *inp, uint8_t val)
    2399             : {
    2400           0 :   if (! ((val == 5))) {
    2401           0 :      TRUNNEL_SET_ERROR_CODE(inp);
    2402           0 :      return -1;
    2403             :   }
    2404           0 :   inp->version = val;
    2405           0 :   return 0;
    2406             : }
    2407             : uint8_t
    2408         869 : socks5_client_version_get_n_methods(const socks5_client_version_t *inp)
    2409             : {
    2410         869 :   return inp->n_methods;
    2411             : }
    2412             : int
    2413           0 : socks5_client_version_set_n_methods(socks5_client_version_t *inp, uint8_t val)
    2414             : {
    2415           0 :   inp->n_methods = val;
    2416           0 :   return 0;
    2417             : }
    2418             : size_t
    2419           0 : socks5_client_version_getlen_methods(const socks5_client_version_t *inp)
    2420             : {
    2421           0 :   return TRUNNEL_DYNARRAY_LEN(&inp->methods);
    2422             : }
    2423             : 
    2424             : uint8_t
    2425         873 : socks5_client_version_get_methods(socks5_client_version_t *inp, size_t idx)
    2426             : {
    2427         873 :   return TRUNNEL_DYNARRAY_GET(&inp->methods, idx);
    2428             : }
    2429             : 
    2430             : uint8_t
    2431           0 : socks5_client_version_getconst_methods(const socks5_client_version_t *inp, size_t idx)
    2432             : {
    2433           0 :   return socks5_client_version_get_methods((socks5_client_version_t*)inp, idx);
    2434             : }
    2435             : int
    2436           0 : socks5_client_version_set_methods(socks5_client_version_t *inp, size_t idx, uint8_t elt)
    2437             : {
    2438           0 :   TRUNNEL_DYNARRAY_SET(&inp->methods, idx, elt);
    2439           0 :   return 0;
    2440             : }
    2441             : int
    2442           0 : socks5_client_version_add_methods(socks5_client_version_t *inp, uint8_t elt)
    2443             : {
    2444             : #if SIZE_MAX >= UINT8_MAX
    2445           0 :   if (inp->methods.n_ == UINT8_MAX)
    2446           0 :     goto trunnel_alloc_failed;
    2447             : #endif
    2448           0 :   TRUNNEL_DYNARRAY_ADD(uint8_t, &inp->methods, elt, {});
    2449           0 :   return 0;
    2450           0 :  trunnel_alloc_failed:
    2451           0 :   TRUNNEL_SET_ERROR_CODE(inp);
    2452           0 :   return -1;
    2453             : }
    2454             : 
    2455             : uint8_t *
    2456           0 : socks5_client_version_getarray_methods(socks5_client_version_t *inp)
    2457             : {
    2458           0 :   return inp->methods.elts_;
    2459             : }
    2460             : const uint8_t  *
    2461           0 : socks5_client_version_getconstarray_methods(const socks5_client_version_t *inp)
    2462             : {
    2463           0 :   return (const uint8_t  *)socks5_client_version_getarray_methods((socks5_client_version_t*)inp);
    2464             : }
    2465             : int
    2466           0 : socks5_client_version_setlen_methods(socks5_client_version_t *inp, size_t newlen)
    2467             : {
    2468           0 :   uint8_t *newptr;
    2469             : #if UINT8_MAX < SIZE_MAX
    2470           0 :   if (newlen > UINT8_MAX)
    2471           0 :     goto trunnel_alloc_failed;
    2472             : #endif
    2473           0 :   newptr = trunnel_dynarray_setlen(&inp->methods.allocated_,
    2474           0 :                  &inp->methods.n_, inp->methods.elts_, newlen,
    2475             :                  sizeof(inp->methods.elts_[0]), (trunnel_free_fn_t) NULL,
    2476             :                  &inp->trunnel_error_code_);
    2477           0 :   if (newlen != 0 && newptr == NULL)
    2478           0 :     goto trunnel_alloc_failed;
    2479           0 :   inp->methods.elts_ = newptr;
    2480           0 :   return 0;
    2481           0 :  trunnel_alloc_failed:
    2482           0 :   TRUNNEL_SET_ERROR_CODE(inp);
    2483           0 :   return -1;
    2484             : }
    2485             : const char *
    2486           0 : socks5_client_version_check(const socks5_client_version_t *obj)
    2487             : {
    2488           0 :   if (obj == NULL)
    2489             :     return "Object was NULL";
    2490           0 :   if (obj->trunnel_error_code_)
    2491             :     return "A set function failed on this object";
    2492           0 :   if (! (obj->version == 5))
    2493             :     return "Integer out of bounds";
    2494           0 :   if (TRUNNEL_DYNARRAY_LEN(&obj->methods) != obj->n_methods)
    2495           0 :     return "Length mismatch for methods";
    2496             :   return NULL;
    2497             : }
    2498             : 
    2499             : ssize_t
    2500           0 : socks5_client_version_encoded_len(const socks5_client_version_t *obj)
    2501             : {
    2502           0 :   ssize_t result = 0;
    2503             : 
    2504           0 :   if (NULL != socks5_client_version_check(obj))
    2505             :      return -1;
    2506             : 
    2507             : 
    2508             :   /* Length of u8 version IN [5] */
    2509           0 :   result += 1;
    2510             : 
    2511             :   /* Length of u8 n_methods */
    2512           0 :   result += 1;
    2513             : 
    2514             :   /* Length of u8 methods[n_methods] */
    2515           0 :   result += TRUNNEL_DYNARRAY_LEN(&obj->methods);
    2516           0 :   return result;
    2517             : }
    2518             : int
    2519           0 : socks5_client_version_clear_errors(socks5_client_version_t *obj)
    2520             : {
    2521           0 :   int r = obj->trunnel_error_code_;
    2522           0 :   obj->trunnel_error_code_ = 0;
    2523           0 :   return r;
    2524             : }
    2525             : ssize_t
    2526           0 : socks5_client_version_encode(uint8_t *output, const size_t avail, const socks5_client_version_t *obj)
    2527             : {
    2528           0 :   ssize_t result = 0;
    2529           0 :   size_t written = 0;
    2530           0 :   uint8_t *ptr = output;
    2531           0 :   const char *msg;
    2532             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
    2533             :   const ssize_t encoded_len = socks5_client_version_encoded_len(obj);
    2534             : #endif
    2535             : 
    2536           0 :   if (NULL != (msg = socks5_client_version_check(obj)))
    2537           0 :     goto check_failed;
    2538             : 
    2539             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
    2540             :   trunnel_assert(encoded_len >= 0);
    2541             : #endif
    2542             : 
    2543             :   /* Encode u8 version IN [5] */
    2544           0 :   trunnel_assert(written <= avail);
    2545           0 :   if (avail - written < 1)
    2546           0 :     goto truncated;
    2547           0 :   trunnel_set_uint8(ptr, (obj->version));
    2548           0 :   written += 1; ptr += 1;
    2549             : 
    2550             :   /* Encode u8 n_methods */
    2551           0 :   trunnel_assert(written <= avail);
    2552           0 :   if (avail - written < 1)
    2553           0 :     goto truncated;
    2554           0 :   trunnel_set_uint8(ptr, (obj->n_methods));
    2555           0 :   written += 1; ptr += 1;
    2556             : 
    2557             :   /* Encode u8 methods[n_methods] */
    2558             :   {
    2559           0 :     size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->methods);
    2560           0 :     trunnel_assert(obj->n_methods == elt_len);
    2561           0 :     trunnel_assert(written <= avail);
    2562           0 :     if (avail - written < elt_len)
    2563           0 :       goto truncated;
    2564           0 :     if (elt_len)
    2565           0 :       memcpy(ptr, obj->methods.elts_, elt_len);
    2566           0 :     written += elt_len; ptr += elt_len;
    2567             :   }
    2568             : 
    2569             : 
    2570           0 :   trunnel_assert(ptr == output + written);
    2571             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
    2572             :   {
    2573             :     trunnel_assert(encoded_len >= 0);
    2574             :     trunnel_assert((size_t)encoded_len == written);
    2575             :   }
    2576             : 
    2577             : #endif
    2578             : 
    2579           0 :   return written;
    2580             : 
    2581           0 :  truncated:
    2582           0 :   result = -2;
    2583           0 :   goto fail;
    2584           0 :  check_failed:
    2585           0 :   (void)msg;
    2586           0 :   result = -1;
    2587           0 :   goto fail;
    2588             :  fail:
    2589             :   trunnel_assert(result < 0);
    2590             :   return result;
    2591             : }
    2592             : 
    2593             : /** As socks5_client_version_parse(), but do not allocate the output
    2594             :  * object.
    2595             :  */
    2596             : static ssize_t
    2597         872 : socks5_client_version_parse_into(socks5_client_version_t *obj, const uint8_t *input, const size_t len_in)
    2598             : {
    2599         872 :   const uint8_t *ptr = input;
    2600         872 :   size_t remaining = len_in;
    2601         872 :   ssize_t result = 0;
    2602         872 :   (void)result;
    2603             : 
    2604             :   /* Parse u8 version IN [5] */
    2605         872 :   CHECK_REMAINING(1, truncated);
    2606         872 :   obj->version = (trunnel_get_uint8(ptr));
    2607         872 :   remaining -= 1; ptr += 1;
    2608         872 :   if (! (obj->version == 5))
    2609           0 :     goto fail;
    2610             : 
    2611             :   /* Parse u8 n_methods */
    2612         872 :   CHECK_REMAINING(1, truncated);
    2613         872 :   obj->n_methods = (trunnel_get_uint8(ptr));
    2614         872 :   remaining -= 1; ptr += 1;
    2615             : 
    2616             :   /* Parse u8 methods[n_methods] */
    2617         872 :   CHECK_REMAINING(obj->n_methods, truncated);
    2618         869 :   TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->methods, obj->n_methods, {});
    2619         869 :   obj->methods.n_ = obj->n_methods;
    2620         869 :   if (obj->n_methods)
    2621         869 :     memcpy(obj->methods.elts_, ptr, obj->n_methods);
    2622         869 :   ptr += obj->n_methods; remaining -= obj->n_methods;
    2623         869 :   trunnel_assert(ptr + remaining == input + len_in);
    2624         869 :   return len_in - remaining;
    2625             : 
    2626             :  truncated:
    2627             :   return -2;
    2628           0 :  trunnel_alloc_failed:
    2629           0 :   return -1;
    2630           0 :  fail:
    2631           0 :   result = -1;
    2632           0 :   return result;
    2633             : }
    2634             : 
    2635             : ssize_t
    2636         872 : socks5_client_version_parse(socks5_client_version_t **output, const uint8_t *input, const size_t len_in)
    2637             : {
    2638         872 :   ssize_t result;
    2639         872 :   *output = socks5_client_version_new();
    2640         872 :   if (NULL == *output)
    2641             :     return -1;
    2642         872 :   result = socks5_client_version_parse_into(*output, input, len_in);
    2643         872 :   if (result < 0) {
    2644           3 :     socks5_client_version_free(*output);
    2645           3 :     *output = NULL;
    2646             :   }
    2647             :   return result;
    2648             : }
    2649             : socks5_server_method_t *
    2650         869 : socks5_server_method_new(void)
    2651             : {
    2652         869 :   socks5_server_method_t *val = trunnel_calloc(1, sizeof(socks5_server_method_t));
    2653         869 :   if (NULL == val)
    2654             :     return NULL;
    2655         869 :   val->version = 5;
    2656         869 :   return val;
    2657             : }
    2658             : 
    2659             : /** Release all storage held inside 'obj', but do not free 'obj'.
    2660             :  */
    2661             : static void
    2662             : socks5_server_method_clear(socks5_server_method_t *obj)
    2663             : {
    2664             :   (void) obj;
    2665             : }
    2666             : 
    2667             : void
    2668         869 : socks5_server_method_free(socks5_server_method_t *obj)
    2669             : {
    2670         869 :   if (obj == NULL)
    2671             :     return;
    2672         869 :   socks5_server_method_clear(obj);
    2673         869 :   trunnel_memwipe(obj, sizeof(socks5_server_method_t));
    2674         869 :   trunnel_free_(obj);
    2675             : }
    2676             : 
    2677             : uint8_t
    2678           0 : socks5_server_method_get_version(const socks5_server_method_t *inp)
    2679             : {
    2680           0 :   return inp->version;
    2681             : }
    2682             : int
    2683         869 : socks5_server_method_set_version(socks5_server_method_t *inp, uint8_t val)
    2684             : {
    2685         869 :   if (! ((val == 5))) {
    2686           0 :      TRUNNEL_SET_ERROR_CODE(inp);
    2687           0 :      return -1;
    2688             :   }
    2689         869 :   inp->version = val;
    2690         869 :   return 0;
    2691             : }
    2692             : uint8_t
    2693           0 : socks5_server_method_get_method(const socks5_server_method_t *inp)
    2694             : {
    2695           0 :   return inp->method;
    2696             : }
    2697             : int
    2698         869 : socks5_server_method_set_method(socks5_server_method_t *inp, uint8_t val)
    2699             : {
    2700         869 :   inp->method = val;
    2701         869 :   return 0;
    2702             : }
    2703             : const char *
    2704        1738 : socks5_server_method_check(const socks5_server_method_t *obj)
    2705             : {
    2706        1738 :   if (obj == NULL)
    2707             :     return "Object was NULL";
    2708        1738 :   if (obj->trunnel_error_code_)
    2709             :     return "A set function failed on this object";
    2710        1738 :   if (! (obj->version == 5))
    2711           0 :     return "Integer out of bounds";
    2712             :   return NULL;
    2713             : }
    2714             : 
    2715             : ssize_t
    2716           0 : socks5_server_method_encoded_len(const socks5_server_method_t *obj)
    2717             : {
    2718           0 :   ssize_t result = 0;
    2719             : 
    2720           0 :   if (NULL != socks5_server_method_check(obj))
    2721           0 :      return -1;
    2722             : 
    2723             : 
    2724             :   /* Length of u8 version IN [5] */
    2725             :   result += 1;
    2726             : 
    2727             :   /* Length of u8 method */
    2728           0 :   result += 1;
    2729             :   return result;
    2730             : }
    2731             : int
    2732           0 : socks5_server_method_clear_errors(socks5_server_method_t *obj)
    2733             : {
    2734           0 :   int r = obj->trunnel_error_code_;
    2735           0 :   obj->trunnel_error_code_ = 0;
    2736           0 :   return r;
    2737             : }
    2738             : ssize_t
    2739         869 : socks5_server_method_encode(uint8_t *output, const size_t avail, const socks5_server_method_t *obj)
    2740             : {
    2741         869 :   ssize_t result = 0;
    2742         869 :   size_t written = 0;
    2743         869 :   uint8_t *ptr = output;
    2744         869 :   const char *msg;
    2745             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
    2746             :   const ssize_t encoded_len = socks5_server_method_encoded_len(obj);
    2747             : #endif
    2748             : 
    2749         869 :   if (NULL != (msg = socks5_server_method_check(obj)))
    2750           0 :     goto check_failed;
    2751             : 
    2752             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
    2753             :   trunnel_assert(encoded_len >= 0);
    2754             : #endif
    2755             : 
    2756             :   /* Encode u8 version IN [5] */
    2757         869 :   trunnel_assert(written <= avail);
    2758         869 :   if (avail - written < 1)
    2759           0 :     goto truncated;
    2760         869 :   trunnel_set_uint8(ptr, (obj->version));
    2761         869 :   written += 1; ptr += 1;
    2762             : 
    2763             :   /* Encode u8 method */
    2764         869 :   trunnel_assert(written <= avail);
    2765         869 :   if (avail - written < 1)
    2766           0 :     goto truncated;
    2767         869 :   trunnel_set_uint8(ptr, (obj->method));
    2768         869 :   written += 1; ptr += 1;
    2769             : 
    2770             : 
    2771         869 :   trunnel_assert(ptr == output + written);
    2772             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
    2773             :   {
    2774             :     trunnel_assert(encoded_len >= 0);
    2775             :     trunnel_assert((size_t)encoded_len == written);
    2776             :   }
    2777             : 
    2778             : #endif
    2779             : 
    2780             :   return written;
    2781             : 
    2782           0 :  truncated:
    2783           0 :   result = -2;
    2784           0 :   goto fail;
    2785           0 :  check_failed:
    2786           0 :   (void)msg;
    2787           0 :   result = -1;
    2788           0 :   goto fail;
    2789             :  fail:
    2790             :   trunnel_assert(result < 0);
    2791             :   return result;
    2792             : }
    2793             : 
    2794             : /** As socks5_server_method_parse(), but do not allocate the output
    2795             :  * object.
    2796             :  */
    2797             : static ssize_t
    2798           0 : socks5_server_method_parse_into(socks5_server_method_t *obj, const uint8_t *input, const size_t len_in)
    2799             : {
    2800           0 :   const uint8_t *ptr = input;
    2801           0 :   size_t remaining = len_in;
    2802           0 :   ssize_t result = 0;
    2803           0 :   (void)result;
    2804             : 
    2805             :   /* Parse u8 version IN [5] */
    2806           0 :   CHECK_REMAINING(1, truncated);
    2807           0 :   obj->version = (trunnel_get_uint8(ptr));
    2808           0 :   remaining -= 1; ptr += 1;
    2809           0 :   if (! (obj->version == 5))
    2810           0 :     goto fail;
    2811             : 
    2812             :   /* Parse u8 method */
    2813           0 :   CHECK_REMAINING(1, truncated);
    2814           0 :   obj->method = (trunnel_get_uint8(ptr));
    2815           0 :   remaining -= 1; ptr += 1;
    2816           0 :   trunnel_assert(ptr + remaining == input + len_in);
    2817             :   return len_in - remaining;
    2818             : 
    2819             :  truncated:
    2820             :   return -2;
    2821           0 :  fail:
    2822           0 :   result = -1;
    2823           0 :   return result;
    2824             : }
    2825             : 
    2826             : ssize_t
    2827           0 : socks5_server_method_parse(socks5_server_method_t **output, const uint8_t *input, const size_t len_in)
    2828             : {
    2829           0 :   ssize_t result;
    2830           0 :   *output = socks5_server_method_new();
    2831           0 :   if (NULL == *output)
    2832             :     return -1;
    2833           0 :   result = socks5_server_method_parse_into(*output, input, len_in);
    2834           0 :   if (result < 0) {
    2835           0 :     socks5_server_method_free(*output);
    2836           0 :     *output = NULL;
    2837             :   }
    2838             :   return result;
    2839             : }
    2840             : socks5_server_userpass_auth_t *
    2841           5 : socks5_server_userpass_auth_new(void)
    2842             : {
    2843           5 :   socks5_server_userpass_auth_t *val = trunnel_calloc(1, sizeof(socks5_server_userpass_auth_t));
    2844           5 :   if (NULL == val)
    2845             :     return NULL;
    2846           5 :   val->version = 1;
    2847           5 :   return val;
    2848             : }
    2849             : 
    2850             : /** Release all storage held inside 'obj', but do not free 'obj'.
    2851             :  */
    2852             : static void
    2853             : socks5_server_userpass_auth_clear(socks5_server_userpass_auth_t *obj)
    2854             : {
    2855             :   (void) obj;
    2856             : }
    2857             : 
    2858             : void
    2859           5 : socks5_server_userpass_auth_free(socks5_server_userpass_auth_t *obj)
    2860             : {
    2861           5 :   if (obj == NULL)
    2862             :     return;
    2863           5 :   socks5_server_userpass_auth_clear(obj);
    2864           5 :   trunnel_memwipe(obj, sizeof(socks5_server_userpass_auth_t));
    2865           5 :   trunnel_free_(obj);
    2866             : }
    2867             : 
    2868             : uint8_t
    2869           0 : socks5_server_userpass_auth_get_version(const socks5_server_userpass_auth_t *inp)
    2870             : {
    2871           0 :   return inp->version;
    2872             : }
    2873             : int
    2874           4 : socks5_server_userpass_auth_set_version(socks5_server_userpass_auth_t *inp, uint8_t val)
    2875             : {
    2876           4 :   if (! ((val == 1))) {
    2877           0 :      TRUNNEL_SET_ERROR_CODE(inp);
    2878           0 :      return -1;
    2879             :   }
    2880           4 :   inp->version = val;
    2881           4 :   return 0;
    2882             : }
    2883             : uint8_t
    2884           0 : socks5_server_userpass_auth_get_status(const socks5_server_userpass_auth_t *inp)
    2885             : {
    2886           0 :   return inp->status;
    2887             : }
    2888             : int
    2889           4 : socks5_server_userpass_auth_set_status(socks5_server_userpass_auth_t *inp, uint8_t val)
    2890             : {
    2891           4 :   inp->status = val;
    2892           4 :   return 0;
    2893             : }
    2894             : const char *
    2895           8 : socks5_server_userpass_auth_check(const socks5_server_userpass_auth_t *obj)
    2896             : {
    2897           8 :   if (obj == NULL)
    2898             :     return "Object was NULL";
    2899           8 :   if (obj->trunnel_error_code_)
    2900             :     return "A set function failed on this object";
    2901           8 :   if (! (obj->version == 1))
    2902           0 :     return "Integer out of bounds";
    2903             :   return NULL;
    2904             : }
    2905             : 
    2906             : ssize_t
    2907           0 : socks5_server_userpass_auth_encoded_len(const socks5_server_userpass_auth_t *obj)
    2908             : {
    2909           0 :   ssize_t result = 0;
    2910             : 
    2911           0 :   if (NULL != socks5_server_userpass_auth_check(obj))
    2912           0 :      return -1;
    2913             : 
    2914             : 
    2915             :   /* Length of u8 version IN [1] */
    2916             :   result += 1;
    2917             : 
    2918             :   /* Length of u8 status */
    2919           0 :   result += 1;
    2920             :   return result;
    2921             : }
    2922             : int
    2923           0 : socks5_server_userpass_auth_clear_errors(socks5_server_userpass_auth_t *obj)
    2924             : {
    2925           0 :   int r = obj->trunnel_error_code_;
    2926           0 :   obj->trunnel_error_code_ = 0;
    2927           0 :   return r;
    2928             : }
    2929             : ssize_t
    2930           4 : socks5_server_userpass_auth_encode(uint8_t *output, const size_t avail, const socks5_server_userpass_auth_t *obj)
    2931             : {
    2932           4 :   ssize_t result = 0;
    2933           4 :   size_t written = 0;
    2934           4 :   uint8_t *ptr = output;
    2935           4 :   const char *msg;
    2936             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
    2937             :   const ssize_t encoded_len = socks5_server_userpass_auth_encoded_len(obj);
    2938             : #endif
    2939             : 
    2940           4 :   if (NULL != (msg = socks5_server_userpass_auth_check(obj)))
    2941           0 :     goto check_failed;
    2942             : 
    2943             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
    2944             :   trunnel_assert(encoded_len >= 0);
    2945             : #endif
    2946             : 
    2947             :   /* Encode u8 version IN [1] */
    2948           4 :   trunnel_assert(written <= avail);
    2949           4 :   if (avail - written < 1)
    2950           0 :     goto truncated;
    2951           4 :   trunnel_set_uint8(ptr, (obj->version));
    2952           4 :   written += 1; ptr += 1;
    2953             : 
    2954             :   /* Encode u8 status */
    2955           4 :   trunnel_assert(written <= avail);
    2956           4 :   if (avail - written < 1)
    2957           0 :     goto truncated;
    2958           4 :   trunnel_set_uint8(ptr, (obj->status));
    2959           4 :   written += 1; ptr += 1;
    2960             : 
    2961             : 
    2962           4 :   trunnel_assert(ptr == output + written);
    2963             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
    2964             :   {
    2965             :     trunnel_assert(encoded_len >= 0);
    2966             :     trunnel_assert((size_t)encoded_len == written);
    2967             :   }
    2968             : 
    2969             : #endif
    2970             : 
    2971             :   return written;
    2972             : 
    2973           0 :  truncated:
    2974           0 :   result = -2;
    2975           0 :   goto fail;
    2976           0 :  check_failed:
    2977           0 :   (void)msg;
    2978           0 :   result = -1;
    2979           0 :   goto fail;
    2980             :  fail:
    2981             :   trunnel_assert(result < 0);
    2982             :   return result;
    2983             : }
    2984             : 
    2985             : /** As socks5_server_userpass_auth_parse(), but do not allocate the
    2986             :  * output object.
    2987             :  */
    2988             : static ssize_t
    2989           0 : socks5_server_userpass_auth_parse_into(socks5_server_userpass_auth_t *obj, const uint8_t *input, const size_t len_in)
    2990             : {
    2991           0 :   const uint8_t *ptr = input;
    2992           0 :   size_t remaining = len_in;
    2993           0 :   ssize_t result = 0;
    2994           0 :   (void)result;
    2995             : 
    2996             :   /* Parse u8 version IN [1] */
    2997           0 :   CHECK_REMAINING(1, truncated);
    2998           0 :   obj->version = (trunnel_get_uint8(ptr));
    2999           0 :   remaining -= 1; ptr += 1;
    3000           0 :   if (! (obj->version == 1))
    3001           0 :     goto fail;
    3002             : 
    3003             :   /* Parse u8 status */
    3004           0 :   CHECK_REMAINING(1, truncated);
    3005           0 :   obj->status = (trunnel_get_uint8(ptr));
    3006           0 :   remaining -= 1; ptr += 1;
    3007           0 :   trunnel_assert(ptr + remaining == input + len_in);
    3008             :   return len_in - remaining;
    3009             : 
    3010             :  truncated:
    3011             :   return -2;
    3012           0 :  fail:
    3013           0 :   result = -1;
    3014           0 :   return result;
    3015             : }
    3016             : 
    3017             : ssize_t
    3018           0 : socks5_server_userpass_auth_parse(socks5_server_userpass_auth_t **output, const uint8_t *input, const size_t len_in)
    3019             : {
    3020           0 :   ssize_t result;
    3021           0 :   *output = socks5_server_userpass_auth_new();
    3022           0 :   if (NULL == *output)
    3023             :     return -1;
    3024           0 :   result = socks5_server_userpass_auth_parse_into(*output, input, len_in);
    3025           0 :   if (result < 0) {
    3026           0 :     socks5_server_userpass_auth_free(*output);
    3027           0 :     *output = NULL;
    3028             :   }
    3029             :   return result;
    3030             : }
    3031             : socks5_client_request_t *
    3032         333 : socks5_client_request_new(void)
    3033             : {
    3034         333 :   socks5_client_request_t *val = trunnel_calloc(1, sizeof(socks5_client_request_t));
    3035         333 :   if (NULL == val)
    3036             :     return NULL;
    3037         333 :   val->version = 5;
    3038         333 :   val->command = CMD_BIND;
    3039         333 :   return val;
    3040             : }
    3041             : 
    3042             : /** Release all storage held inside 'obj', but do not free 'obj'.
    3043             :  */
    3044             : static void
    3045         333 : socks5_client_request_clear(socks5_client_request_t *obj)
    3046             : {
    3047         333 :   (void) obj;
    3048         333 :   domainname_free(obj->dest_addr_domainname);
    3049         333 :   obj->dest_addr_domainname = NULL;
    3050         333 : }
    3051             : 
    3052             : void
    3053         649 : socks5_client_request_free(socks5_client_request_t *obj)
    3054             : {
    3055         649 :   if (obj == NULL)
    3056             :     return;
    3057         333 :   socks5_client_request_clear(obj);
    3058         333 :   trunnel_memwipe(obj, sizeof(socks5_client_request_t));
    3059         333 :   trunnel_free_(obj);
    3060             : }
    3061             : 
    3062             : uint8_t
    3063          17 : socks5_client_request_get_version(const socks5_client_request_t *inp)
    3064             : {
    3065          17 :   return inp->version;
    3066             : }
    3067             : int
    3068           0 : socks5_client_request_set_version(socks5_client_request_t *inp, uint8_t val)
    3069             : {
    3070           0 :   if (! ((val == 5))) {
    3071           0 :      TRUNNEL_SET_ERROR_CODE(inp);
    3072           0 :      return -1;
    3073             :   }
    3074           0 :   inp->version = val;
    3075           0 :   return 0;
    3076             : }
    3077             : uint8_t
    3078          17 : socks5_client_request_get_command(const socks5_client_request_t *inp)
    3079             : {
    3080          17 :   return inp->command;
    3081             : }
    3082             : int
    3083           0 : socks5_client_request_set_command(socks5_client_request_t *inp, uint8_t val)
    3084             : {
    3085           0 :   if (! ((val == CMD_BIND || val == CMD_CONNECT || val == CMD_RESOLVE || val == CMD_RESOLVE_PTR || val == CMD_UDP_ASSOCIATE))) {
    3086           0 :      TRUNNEL_SET_ERROR_CODE(inp);
    3087           0 :      return -1;
    3088             :   }
    3089           0 :   inp->command = val;
    3090           0 :   return 0;
    3091             : }
    3092             : uint8_t
    3093           0 : socks5_client_request_get_reserved(const socks5_client_request_t *inp)
    3094             : {
    3095           0 :   return inp->reserved;
    3096             : }
    3097             : int
    3098           0 : socks5_client_request_set_reserved(socks5_client_request_t *inp, uint8_t val)
    3099             : {
    3100           0 :   if (! ((val == 0))) {
    3101           0 :      TRUNNEL_SET_ERROR_CODE(inp);
    3102           0 :      return -1;
    3103             :   }
    3104           0 :   inp->reserved = val;
    3105           0 :   return 0;
    3106             : }
    3107             : uint8_t
    3108          17 : socks5_client_request_get_atype(const socks5_client_request_t *inp)
    3109             : {
    3110          17 :   return inp->atype;
    3111             : }
    3112             : int
    3113           0 : socks5_client_request_set_atype(socks5_client_request_t *inp, uint8_t val)
    3114             : {
    3115           0 :   inp->atype = val;
    3116           0 :   return 0;
    3117             : }
    3118             : uint32_t
    3119           6 : socks5_client_request_get_dest_addr_ipv4(const socks5_client_request_t *inp)
    3120             : {
    3121           6 :   return inp->dest_addr_ipv4;
    3122             : }
    3123             : int
    3124           0 : socks5_client_request_set_dest_addr_ipv4(socks5_client_request_t *inp, uint32_t val)
    3125             : {
    3126           0 :   inp->dest_addr_ipv4 = val;
    3127           0 :   return 0;
    3128             : }
    3129             : size_t
    3130           0 : socks5_client_request_getlen_dest_addr_ipv6(const socks5_client_request_t *inp)
    3131             : {
    3132           0 :   (void)inp;  return 16;
    3133             : }
    3134             : 
    3135             : uint8_t
    3136           0 : socks5_client_request_get_dest_addr_ipv6(socks5_client_request_t *inp, size_t idx)
    3137             : {
    3138           0 :   trunnel_assert(idx < 16);
    3139           0 :   return inp->dest_addr_ipv6[idx];
    3140             : }
    3141             : 
    3142             : uint8_t
    3143           0 : socks5_client_request_getconst_dest_addr_ipv6(const socks5_client_request_t *inp, size_t idx)
    3144             : {
    3145           0 :   return socks5_client_request_get_dest_addr_ipv6((socks5_client_request_t*)inp, idx);
    3146             : }
    3147             : int
    3148           0 : socks5_client_request_set_dest_addr_ipv6(socks5_client_request_t *inp, size_t idx, uint8_t elt)
    3149             : {
    3150           0 :   trunnel_assert(idx < 16);
    3151           0 :   inp->dest_addr_ipv6[idx] = elt;
    3152           0 :   return 0;
    3153             : }
    3154             : 
    3155             : uint8_t *
    3156           2 : socks5_client_request_getarray_dest_addr_ipv6(socks5_client_request_t *inp)
    3157             : {
    3158           2 :   return inp->dest_addr_ipv6;
    3159             : }
    3160             : const uint8_t  *
    3161           0 : socks5_client_request_getconstarray_dest_addr_ipv6(const socks5_client_request_t *inp)
    3162             : {
    3163           0 :   return (const uint8_t  *)socks5_client_request_getarray_dest_addr_ipv6((socks5_client_request_t*)inp);
    3164             : }
    3165             : struct domainname_st *
    3166           9 : socks5_client_request_get_dest_addr_domainname(socks5_client_request_t *inp)
    3167             : {
    3168           9 :   return inp->dest_addr_domainname;
    3169             : }
    3170             : const struct domainname_st *
    3171           9 : socks5_client_request_getconst_dest_addr_domainname(const socks5_client_request_t *inp)
    3172             : {
    3173           9 :   return socks5_client_request_get_dest_addr_domainname((socks5_client_request_t*) inp);
    3174             : }
    3175             : int
    3176           0 : socks5_client_request_set_dest_addr_domainname(socks5_client_request_t *inp, struct domainname_st *val)
    3177             : {
    3178           0 :   if (inp->dest_addr_domainname && inp->dest_addr_domainname != val)
    3179           0 :     domainname_free(inp->dest_addr_domainname);
    3180           0 :   return socks5_client_request_set0_dest_addr_domainname(inp, val);
    3181             : }
    3182             : int
    3183           0 : socks5_client_request_set0_dest_addr_domainname(socks5_client_request_t *inp, struct domainname_st *val)
    3184             : {
    3185           0 :   inp->dest_addr_domainname = val;
    3186           0 :   return 0;
    3187             : }
    3188             : uint16_t
    3189          17 : socks5_client_request_get_dest_port(const socks5_client_request_t *inp)
    3190             : {
    3191          17 :   return inp->dest_port;
    3192             : }
    3193             : int
    3194           0 : socks5_client_request_set_dest_port(socks5_client_request_t *inp, uint16_t val)
    3195             : {
    3196           0 :   inp->dest_port = val;
    3197           0 :   return 0;
    3198             : }
    3199             : const char *
    3200           0 : socks5_client_request_check(const socks5_client_request_t *obj)
    3201             : {
    3202           0 :   if (obj == NULL)
    3203             :     return "Object was NULL";
    3204           0 :   if (obj->trunnel_error_code_)
    3205             :     return "A set function failed on this object";
    3206           0 :   if (! (obj->version == 5))
    3207             :     return "Integer out of bounds";
    3208           0 :   if (! (obj->command == CMD_BIND || obj->command == CMD_CONNECT || obj->command == CMD_RESOLVE || obj->command == CMD_RESOLVE_PTR || obj->command == CMD_UDP_ASSOCIATE))
    3209             :     return "Integer out of bounds";
    3210           0 :   if (! (obj->reserved == 0))
    3211             :     return "Integer out of bounds";
    3212           0 :   switch (obj->atype) {
    3213             : 
    3214             :     case ATYPE_IPV4:
    3215             :       break;
    3216             : 
    3217             :     case ATYPE_IPV6:
    3218             :       break;
    3219             : 
    3220           0 :     case ATYPE_DOMAINNAME:
    3221             :       {
    3222           0 :         const char *msg;
    3223           0 :         if (NULL != (msg = domainname_check(obj->dest_addr_domainname)))
    3224           0 :           return msg;
    3225             :       }
    3226             :       break;
    3227             : 
    3228             :     default:
    3229             :         return "Bad tag for union";
    3230             :       break;
    3231             :   }
    3232             :   return NULL;
    3233             : }
    3234             : 
    3235             : ssize_t
    3236           0 : socks5_client_request_encoded_len(const socks5_client_request_t *obj)
    3237             : {
    3238           0 :   ssize_t result = 0;
    3239             : 
    3240           0 :   if (NULL != socks5_client_request_check(obj))
    3241             :      return -1;
    3242             : 
    3243             : 
    3244             :   /* Length of u8 version IN [5] */
    3245           0 :   result += 1;
    3246             : 
    3247             :   /* Length of u8 command IN [CMD_BIND, CMD_CONNECT, CMD_RESOLVE, CMD_RESOLVE_PTR, CMD_UDP_ASSOCIATE] */
    3248           0 :   result += 1;
    3249             : 
    3250             :   /* Length of u8 reserved IN [0] */
    3251           0 :   result += 1;
    3252             : 
    3253             :   /* Length of u8 atype */
    3254           0 :   result += 1;
    3255           0 :   switch (obj->atype) {
    3256             : 
    3257             :     case ATYPE_IPV4:
    3258             : 
    3259             :       /* Length of u32 dest_addr_ipv4 */
    3260             :       result += 4;
    3261             :       break;
    3262             : 
    3263           0 :     case ATYPE_IPV6:
    3264             : 
    3265             :       /* Length of u8 dest_addr_ipv6[16] */
    3266           0 :       result += 16;
    3267           0 :       break;
    3268             : 
    3269           0 :     case ATYPE_DOMAINNAME:
    3270             : 
    3271             :       /* Length of struct domainname dest_addr_domainname */
    3272           0 :       result += domainname_encoded_len(obj->dest_addr_domainname);
    3273           0 :       break;
    3274             : 
    3275             :     default:
    3276           0 :       trunnel_assert(0);
    3277             :       break;
    3278             :   }
    3279             : 
    3280             :   /* Length of u16 dest_port */
    3281           0 :   result += 2;
    3282           0 :   return result;
    3283             : }
    3284             : int
    3285           0 : socks5_client_request_clear_errors(socks5_client_request_t *obj)
    3286             : {
    3287           0 :   int r = obj->trunnel_error_code_;
    3288           0 :   obj->trunnel_error_code_ = 0;
    3289           0 :   return r;
    3290             : }
    3291             : ssize_t
    3292           0 : socks5_client_request_encode(uint8_t *output, const size_t avail, const socks5_client_request_t *obj)
    3293             : {
    3294           0 :   ssize_t result = 0;
    3295           0 :   size_t written = 0;
    3296           0 :   uint8_t *ptr = output;
    3297           0 :   const char *msg;
    3298             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
    3299             :   const ssize_t encoded_len = socks5_client_request_encoded_len(obj);
    3300             : #endif
    3301             : 
    3302           0 :   if (NULL != (msg = socks5_client_request_check(obj)))
    3303           0 :     goto check_failed;
    3304             : 
    3305             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
    3306             :   trunnel_assert(encoded_len >= 0);
    3307             : #endif
    3308             : 
    3309             :   /* Encode u8 version IN [5] */
    3310           0 :   trunnel_assert(written <= avail);
    3311           0 :   if (avail - written < 1)
    3312           0 :     goto truncated;
    3313           0 :   trunnel_set_uint8(ptr, (obj->version));
    3314           0 :   written += 1; ptr += 1;
    3315             : 
    3316             :   /* Encode u8 command IN [CMD_BIND, CMD_CONNECT, CMD_RESOLVE, CMD_RESOLVE_PTR, CMD_UDP_ASSOCIATE] */
    3317           0 :   trunnel_assert(written <= avail);
    3318           0 :   if (avail - written < 1)
    3319           0 :     goto truncated;
    3320           0 :   trunnel_set_uint8(ptr, (obj->command));
    3321           0 :   written += 1; ptr += 1;
    3322             : 
    3323             :   /* Encode u8 reserved IN [0] */
    3324           0 :   trunnel_assert(written <= avail);
    3325           0 :   if (avail - written < 1)
    3326           0 :     goto truncated;
    3327           0 :   trunnel_set_uint8(ptr, (obj->reserved));
    3328           0 :   written += 1; ptr += 1;
    3329             : 
    3330             :   /* Encode u8 atype */
    3331           0 :   trunnel_assert(written <= avail);
    3332           0 :   if (avail - written < 1)
    3333           0 :     goto truncated;
    3334           0 :   trunnel_set_uint8(ptr, (obj->atype));
    3335           0 :   written += 1; ptr += 1;
    3336             : 
    3337             :   /* Encode union dest_addr[atype] */
    3338           0 :   trunnel_assert(written <= avail);
    3339           0 :   switch (obj->atype) {
    3340             : 
    3341             :     case ATYPE_IPV4:
    3342             : 
    3343             :       /* Encode u32 dest_addr_ipv4 */
    3344           0 :       trunnel_assert(written <= avail);
    3345           0 :       if (avail - written < 4)
    3346           0 :         goto truncated;
    3347           0 :       trunnel_set_uint32(ptr, trunnel_htonl(obj->dest_addr_ipv4));
    3348           0 :       written += 4; ptr += 4;
    3349           0 :       break;
    3350             : 
    3351             :     case ATYPE_IPV6:
    3352             : 
    3353             :       /* Encode u8 dest_addr_ipv6[16] */
    3354           0 :       trunnel_assert(written <= avail);
    3355           0 :       if (avail - written < 16)
    3356           0 :         goto truncated;
    3357           0 :       memcpy(ptr, obj->dest_addr_ipv6, 16);
    3358           0 :       written += 16; ptr += 16;
    3359           0 :       break;
    3360             : 
    3361             :     case ATYPE_DOMAINNAME:
    3362             : 
    3363             :       /* Encode struct domainname dest_addr_domainname */
    3364           0 :       trunnel_assert(written <= avail);
    3365           0 :       result = domainname_encode(ptr, avail - written, obj->dest_addr_domainname);
    3366           0 :       if (result < 0)
    3367           0 :         goto fail; /* XXXXXXX !*/
    3368           0 :       written += result; ptr += result;
    3369           0 :       break;
    3370             : 
    3371             :     default:
    3372           0 :       trunnel_assert(0);
    3373             :       break;
    3374             :   }
    3375             : 
    3376             :   /* Encode u16 dest_port */
    3377           0 :   trunnel_assert(written <= avail);
    3378           0 :   if (avail - written < 2)
    3379           0 :     goto truncated;
    3380           0 :   trunnel_set_uint16(ptr, trunnel_htons(obj->dest_port));
    3381           0 :   written += 2; ptr += 2;
    3382             : 
    3383             : 
    3384           0 :   trunnel_assert(ptr == output + written);
    3385             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
    3386             :   {
    3387             :     trunnel_assert(encoded_len >= 0);
    3388             :     trunnel_assert((size_t)encoded_len == written);
    3389             :   }
    3390             : 
    3391             : #endif
    3392             : 
    3393           0 :   return written;
    3394             : 
    3395           0 :  truncated:
    3396           0 :   result = -2;
    3397           0 :   goto fail;
    3398           0 :  check_failed:
    3399           0 :   (void)msg;
    3400           0 :   result = -1;
    3401           0 :   goto fail;
    3402           0 :  fail:
    3403           0 :   trunnel_assert(result < 0);
    3404             :   return result;
    3405             : }
    3406             : 
    3407             : /** As socks5_client_request_parse(), but do not allocate the output
    3408             :  * object.
    3409             :  */
    3410             : static ssize_t
    3411         333 : socks5_client_request_parse_into(socks5_client_request_t *obj, const uint8_t *input, const size_t len_in)
    3412             : {
    3413         333 :   const uint8_t *ptr = input;
    3414         333 :   size_t remaining = len_in;
    3415         333 :   ssize_t result = 0;
    3416         333 :   (void)result;
    3417             : 
    3418             :   /* Parse u8 version IN [5] */
    3419         333 :   CHECK_REMAINING(1, truncated);
    3420         333 :   obj->version = (trunnel_get_uint8(ptr));
    3421         333 :   remaining -= 1; ptr += 1;
    3422         333 :   if (! (obj->version == 5))
    3423           0 :     goto fail;
    3424             : 
    3425             :   /* Parse u8 command IN [CMD_BIND, CMD_CONNECT, CMD_RESOLVE, CMD_RESOLVE_PTR, CMD_UDP_ASSOCIATE] */
    3426         333 :   CHECK_REMAINING(1, truncated);
    3427         333 :   obj->command = (trunnel_get_uint8(ptr));
    3428         333 :   remaining -= 1; ptr += 1;
    3429         333 :   if (! (obj->command == CMD_BIND || obj->command == CMD_CONNECT || obj->command == CMD_RESOLVE || obj->command == CMD_RESOLVE_PTR || obj->command == CMD_UDP_ASSOCIATE))
    3430           0 :     goto fail;
    3431             : 
    3432             :   /* Parse u8 reserved IN [0] */
    3433         333 :   CHECK_REMAINING(1, truncated);
    3434         328 :   obj->reserved = (trunnel_get_uint8(ptr));
    3435         328 :   remaining -= 1; ptr += 1;
    3436         328 :   if (! (obj->reserved == 0))
    3437           0 :     goto fail;
    3438             : 
    3439             :   /* Parse u8 atype */
    3440         328 :   CHECK_REMAINING(1, truncated);
    3441         323 :   obj->atype = (trunnel_get_uint8(ptr));
    3442         323 :   remaining -= 1; ptr += 1;
    3443             : 
    3444             :   /* Parse union dest_addr[atype] */
    3445         323 :   switch (obj->atype) {
    3446             : 
    3447          12 :     case ATYPE_IPV4:
    3448             : 
    3449             :       /* Parse u32 dest_addr_ipv4 */
    3450          12 :       CHECK_REMAINING(4, truncated);
    3451           8 :       obj->dest_addr_ipv4 = trunnel_ntohl(trunnel_get_uint32(ptr));
    3452           8 :       remaining -= 4; ptr += 4;
    3453           8 :       break;
    3454             : 
    3455          20 :     case ATYPE_IPV6:
    3456             : 
    3457             :       /* Parse u8 dest_addr_ipv6[16] */
    3458          20 :       CHECK_REMAINING(16, truncated);
    3459           4 :       memcpy(obj->dest_addr_ipv6, ptr, 16);
    3460           4 :       remaining -= 16; ptr += 16;
    3461           4 :       break;
    3462             : 
    3463         290 :     case ATYPE_DOMAINNAME:
    3464             : 
    3465             :       /* Parse struct domainname dest_addr_domainname */
    3466         290 :       result = domainname_parse(&obj->dest_addr_domainname, ptr, remaining);
    3467         290 :       if (result < 0)
    3468         275 :         goto relay_fail;
    3469          15 :       trunnel_assert((size_t)result <= remaining);
    3470          15 :       remaining -= result; ptr += result;
    3471          15 :       break;
    3472             : 
    3473           1 :     default:
    3474           1 :       goto fail;
    3475          27 :       break;
    3476             :   }
    3477             : 
    3478             :   /* Parse u16 dest_port */
    3479          27 :   CHECK_REMAINING(2, truncated);
    3480          17 :   obj->dest_port = trunnel_ntohs(trunnel_get_uint16(ptr));
    3481          17 :   remaining -= 2; ptr += 2;
    3482          17 :   trunnel_assert(ptr + remaining == input + len_in);
    3483          17 :   return len_in - remaining;
    3484             : 
    3485             :  truncated:
    3486             :   return -2;
    3487         275 :  relay_fail:
    3488         275 :   trunnel_assert(result < 0);
    3489             :   return result;
    3490             :  fail:
    3491         333 :   result = -1;
    3492             :   return result;
    3493             : }
    3494             : 
    3495             : ssize_t
    3496         333 : socks5_client_request_parse(socks5_client_request_t **output, const uint8_t *input, const size_t len_in)
    3497             : {
    3498         333 :   ssize_t result;
    3499         333 :   *output = socks5_client_request_new();
    3500         333 :   if (NULL == *output)
    3501             :     return -1;
    3502         333 :   result = socks5_client_request_parse_into(*output, input, len_in);
    3503         333 :   if (result < 0) {
    3504         316 :     socks5_client_request_free(*output);
    3505         316 :     *output = NULL;
    3506             :   }
    3507             :   return result;
    3508             : }
    3509             : socks5_server_reply_t *
    3510           7 : socks5_server_reply_new(void)
    3511             : {
    3512           7 :   socks5_server_reply_t *val = trunnel_calloc(1, sizeof(socks5_server_reply_t));
    3513           7 :   if (NULL == val)
    3514             :     return NULL;
    3515           7 :   val->version = 5;
    3516           7 :   return val;
    3517             : }
    3518             : 
    3519             : /** Release all storage held inside 'obj', but do not free 'obj'.
    3520             :  */
    3521             : static void
    3522           7 : socks5_server_reply_clear(socks5_server_reply_t *obj)
    3523             : {
    3524           7 :   (void) obj;
    3525           7 :   domainname_free(obj->bind_addr_domainname);
    3526           7 :   obj->bind_addr_domainname = NULL;
    3527           7 : }
    3528             : 
    3529             : void
    3530           7 : socks5_server_reply_free(socks5_server_reply_t *obj)
    3531             : {
    3532           7 :   if (obj == NULL)
    3533             :     return;
    3534           7 :   socks5_server_reply_clear(obj);
    3535           7 :   trunnel_memwipe(obj, sizeof(socks5_server_reply_t));
    3536           7 :   trunnel_free_(obj);
    3537             : }
    3538             : 
    3539             : uint8_t
    3540           0 : socks5_server_reply_get_version(const socks5_server_reply_t *inp)
    3541             : {
    3542           0 :   return inp->version;
    3543             : }
    3544             : int
    3545           7 : socks5_server_reply_set_version(socks5_server_reply_t *inp, uint8_t val)
    3546             : {
    3547           7 :   if (! ((val == 5))) {
    3548           0 :      TRUNNEL_SET_ERROR_CODE(inp);
    3549           0 :      return -1;
    3550             :   }
    3551           7 :   inp->version = val;
    3552           7 :   return 0;
    3553             : }
    3554             : uint8_t
    3555           0 : socks5_server_reply_get_reply(const socks5_server_reply_t *inp)
    3556             : {
    3557           0 :   return inp->reply;
    3558             : }
    3559             : int
    3560           7 : socks5_server_reply_set_reply(socks5_server_reply_t *inp, uint8_t val)
    3561             : {
    3562           7 :   inp->reply = val;
    3563           7 :   return 0;
    3564             : }
    3565             : uint8_t
    3566           0 : socks5_server_reply_get_reserved(const socks5_server_reply_t *inp)
    3567             : {
    3568           0 :   return inp->reserved;
    3569             : }
    3570             : int
    3571           0 : socks5_server_reply_set_reserved(socks5_server_reply_t *inp, uint8_t val)
    3572             : {
    3573           0 :   if (! ((val == 0))) {
    3574           0 :      TRUNNEL_SET_ERROR_CODE(inp);
    3575           0 :      return -1;
    3576             :   }
    3577           0 :   inp->reserved = val;
    3578           0 :   return 0;
    3579             : }
    3580             : uint8_t
    3581           0 : socks5_server_reply_get_atype(const socks5_server_reply_t *inp)
    3582             : {
    3583           0 :   return inp->atype;
    3584             : }
    3585             : int
    3586           7 : socks5_server_reply_set_atype(socks5_server_reply_t *inp, uint8_t val)
    3587             : {
    3588           7 :   inp->atype = val;
    3589           7 :   return 0;
    3590             : }
    3591             : uint32_t
    3592           0 : socks5_server_reply_get_bind_addr_ipv4(const socks5_server_reply_t *inp)
    3593             : {
    3594           0 :   return inp->bind_addr_ipv4;
    3595             : }
    3596             : int
    3597           0 : socks5_server_reply_set_bind_addr_ipv4(socks5_server_reply_t *inp, uint32_t val)
    3598             : {
    3599           0 :   inp->bind_addr_ipv4 = val;
    3600           0 :   return 0;
    3601             : }
    3602             : size_t
    3603           0 : socks5_server_reply_getlen_bind_addr_ipv6(const socks5_server_reply_t *inp)
    3604             : {
    3605           0 :   (void)inp;  return 16;
    3606             : }
    3607             : 
    3608             : uint8_t
    3609           0 : socks5_server_reply_get_bind_addr_ipv6(socks5_server_reply_t *inp, size_t idx)
    3610             : {
    3611           0 :   trunnel_assert(idx < 16);
    3612           0 :   return inp->bind_addr_ipv6[idx];
    3613             : }
    3614             : 
    3615             : uint8_t
    3616           0 : socks5_server_reply_getconst_bind_addr_ipv6(const socks5_server_reply_t *inp, size_t idx)
    3617             : {
    3618           0 :   return socks5_server_reply_get_bind_addr_ipv6((socks5_server_reply_t*)inp, idx);
    3619             : }
    3620             : int
    3621           0 : socks5_server_reply_set_bind_addr_ipv6(socks5_server_reply_t *inp, size_t idx, uint8_t elt)
    3622             : {
    3623           0 :   trunnel_assert(idx < 16);
    3624           0 :   inp->bind_addr_ipv6[idx] = elt;
    3625           0 :   return 0;
    3626             : }
    3627             : 
    3628             : uint8_t *
    3629           0 : socks5_server_reply_getarray_bind_addr_ipv6(socks5_server_reply_t *inp)
    3630             : {
    3631           0 :   return inp->bind_addr_ipv6;
    3632             : }
    3633             : const uint8_t  *
    3634           0 : socks5_server_reply_getconstarray_bind_addr_ipv6(const socks5_server_reply_t *inp)
    3635             : {
    3636           0 :   return (const uint8_t  *)socks5_server_reply_getarray_bind_addr_ipv6((socks5_server_reply_t*)inp);
    3637             : }
    3638             : struct domainname_st *
    3639           0 : socks5_server_reply_get_bind_addr_domainname(socks5_server_reply_t *inp)
    3640             : {
    3641           0 :   return inp->bind_addr_domainname;
    3642             : }
    3643             : const struct domainname_st *
    3644           0 : socks5_server_reply_getconst_bind_addr_domainname(const socks5_server_reply_t *inp)
    3645             : {
    3646           0 :   return socks5_server_reply_get_bind_addr_domainname((socks5_server_reply_t*) inp);
    3647             : }
    3648             : int
    3649           0 : socks5_server_reply_set_bind_addr_domainname(socks5_server_reply_t *inp, struct domainname_st *val)
    3650             : {
    3651           0 :   if (inp->bind_addr_domainname && inp->bind_addr_domainname != val)
    3652           0 :     domainname_free(inp->bind_addr_domainname);
    3653           0 :   return socks5_server_reply_set0_bind_addr_domainname(inp, val);
    3654             : }
    3655             : int
    3656           0 : socks5_server_reply_set0_bind_addr_domainname(socks5_server_reply_t *inp, struct domainname_st *val)
    3657             : {
    3658           0 :   inp->bind_addr_domainname = val;
    3659           0 :   return 0;
    3660             : }
    3661             : uint16_t
    3662           0 : socks5_server_reply_get_bind_port(const socks5_server_reply_t *inp)
    3663             : {
    3664           0 :   return inp->bind_port;
    3665             : }
    3666             : int
    3667           0 : socks5_server_reply_set_bind_port(socks5_server_reply_t *inp, uint16_t val)
    3668             : {
    3669           0 :   inp->bind_port = val;
    3670           0 :   return 0;
    3671             : }
    3672             : const char *
    3673          14 : socks5_server_reply_check(const socks5_server_reply_t *obj)
    3674             : {
    3675          14 :   if (obj == NULL)
    3676             :     return "Object was NULL";
    3677          14 :   if (obj->trunnel_error_code_)
    3678             :     return "A set function failed on this object";
    3679          14 :   if (! (obj->version == 5))
    3680             :     return "Integer out of bounds";
    3681          14 :   if (! (obj->reserved == 0))
    3682             :     return "Integer out of bounds";
    3683          14 :   switch (obj->atype) {
    3684             : 
    3685             :     case ATYPE_IPV4:
    3686             :       break;
    3687             : 
    3688             :     case ATYPE_IPV6:
    3689             :       break;
    3690             : 
    3691           0 :     case ATYPE_DOMAINNAME:
    3692             :       {
    3693           0 :         const char *msg;
    3694           0 :         if (NULL != (msg = domainname_check(obj->bind_addr_domainname)))
    3695           0 :           return msg;
    3696             :       }
    3697             :       break;
    3698             : 
    3699             :     default:
    3700             :         return "Bad tag for union";
    3701             :       break;
    3702             :   }
    3703             :   return NULL;
    3704             : }
    3705             : 
    3706             : ssize_t
    3707           0 : socks5_server_reply_encoded_len(const socks5_server_reply_t *obj)
    3708             : {
    3709           0 :   ssize_t result = 0;
    3710             : 
    3711           0 :   if (NULL != socks5_server_reply_check(obj))
    3712             :      return -1;
    3713             : 
    3714             : 
    3715             :   /* Length of u8 version IN [5] */
    3716           0 :   result += 1;
    3717             : 
    3718             :   /* Length of u8 reply */
    3719           0 :   result += 1;
    3720             : 
    3721             :   /* Length of u8 reserved IN [0] */
    3722           0 :   result += 1;
    3723             : 
    3724             :   /* Length of u8 atype */
    3725           0 :   result += 1;
    3726           0 :   switch (obj->atype) {
    3727             : 
    3728             :     case ATYPE_IPV4:
    3729             : 
    3730             :       /* Length of u32 bind_addr_ipv4 */
    3731             :       result += 4;
    3732             :       break;
    3733             : 
    3734           0 :     case ATYPE_IPV6:
    3735             : 
    3736             :       /* Length of u8 bind_addr_ipv6[16] */
    3737           0 :       result += 16;
    3738           0 :       break;
    3739             : 
    3740           0 :     case ATYPE_DOMAINNAME:
    3741             : 
    3742             :       /* Length of struct domainname bind_addr_domainname */
    3743           0 :       result += domainname_encoded_len(obj->bind_addr_domainname);
    3744           0 :       break;
    3745             : 
    3746             :     default:
    3747           0 :       trunnel_assert(0);
    3748             :       break;
    3749             :   }
    3750             : 
    3751             :   /* Length of u16 bind_port */
    3752           0 :   result += 2;
    3753           0 :   return result;
    3754             : }
    3755             : int
    3756           0 : socks5_server_reply_clear_errors(socks5_server_reply_t *obj)
    3757             : {
    3758           0 :   int r = obj->trunnel_error_code_;
    3759           0 :   obj->trunnel_error_code_ = 0;
    3760           0 :   return r;
    3761             : }
    3762             : ssize_t
    3763           7 : socks5_server_reply_encode(uint8_t *output, const size_t avail, const socks5_server_reply_t *obj)
    3764             : {
    3765           7 :   ssize_t result = 0;
    3766           7 :   size_t written = 0;
    3767           7 :   uint8_t *ptr = output;
    3768           7 :   const char *msg;
    3769             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
    3770             :   const ssize_t encoded_len = socks5_server_reply_encoded_len(obj);
    3771             : #endif
    3772             : 
    3773           7 :   if (NULL != (msg = socks5_server_reply_check(obj)))
    3774           0 :     goto check_failed;
    3775             : 
    3776             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
    3777             :   trunnel_assert(encoded_len >= 0);
    3778             : #endif
    3779             : 
    3780             :   /* Encode u8 version IN [5] */
    3781           7 :   trunnel_assert(written <= avail);
    3782           7 :   if (avail - written < 1)
    3783           0 :     goto truncated;
    3784           7 :   trunnel_set_uint8(ptr, (obj->version));
    3785           7 :   written += 1; ptr += 1;
    3786             : 
    3787             :   /* Encode u8 reply */
    3788           7 :   trunnel_assert(written <= avail);
    3789           7 :   if (avail - written < 1)
    3790           0 :     goto truncated;
    3791           7 :   trunnel_set_uint8(ptr, (obj->reply));
    3792           7 :   written += 1; ptr += 1;
    3793             : 
    3794             :   /* Encode u8 reserved IN [0] */
    3795           7 :   trunnel_assert(written <= avail);
    3796           7 :   if (avail - written < 1)
    3797           0 :     goto truncated;
    3798           7 :   trunnel_set_uint8(ptr, (obj->reserved));
    3799           7 :   written += 1; ptr += 1;
    3800             : 
    3801             :   /* Encode u8 atype */
    3802           7 :   trunnel_assert(written <= avail);
    3803           7 :   if (avail - written < 1)
    3804           0 :     goto truncated;
    3805           7 :   trunnel_set_uint8(ptr, (obj->atype));
    3806           7 :   written += 1; ptr += 1;
    3807             : 
    3808             :   /* Encode union bind_addr[atype] */
    3809           7 :   trunnel_assert(written <= avail);
    3810           7 :   switch (obj->atype) {
    3811             : 
    3812             :     case ATYPE_IPV4:
    3813             : 
    3814             :       /* Encode u32 bind_addr_ipv4 */
    3815           7 :       trunnel_assert(written <= avail);
    3816           7 :       if (avail - written < 4)
    3817           0 :         goto truncated;
    3818           7 :       trunnel_set_uint32(ptr, trunnel_htonl(obj->bind_addr_ipv4));
    3819           7 :       written += 4; ptr += 4;
    3820           7 :       break;
    3821             : 
    3822             :     case ATYPE_IPV6:
    3823             : 
    3824             :       /* Encode u8 bind_addr_ipv6[16] */
    3825           0 :       trunnel_assert(written <= avail);
    3826           0 :       if (avail - written < 16)
    3827           0 :         goto truncated;
    3828           0 :       memcpy(ptr, obj->bind_addr_ipv6, 16);
    3829           0 :       written += 16; ptr += 16;
    3830           0 :       break;
    3831             : 
    3832             :     case ATYPE_DOMAINNAME:
    3833             : 
    3834             :       /* Encode struct domainname bind_addr_domainname */
    3835           0 :       trunnel_assert(written <= avail);
    3836           0 :       result = domainname_encode(ptr, avail - written, obj->bind_addr_domainname);
    3837           0 :       if (result < 0)
    3838           0 :         goto fail; /* XXXXXXX !*/
    3839           0 :       written += result; ptr += result;
    3840           0 :       break;
    3841             : 
    3842             :     default:
    3843           0 :       trunnel_assert(0);
    3844             :       break;
    3845             :   }
    3846             : 
    3847             :   /* Encode u16 bind_port */
    3848           7 :   trunnel_assert(written <= avail);
    3849           7 :   if (avail - written < 2)
    3850           0 :     goto truncated;
    3851           7 :   trunnel_set_uint16(ptr, trunnel_htons(obj->bind_port));
    3852           7 :   written += 2; ptr += 2;
    3853             : 
    3854             : 
    3855           7 :   trunnel_assert(ptr == output + written);
    3856             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
    3857             :   {
    3858             :     trunnel_assert(encoded_len >= 0);
    3859             :     trunnel_assert((size_t)encoded_len == written);
    3860             :   }
    3861             : 
    3862             : #endif
    3863             : 
    3864           7 :   return written;
    3865             : 
    3866           0 :  truncated:
    3867           0 :   result = -2;
    3868           0 :   goto fail;
    3869           0 :  check_failed:
    3870           0 :   (void)msg;
    3871           0 :   result = -1;
    3872           0 :   goto fail;
    3873           0 :  fail:
    3874           0 :   trunnel_assert(result < 0);
    3875             :   return result;
    3876             : }
    3877             : 
    3878             : /** As socks5_server_reply_parse(), but do not allocate the output
    3879             :  * object.
    3880             :  */
    3881             : static ssize_t
    3882           0 : socks5_server_reply_parse_into(socks5_server_reply_t *obj, const uint8_t *input, const size_t len_in)
    3883             : {
    3884           0 :   const uint8_t *ptr = input;
    3885           0 :   size_t remaining = len_in;
    3886           0 :   ssize_t result = 0;
    3887           0 :   (void)result;
    3888             : 
    3889             :   /* Parse u8 version IN [5] */
    3890           0 :   CHECK_REMAINING(1, truncated);
    3891           0 :   obj->version = (trunnel_get_uint8(ptr));
    3892           0 :   remaining -= 1; ptr += 1;
    3893           0 :   if (! (obj->version == 5))
    3894           0 :     goto fail;
    3895             : 
    3896             :   /* Parse u8 reply */
    3897           0 :   CHECK_REMAINING(1, truncated);
    3898           0 :   obj->reply = (trunnel_get_uint8(ptr));
    3899           0 :   remaining -= 1; ptr += 1;
    3900             : 
    3901             :   /* Parse u8 reserved IN [0] */
    3902           0 :   CHECK_REMAINING(1, truncated);
    3903           0 :   obj->reserved = (trunnel_get_uint8(ptr));
    3904           0 :   remaining -= 1; ptr += 1;
    3905           0 :   if (! (obj->reserved == 0))
    3906           0 :     goto fail;
    3907             : 
    3908             :   /* Parse u8 atype */
    3909           0 :   CHECK_REMAINING(1, truncated);
    3910           0 :   obj->atype = (trunnel_get_uint8(ptr));
    3911           0 :   remaining -= 1; ptr += 1;
    3912             : 
    3913             :   /* Parse union bind_addr[atype] */
    3914           0 :   switch (obj->atype) {
    3915             : 
    3916           0 :     case ATYPE_IPV4:
    3917             : 
    3918             :       /* Parse u32 bind_addr_ipv4 */
    3919           0 :       CHECK_REMAINING(4, truncated);
    3920           0 :       obj->bind_addr_ipv4 = trunnel_ntohl(trunnel_get_uint32(ptr));
    3921           0 :       remaining -= 4; ptr += 4;
    3922           0 :       break;
    3923             : 
    3924           0 :     case ATYPE_IPV6:
    3925             : 
    3926             :       /* Parse u8 bind_addr_ipv6[16] */
    3927           0 :       CHECK_REMAINING(16, truncated);
    3928           0 :       memcpy(obj->bind_addr_ipv6, ptr, 16);
    3929           0 :       remaining -= 16; ptr += 16;
    3930           0 :       break;
    3931             : 
    3932           0 :     case ATYPE_DOMAINNAME:
    3933             : 
    3934             :       /* Parse struct domainname bind_addr_domainname */
    3935           0 :       result = domainname_parse(&obj->bind_addr_domainname, ptr, remaining);
    3936           0 :       if (result < 0)
    3937           0 :         goto relay_fail;
    3938           0 :       trunnel_assert((size_t)result <= remaining);
    3939           0 :       remaining -= result; ptr += result;
    3940           0 :       break;
    3941             : 
    3942           0 :     default:
    3943           0 :       goto fail;
    3944           0 :       break;
    3945             :   }
    3946             : 
    3947             :   /* Parse u16 bind_port */
    3948           0 :   CHECK_REMAINING(2, truncated);
    3949           0 :   obj->bind_port = trunnel_ntohs(trunnel_get_uint16(ptr));
    3950           0 :   remaining -= 2; ptr += 2;
    3951           0 :   trunnel_assert(ptr + remaining == input + len_in);
    3952           0 :   return len_in - remaining;
    3953             : 
    3954             :  truncated:
    3955             :   return -2;
    3956           0 :  relay_fail:
    3957           0 :   trunnel_assert(result < 0);
    3958             :   return result;
    3959             :  fail:
    3960           0 :   result = -1;
    3961             :   return result;
    3962             : }
    3963             : 
    3964             : ssize_t
    3965           0 : socks5_server_reply_parse(socks5_server_reply_t **output, const uint8_t *input, const size_t len_in)
    3966             : {
    3967           0 :   ssize_t result;
    3968           0 :   *output = socks5_server_reply_new();
    3969           0 :   if (NULL == *output)
    3970             :     return -1;
    3971           0 :   result = socks5_server_reply_parse_into(*output, input, len_in);
    3972           0 :   if (result < 0) {
    3973           0 :     socks5_server_reply_free(*output);
    3974           0 :     *output = NULL;
    3975             :   }
    3976             :   return result;
    3977             : }

Generated by: LCOV version 1.14