tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

socks5.c (84510B)


      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 domainname_new(void)
     33 {
     34  domainname_t *val = trunnel_calloc(1, sizeof(domainname_t));
     35  if (NULL == val)
     36    return NULL;
     37  return val;
     38 }
     39 
     40 /** Release all storage held inside 'obj', but do not free 'obj'.
     41 */
     42 static void
     43 domainname_clear(domainname_t *obj)
     44 {
     45  (void) obj;
     46  TRUNNEL_DYNARRAY_WIPE(&obj->name);
     47  TRUNNEL_DYNARRAY_CLEAR(&obj->name);
     48 }
     49 
     50 void
     51 domainname_free(domainname_t *obj)
     52 {
     53  if (obj == NULL)
     54    return;
     55  domainname_clear(obj);
     56  trunnel_memwipe(obj, sizeof(domainname_t));
     57  trunnel_free_(obj);
     58 }
     59 
     60 uint8_t
     61 domainname_get_len(const domainname_t *inp)
     62 {
     63  return inp->len;
     64 }
     65 int
     66 domainname_set_len(domainname_t *inp, uint8_t val)
     67 {
     68  inp->len = val;
     69  return 0;
     70 }
     71 size_t
     72 domainname_getlen_name(const domainname_t *inp)
     73 {
     74  return TRUNNEL_DYNARRAY_LEN(&inp->name);
     75 }
     76 
     77 char
     78 domainname_get_name(domainname_t *inp, size_t idx)
     79 {
     80  return TRUNNEL_DYNARRAY_GET(&inp->name, idx);
     81 }
     82 
     83 char
     84 domainname_getconst_name(const domainname_t *inp, size_t idx)
     85 {
     86  return domainname_get_name((domainname_t*)inp, idx);
     87 }
     88 int
     89 domainname_set_name(domainname_t *inp, size_t idx, char elt)
     90 {
     91  TRUNNEL_DYNARRAY_SET(&inp->name, idx, elt);
     92  return 0;
     93 }
     94 int
     95 domainname_add_name(domainname_t *inp, char elt)
     96 {
     97 #if SIZE_MAX >= UINT8_MAX
     98  if (inp->name.n_ == UINT8_MAX)
     99    goto trunnel_alloc_failed;
    100 #endif
    101  TRUNNEL_DYNARRAY_ADD(char, &inp->name, elt, {});
    102  return 0;
    103 trunnel_alloc_failed:
    104  TRUNNEL_SET_ERROR_CODE(inp);
    105  return -1;
    106 }
    107 
    108 char *
    109 domainname_getarray_name(domainname_t *inp)
    110 {
    111  return inp->name.elts_;
    112 }
    113 const char  *
    114 domainname_getconstarray_name(const domainname_t *inp)
    115 {
    116  return (const char  *)domainname_getarray_name((domainname_t*)inp);
    117 }
    118 int
    119 domainname_setlen_name(domainname_t *inp, size_t newlen)
    120 {
    121 #if UINT8_MAX < SIZE_MAX
    122  if (newlen > UINT8_MAX)
    123    goto trunnel_alloc_failed;
    124 #endif
    125  return trunnel_string_setlen(&inp->name, newlen,
    126            &inp->trunnel_error_code_);
    127 trunnel_alloc_failed:
    128  TRUNNEL_SET_ERROR_CODE(inp);
    129  return -1;
    130 }
    131 const char *
    132 domainname_getstr_name(domainname_t *inp)
    133 {
    134  return trunnel_string_getstr(&inp->name);
    135 }
    136 int
    137 domainname_setstr0_name(domainname_t *inp, const char *val, size_t len)
    138 {
    139 #if UINT8_MAX < SIZE_MAX
    140  if (len > UINT8_MAX) {
    141    TRUNNEL_SET_ERROR_CODE(inp);
    142    return -1;
    143  }
    144 #endif
    145  return trunnel_string_setstr0(&inp->name, val, len, &inp->trunnel_error_code_);
    146 }
    147 int
    148 domainname_setstr_name(domainname_t *inp, const char *val)
    149 {
    150  return domainname_setstr0_name(inp, val, strlen(val));
    151 }
    152 const char *
    153 domainname_check(const domainname_t *obj)
    154 {
    155  if (obj == NULL)
    156    return "Object was NULL";
    157  if (obj->trunnel_error_code_)
    158    return "A set function failed on this object";
    159  if (TRUNNEL_DYNARRAY_LEN(&obj->name) != obj->len)
    160    return "Length mismatch for name";
    161  return NULL;
    162 }
    163 
    164 ssize_t
    165 domainname_encoded_len(const domainname_t *obj)
    166 {
    167  ssize_t result = 0;
    168 
    169  if (NULL != domainname_check(obj))
    170     return -1;
    171 
    172 
    173  /* Length of u8 len */
    174  result += 1;
    175 
    176  /* Length of char name[len] */
    177  result += TRUNNEL_DYNARRAY_LEN(&obj->name);
    178  return result;
    179 }
    180 int
    181 domainname_clear_errors(domainname_t *obj)
    182 {
    183  int r = obj->trunnel_error_code_;
    184  obj->trunnel_error_code_ = 0;
    185  return r;
    186 }
    187 ssize_t
    188 domainname_encode(uint8_t *output, const size_t avail, const domainname_t *obj)
    189 {
    190  ssize_t result = 0;
    191  size_t written = 0;
    192  uint8_t *ptr = output;
    193  const char *msg;
    194 #ifdef TRUNNEL_CHECK_ENCODED_LEN
    195  const ssize_t encoded_len = domainname_encoded_len(obj);
    196 #endif
    197 
    198  if (NULL != (msg = domainname_check(obj)))
    199    goto check_failed;
    200 
    201 #ifdef TRUNNEL_CHECK_ENCODED_LEN
    202  trunnel_assert(encoded_len >= 0);
    203 #endif
    204 
    205  /* Encode u8 len */
    206  trunnel_assert(written <= avail);
    207  if (avail - written < 1)
    208    goto truncated;
    209  trunnel_set_uint8(ptr, (obj->len));
    210  written += 1; ptr += 1;
    211 
    212  /* Encode char name[len] */
    213  {
    214    size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->name);
    215    trunnel_assert(obj->len == elt_len);
    216    trunnel_assert(written <= avail);
    217    if (avail - written < elt_len)
    218      goto truncated;
    219    if (elt_len)
    220      memcpy(ptr, obj->name.elts_, elt_len);
    221    written += elt_len; ptr += elt_len;
    222  }
    223 
    224 
    225  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  return written;
    235 
    236 truncated:
    237  result = -2;
    238  goto fail;
    239 check_failed:
    240  (void)msg;
    241  result = -1;
    242  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 domainname_parse_into(domainname_t *obj, const uint8_t *input, const size_t len_in)
    252 {
    253  const uint8_t *ptr = input;
    254  size_t remaining = len_in;
    255  ssize_t result = 0;
    256  (void)result;
    257 
    258  /* Parse u8 len */
    259  CHECK_REMAINING(1, truncated);
    260  obj->len = (trunnel_get_uint8(ptr));
    261  remaining -= 1; ptr += 1;
    262 
    263  /* Parse char name[len] */
    264  CHECK_REMAINING(obj->len, truncated);
    265  if (domainname_setstr0_name(obj, (const char*)ptr, obj->len))
    266    goto fail;
    267  ptr += obj->len; remaining -= obj->len;
    268  trunnel_assert(ptr + remaining == input + len_in);
    269  return len_in - remaining;
    270 
    271 truncated:
    272  return -2;
    273 fail:
    274  result = -1;
    275  return result;
    276 }
    277 
    278 ssize_t
    279 domainname_parse(domainname_t **output, const uint8_t *input, const size_t len_in)
    280 {
    281  ssize_t result;
    282  *output = domainname_new();
    283  if (NULL == *output)
    284    return -1;
    285  result = domainname_parse_into(*output, input, len_in);
    286  if (result < 0) {
    287    domainname_free(*output);
    288    *output = NULL;
    289  }
    290  return result;
    291 }
    292 socks4_client_request_t *
    293 socks4_client_request_new(void)
    294 {
    295  socks4_client_request_t *val = trunnel_calloc(1, sizeof(socks4_client_request_t));
    296  if (NULL == val)
    297    return NULL;
    298  val->version = 4;
    299  val->command = CMD_BIND;
    300  return val;
    301 }
    302 
    303 /** Release all storage held inside 'obj', but do not free 'obj'.
    304 */
    305 static void
    306 socks4_client_request_clear(socks4_client_request_t *obj)
    307 {
    308  (void) obj;
    309  trunnel_wipestr(obj->username);
    310  trunnel_free(obj->username);
    311  trunnel_wipestr(obj->socks4a_addr_hostname);
    312  trunnel_free(obj->socks4a_addr_hostname);
    313 }
    314 
    315 void
    316 socks4_client_request_free(socks4_client_request_t *obj)
    317 {
    318  if (obj == NULL)
    319    return;
    320  socks4_client_request_clear(obj);
    321  trunnel_memwipe(obj, sizeof(socks4_client_request_t));
    322  trunnel_free_(obj);
    323 }
    324 
    325 uint8_t
    326 socks4_client_request_get_version(const socks4_client_request_t *inp)
    327 {
    328  return inp->version;
    329 }
    330 int
    331 socks4_client_request_set_version(socks4_client_request_t *inp, uint8_t val)
    332 {
    333  if (! ((val == 4))) {
    334     TRUNNEL_SET_ERROR_CODE(inp);
    335     return -1;
    336  }
    337  inp->version = val;
    338  return 0;
    339 }
    340 uint8_t
    341 socks4_client_request_get_command(const socks4_client_request_t *inp)
    342 {
    343  return inp->command;
    344 }
    345 int
    346 socks4_client_request_set_command(socks4_client_request_t *inp, uint8_t val)
    347 {
    348  if (! ((val == CMD_BIND || val == CMD_CONNECT || val == CMD_RESOLVE || val == CMD_RESOLVE_PTR))) {
    349     TRUNNEL_SET_ERROR_CODE(inp);
    350     return -1;
    351  }
    352  inp->command = val;
    353  return 0;
    354 }
    355 uint16_t
    356 socks4_client_request_get_port(const socks4_client_request_t *inp)
    357 {
    358  return inp->port;
    359 }
    360 int
    361 socks4_client_request_set_port(socks4_client_request_t *inp, uint16_t val)
    362 {
    363  inp->port = val;
    364  return 0;
    365 }
    366 uint32_t
    367 socks4_client_request_get_addr(const socks4_client_request_t *inp)
    368 {
    369  return inp->addr;
    370 }
    371 int
    372 socks4_client_request_set_addr(socks4_client_request_t *inp, uint32_t val)
    373 {
    374  inp->addr = val;
    375  return 0;
    376 }
    377 const char *
    378 socks4_client_request_get_username(const socks4_client_request_t *inp)
    379 {
    380  return inp->username;
    381 }
    382 int
    383 socks4_client_request_set_username(socks4_client_request_t *inp, const char *val)
    384 {
    385  trunnel_free(inp->username);
    386  if (NULL == (inp->username = trunnel_strdup(val))) {
    387    TRUNNEL_SET_ERROR_CODE(inp);
    388    return -1;
    389  }
    390  return 0;
    391 }
    392 const char *
    393 socks4_client_request_get_socks4a_addr_hostname(const socks4_client_request_t *inp)
    394 {
    395  return inp->socks4a_addr_hostname;
    396 }
    397 int
    398 socks4_client_request_set_socks4a_addr_hostname(socks4_client_request_t *inp, const char *val)
    399 {
    400  trunnel_free(inp->socks4a_addr_hostname);
    401  if (NULL == (inp->socks4a_addr_hostname = trunnel_strdup(val))) {
    402    TRUNNEL_SET_ERROR_CODE(inp);
    403    return -1;
    404  }
    405  return 0;
    406 }
    407 const char *
    408 socks4_client_request_check(const socks4_client_request_t *obj)
    409 {
    410  if (obj == NULL)
    411    return "Object was NULL";
    412  if (obj->trunnel_error_code_)
    413    return "A set function failed on this object";
    414  if (! (obj->version == 4))
    415    return "Integer out of bounds";
    416  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  if (NULL == obj->username)
    419    return "Missing username";
    420  switch (obj->addr) {
    421 
    422    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      if (NULL == obj->socks4a_addr_hostname)
    678        return "Missing socks4a_addr_hostname";
    679      break;
    680 
    681    default:
    682      break;
    683  }
    684  return NULL;
    685 }
    686 
    687 ssize_t
    688 socks4_client_request_encoded_len(const socks4_client_request_t *obj)
    689 {
    690  ssize_t result = 0;
    691 
    692  if (NULL != socks4_client_request_check(obj))
    693     return -1;
    694 
    695 
    696  /* Length of u8 version IN [4] */
    697  result += 1;
    698 
    699  /* Length of u8 command IN [CMD_BIND, CMD_CONNECT, CMD_RESOLVE, CMD_RESOLVE_PTR] */
    700  result += 1;
    701 
    702  /* Length of u16 port */
    703  result += 2;
    704 
    705  /* Length of u32 addr */
    706  result += 4;
    707 
    708  /* Length of nulterm username */
    709  result += strlen(obj->username) + 1;
    710  switch (obj->addr) {
    711 
    712    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      result += strlen(obj->socks4a_addr_hostname) + 1;
    970      break;
    971 
    972    default:
    973      break;
    974  }
    975  return result;
    976 }
    977 int
    978 socks4_client_request_clear_errors(socks4_client_request_t *obj)
    979 {
    980  int r = obj->trunnel_error_code_;
    981  obj->trunnel_error_code_ = 0;
    982  return r;
    983 }
    984 ssize_t
    985 socks4_client_request_encode(uint8_t *output, const size_t avail, const socks4_client_request_t *obj)
    986 {
    987  ssize_t result = 0;
    988  size_t written = 0;
    989  uint8_t *ptr = output;
    990  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  if (NULL != (msg = socks4_client_request_check(obj)))
    996    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  trunnel_assert(written <= avail);
   1004  if (avail - written < 1)
   1005    goto truncated;
   1006  trunnel_set_uint8(ptr, (obj->version));
   1007  written += 1; ptr += 1;
   1008 
   1009  /* Encode u8 command IN [CMD_BIND, CMD_CONNECT, CMD_RESOLVE, CMD_RESOLVE_PTR] */
   1010  trunnel_assert(written <= avail);
   1011  if (avail - written < 1)
   1012    goto truncated;
   1013  trunnel_set_uint8(ptr, (obj->command));
   1014  written += 1; ptr += 1;
   1015 
   1016  /* Encode u16 port */
   1017  trunnel_assert(written <= avail);
   1018  if (avail - written < 2)
   1019    goto truncated;
   1020  trunnel_set_uint16(ptr, trunnel_htons(obj->port));
   1021  written += 2; ptr += 2;
   1022 
   1023  /* Encode u32 addr */
   1024  trunnel_assert(written <= avail);
   1025  if (avail - written < 4)
   1026    goto truncated;
   1027  trunnel_set_uint32(ptr, trunnel_htonl(obj->addr));
   1028  written += 4; ptr += 4;
   1029 
   1030  /* Encode nulterm username */
   1031  {
   1032    size_t len = strlen(obj->username);
   1033    trunnel_assert(written <= avail);
   1034    if (avail - written < len + 1)
   1035      goto truncated;
   1036    memcpy(ptr, obj->username, len + 1);
   1037    ptr += len + 1; written += len + 1;
   1038  }
   1039 
   1040  /* Encode union socks4a_addr[addr] */
   1041  trunnel_assert(written <= avail);
   1042  switch (obj->addr) {
   1043 
   1044    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        size_t len = strlen(obj->socks4a_addr_hostname);
   1303        trunnel_assert(written <= avail);
   1304        if (avail - written < len + 1)
   1305          goto truncated;
   1306        memcpy(ptr, obj->socks4a_addr_hostname, len + 1);
   1307        ptr += len + 1; written += len + 1;
   1308      }
   1309      break;
   1310 
   1311    default:
   1312      break;
   1313  }
   1314 
   1315 
   1316  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  return written;
   1326 
   1327 truncated:
   1328  result = -2;
   1329  goto fail;
   1330 check_failed:
   1331  (void)msg;
   1332  result = -1;
   1333  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 socks4_client_request_parse_into(socks4_client_request_t *obj, const uint8_t *input, const size_t len_in)
   1344 {
   1345  const uint8_t *ptr = input;
   1346  size_t remaining = len_in;
   1347  ssize_t result = 0;
   1348  (void)result;
   1349 
   1350  /* Parse u8 version IN [4] */
   1351  CHECK_REMAINING(1, truncated);
   1352  obj->version = (trunnel_get_uint8(ptr));
   1353  remaining -= 1; ptr += 1;
   1354  if (! (obj->version == 4))
   1355    goto fail;
   1356 
   1357  /* Parse u8 command IN [CMD_BIND, CMD_CONNECT, CMD_RESOLVE, CMD_RESOLVE_PTR] */
   1358  CHECK_REMAINING(1, truncated);
   1359  obj->command = (trunnel_get_uint8(ptr));
   1360  remaining -= 1; ptr += 1;
   1361  if (! (obj->command == CMD_BIND || obj->command == CMD_CONNECT || obj->command == CMD_RESOLVE || obj->command == CMD_RESOLVE_PTR))
   1362    goto fail;
   1363 
   1364  /* Parse u16 port */
   1365  CHECK_REMAINING(2, truncated);
   1366  obj->port = trunnel_ntohs(trunnel_get_uint16(ptr));
   1367  remaining -= 2; ptr += 2;
   1368 
   1369  /* Parse u32 addr */
   1370  CHECK_REMAINING(4, truncated);
   1371  obj->addr = trunnel_ntohl(trunnel_get_uint32(ptr));
   1372  remaining -= 4; ptr += 4;
   1373 
   1374  /* Parse nulterm username */
   1375  {
   1376    uint8_t *eos = (uint8_t*)memchr(ptr, 0, remaining);
   1377    size_t memlen;
   1378    if (eos == NULL)
   1379      goto truncated;
   1380    trunnel_assert(eos >= ptr);
   1381    trunnel_assert((size_t)(eos - ptr) < SIZE_MAX - 1);
   1382    memlen = ((size_t)(eos - ptr)) + 1;
   1383    if (!(obj->username = trunnel_malloc(memlen)))
   1384      goto fail;
   1385    memcpy(obj->username, ptr, memlen);
   1386    remaining -= memlen; ptr += memlen;
   1387  }
   1388 
   1389  /* Parse union socks4a_addr[addr] */
   1390  switch (obj->addr) {
   1391 
   1392    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        uint8_t *eos = (uint8_t*)memchr(ptr, 0, remaining);
   1651        size_t memlen;
   1652        if (eos == NULL)
   1653          goto truncated;
   1654        trunnel_assert(eos >= ptr);
   1655        trunnel_assert((size_t)(eos - ptr) < SIZE_MAX - 1);
   1656        memlen = ((size_t)(eos - ptr)) + 1;
   1657        if (!(obj->socks4a_addr_hostname = trunnel_malloc(memlen)))
   1658          goto fail;
   1659        memcpy(obj->socks4a_addr_hostname, ptr, memlen);
   1660        remaining -= memlen; ptr += memlen;
   1661      }
   1662      break;
   1663 
   1664    default:
   1665      break;
   1666  }
   1667  trunnel_assert(ptr + remaining == input + len_in);
   1668  return len_in - remaining;
   1669 
   1670 truncated:
   1671  return -2;
   1672 fail:
   1673  result = -1;
   1674  return result;
   1675 }
   1676 
   1677 ssize_t
   1678 socks4_client_request_parse(socks4_client_request_t **output, const uint8_t *input, const size_t len_in)
   1679 {
   1680  ssize_t result;
   1681  *output = socks4_client_request_new();
   1682  if (NULL == *output)
   1683    return -1;
   1684  result = socks4_client_request_parse_into(*output, input, len_in);
   1685  if (result < 0) {
   1686    socks4_client_request_free(*output);
   1687    *output = NULL;
   1688  }
   1689  return result;
   1690 }
   1691 socks4_server_reply_t *
   1692 socks4_server_reply_new(void)
   1693 {
   1694  socks4_server_reply_t *val = trunnel_calloc(1, sizeof(socks4_server_reply_t));
   1695  if (NULL == val)
   1696    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 socks4_server_reply_free(socks4_server_reply_t *obj)
   1710 {
   1711  if (obj == NULL)
   1712    return;
   1713  socks4_server_reply_clear(obj);
   1714  trunnel_memwipe(obj, sizeof(socks4_server_reply_t));
   1715  trunnel_free_(obj);
   1716 }
   1717 
   1718 uint8_t
   1719 socks4_server_reply_get_version(const socks4_server_reply_t *inp)
   1720 {
   1721  return inp->version;
   1722 }
   1723 int
   1724 socks4_server_reply_set_version(socks4_server_reply_t *inp, uint8_t val)
   1725 {
   1726  if (! ((val == 0 || val == 4))) {
   1727     TRUNNEL_SET_ERROR_CODE(inp);
   1728     return -1;
   1729  }
   1730  inp->version = val;
   1731  return 0;
   1732 }
   1733 uint8_t
   1734 socks4_server_reply_get_status(const socks4_server_reply_t *inp)
   1735 {
   1736  return inp->status;
   1737 }
   1738 int
   1739 socks4_server_reply_set_status(socks4_server_reply_t *inp, uint8_t val)
   1740 {
   1741  inp->status = val;
   1742  return 0;
   1743 }
   1744 uint16_t
   1745 socks4_server_reply_get_port(const socks4_server_reply_t *inp)
   1746 {
   1747  return inp->port;
   1748 }
   1749 int
   1750 socks4_server_reply_set_port(socks4_server_reply_t *inp, uint16_t val)
   1751 {
   1752  inp->port = val;
   1753  return 0;
   1754 }
   1755 uint32_t
   1756 socks4_server_reply_get_addr(const socks4_server_reply_t *inp)
   1757 {
   1758  return inp->addr;
   1759 }
   1760 int
   1761 socks4_server_reply_set_addr(socks4_server_reply_t *inp, uint32_t val)
   1762 {
   1763  inp->addr = val;
   1764  return 0;
   1765 }
   1766 const char *
   1767 socks4_server_reply_check(const socks4_server_reply_t *obj)
   1768 {
   1769  if (obj == NULL)
   1770    return "Object was NULL";
   1771  if (obj->trunnel_error_code_)
   1772    return "A set function failed on this object";
   1773  if (! (obj->version == 0 || obj->version == 4))
   1774    return "Integer out of bounds";
   1775  return NULL;
   1776 }
   1777 
   1778 ssize_t
   1779 socks4_server_reply_encoded_len(const socks4_server_reply_t *obj)
   1780 {
   1781  ssize_t result = 0;
   1782 
   1783  if (NULL != socks4_server_reply_check(obj))
   1784     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  result += 4;
   1798  return result;
   1799 }
   1800 int
   1801 socks4_server_reply_clear_errors(socks4_server_reply_t *obj)
   1802 {
   1803  int r = obj->trunnel_error_code_;
   1804  obj->trunnel_error_code_ = 0;
   1805  return r;
   1806 }
   1807 ssize_t
   1808 socks4_server_reply_encode(uint8_t *output, const size_t avail, const socks4_server_reply_t *obj)
   1809 {
   1810  ssize_t result = 0;
   1811  size_t written = 0;
   1812  uint8_t *ptr = output;
   1813  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  if (NULL != (msg = socks4_server_reply_check(obj)))
   1819    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  trunnel_assert(written <= avail);
   1827  if (avail - written < 1)
   1828    goto truncated;
   1829  trunnel_set_uint8(ptr, (obj->version));
   1830  written += 1; ptr += 1;
   1831 
   1832  /* Encode u8 status */
   1833  trunnel_assert(written <= avail);
   1834  if (avail - written < 1)
   1835    goto truncated;
   1836  trunnel_set_uint8(ptr, (obj->status));
   1837  written += 1; ptr += 1;
   1838 
   1839  /* Encode u16 port */
   1840  trunnel_assert(written <= avail);
   1841  if (avail - written < 2)
   1842    goto truncated;
   1843  trunnel_set_uint16(ptr, trunnel_htons(obj->port));
   1844  written += 2; ptr += 2;
   1845 
   1846  /* Encode u32 addr */
   1847  trunnel_assert(written <= avail);
   1848  if (avail - written < 4)
   1849    goto truncated;
   1850  trunnel_set_uint32(ptr, trunnel_htonl(obj->addr));
   1851  written += 4; ptr += 4;
   1852 
   1853 
   1854  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 truncated:
   1866  result = -2;
   1867  goto fail;
   1868 check_failed:
   1869  (void)msg;
   1870  result = -1;
   1871  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 socks4_server_reply_parse_into(socks4_server_reply_t *obj, const uint8_t *input, const size_t len_in)
   1882 {
   1883  const uint8_t *ptr = input;
   1884  size_t remaining = len_in;
   1885  ssize_t result = 0;
   1886  (void)result;
   1887 
   1888  /* Parse u8 version IN [0, 4] */
   1889  CHECK_REMAINING(1, truncated);
   1890  obj->version = (trunnel_get_uint8(ptr));
   1891  remaining -= 1; ptr += 1;
   1892  if (! (obj->version == 0 || obj->version == 4))
   1893    goto fail;
   1894 
   1895  /* Parse u8 status */
   1896  CHECK_REMAINING(1, truncated);
   1897  obj->status = (trunnel_get_uint8(ptr));
   1898  remaining -= 1; ptr += 1;
   1899 
   1900  /* Parse u16 port */
   1901  CHECK_REMAINING(2, truncated);
   1902  obj->port = trunnel_ntohs(trunnel_get_uint16(ptr));
   1903  remaining -= 2; ptr += 2;
   1904 
   1905  /* Parse u32 addr */
   1906  CHECK_REMAINING(4, truncated);
   1907  obj->addr = trunnel_ntohl(trunnel_get_uint32(ptr));
   1908  remaining -= 4; ptr += 4;
   1909  trunnel_assert(ptr + remaining == input + len_in);
   1910  return len_in - remaining;
   1911 
   1912 truncated:
   1913  return -2;
   1914 fail:
   1915  result = -1;
   1916  return result;
   1917 }
   1918 
   1919 ssize_t
   1920 socks4_server_reply_parse(socks4_server_reply_t **output, const uint8_t *input, const size_t len_in)
   1921 {
   1922  ssize_t result;
   1923  *output = socks4_server_reply_new();
   1924  if (NULL == *output)
   1925    return -1;
   1926  result = socks4_server_reply_parse_into(*output, input, len_in);
   1927  if (result < 0) {
   1928    socks4_server_reply_free(*output);
   1929    *output = NULL;
   1930  }
   1931  return result;
   1932 }
   1933 socks5_client_userpass_auth_t *
   1934 socks5_client_userpass_auth_new(void)
   1935 {
   1936  socks5_client_userpass_auth_t *val = trunnel_calloc(1, sizeof(socks5_client_userpass_auth_t));
   1937  if (NULL == val)
   1938    return NULL;
   1939  val->version = 1;
   1940  return val;
   1941 }
   1942 
   1943 /** Release all storage held inside 'obj', but do not free 'obj'.
   1944 */
   1945 static void
   1946 socks5_client_userpass_auth_clear(socks5_client_userpass_auth_t *obj)
   1947 {
   1948  (void) obj;
   1949  TRUNNEL_DYNARRAY_WIPE(&obj->username);
   1950  TRUNNEL_DYNARRAY_CLEAR(&obj->username);
   1951  TRUNNEL_DYNARRAY_WIPE(&obj->passwd);
   1952  TRUNNEL_DYNARRAY_CLEAR(&obj->passwd);
   1953 }
   1954 
   1955 void
   1956 socks5_client_userpass_auth_free(socks5_client_userpass_auth_t *obj)
   1957 {
   1958  if (obj == NULL)
   1959    return;
   1960  socks5_client_userpass_auth_clear(obj);
   1961  trunnel_memwipe(obj, sizeof(socks5_client_userpass_auth_t));
   1962  trunnel_free_(obj);
   1963 }
   1964 
   1965 uint8_t
   1966 socks5_client_userpass_auth_get_version(const socks5_client_userpass_auth_t *inp)
   1967 {
   1968  return inp->version;
   1969 }
   1970 int
   1971 socks5_client_userpass_auth_set_version(socks5_client_userpass_auth_t *inp, uint8_t val)
   1972 {
   1973  if (! ((val == 1))) {
   1974     TRUNNEL_SET_ERROR_CODE(inp);
   1975     return -1;
   1976  }
   1977  inp->version = val;
   1978  return 0;
   1979 }
   1980 uint8_t
   1981 socks5_client_userpass_auth_get_username_len(const socks5_client_userpass_auth_t *inp)
   1982 {
   1983  return inp->username_len;
   1984 }
   1985 int
   1986 socks5_client_userpass_auth_set_username_len(socks5_client_userpass_auth_t *inp, uint8_t val)
   1987 {
   1988  inp->username_len = val;
   1989  return 0;
   1990 }
   1991 size_t
   1992 socks5_client_userpass_auth_getlen_username(const socks5_client_userpass_auth_t *inp)
   1993 {
   1994  return TRUNNEL_DYNARRAY_LEN(&inp->username);
   1995 }
   1996 
   1997 char
   1998 socks5_client_userpass_auth_get_username(socks5_client_userpass_auth_t *inp, size_t idx)
   1999 {
   2000  return TRUNNEL_DYNARRAY_GET(&inp->username, idx);
   2001 }
   2002 
   2003 char
   2004 socks5_client_userpass_auth_getconst_username(const socks5_client_userpass_auth_t *inp, size_t idx)
   2005 {
   2006  return socks5_client_userpass_auth_get_username((socks5_client_userpass_auth_t*)inp, idx);
   2007 }
   2008 int
   2009 socks5_client_userpass_auth_set_username(socks5_client_userpass_auth_t *inp, size_t idx, char elt)
   2010 {
   2011  TRUNNEL_DYNARRAY_SET(&inp->username, idx, elt);
   2012  return 0;
   2013 }
   2014 int
   2015 socks5_client_userpass_auth_add_username(socks5_client_userpass_auth_t *inp, char elt)
   2016 {
   2017 #if SIZE_MAX >= UINT8_MAX
   2018  if (inp->username.n_ == UINT8_MAX)
   2019    goto trunnel_alloc_failed;
   2020 #endif
   2021  TRUNNEL_DYNARRAY_ADD(char, &inp->username, elt, {});
   2022  return 0;
   2023 trunnel_alloc_failed:
   2024  TRUNNEL_SET_ERROR_CODE(inp);
   2025  return -1;
   2026 }
   2027 
   2028 char *
   2029 socks5_client_userpass_auth_getarray_username(socks5_client_userpass_auth_t *inp)
   2030 {
   2031  return inp->username.elts_;
   2032 }
   2033 const char  *
   2034 socks5_client_userpass_auth_getconstarray_username(const socks5_client_userpass_auth_t *inp)
   2035 {
   2036  return (const char  *)socks5_client_userpass_auth_getarray_username((socks5_client_userpass_auth_t*)inp);
   2037 }
   2038 int
   2039 socks5_client_userpass_auth_setlen_username(socks5_client_userpass_auth_t *inp, size_t newlen)
   2040 {
   2041 #if UINT8_MAX < SIZE_MAX
   2042  if (newlen > UINT8_MAX)
   2043    goto trunnel_alloc_failed;
   2044 #endif
   2045  return trunnel_string_setlen(&inp->username, newlen,
   2046            &inp->trunnel_error_code_);
   2047 trunnel_alloc_failed:
   2048  TRUNNEL_SET_ERROR_CODE(inp);
   2049  return -1;
   2050 }
   2051 const char *
   2052 socks5_client_userpass_auth_getstr_username(socks5_client_userpass_auth_t *inp)
   2053 {
   2054  return trunnel_string_getstr(&inp->username);
   2055 }
   2056 int
   2057 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  if (len > UINT8_MAX) {
   2061    TRUNNEL_SET_ERROR_CODE(inp);
   2062    return -1;
   2063  }
   2064 #endif
   2065  return trunnel_string_setstr0(&inp->username, val, len, &inp->trunnel_error_code_);
   2066 }
   2067 int
   2068 socks5_client_userpass_auth_setstr_username(socks5_client_userpass_auth_t *inp, const char *val)
   2069 {
   2070  return socks5_client_userpass_auth_setstr0_username(inp, val, strlen(val));
   2071 }
   2072 uint8_t
   2073 socks5_client_userpass_auth_get_passwd_len(const socks5_client_userpass_auth_t *inp)
   2074 {
   2075  return inp->passwd_len;
   2076 }
   2077 int
   2078 socks5_client_userpass_auth_set_passwd_len(socks5_client_userpass_auth_t *inp, uint8_t val)
   2079 {
   2080  inp->passwd_len = val;
   2081  return 0;
   2082 }
   2083 size_t
   2084 socks5_client_userpass_auth_getlen_passwd(const socks5_client_userpass_auth_t *inp)
   2085 {
   2086  return TRUNNEL_DYNARRAY_LEN(&inp->passwd);
   2087 }
   2088 
   2089 char
   2090 socks5_client_userpass_auth_get_passwd(socks5_client_userpass_auth_t *inp, size_t idx)
   2091 {
   2092  return TRUNNEL_DYNARRAY_GET(&inp->passwd, idx);
   2093 }
   2094 
   2095 char
   2096 socks5_client_userpass_auth_getconst_passwd(const socks5_client_userpass_auth_t *inp, size_t idx)
   2097 {
   2098  return socks5_client_userpass_auth_get_passwd((socks5_client_userpass_auth_t*)inp, idx);
   2099 }
   2100 int
   2101 socks5_client_userpass_auth_set_passwd(socks5_client_userpass_auth_t *inp, size_t idx, char elt)
   2102 {
   2103  TRUNNEL_DYNARRAY_SET(&inp->passwd, idx, elt);
   2104  return 0;
   2105 }
   2106 int
   2107 socks5_client_userpass_auth_add_passwd(socks5_client_userpass_auth_t *inp, char elt)
   2108 {
   2109 #if SIZE_MAX >= UINT8_MAX
   2110  if (inp->passwd.n_ == UINT8_MAX)
   2111    goto trunnel_alloc_failed;
   2112 #endif
   2113  TRUNNEL_DYNARRAY_ADD(char, &inp->passwd, elt, {});
   2114  return 0;
   2115 trunnel_alloc_failed:
   2116  TRUNNEL_SET_ERROR_CODE(inp);
   2117  return -1;
   2118 }
   2119 
   2120 char *
   2121 socks5_client_userpass_auth_getarray_passwd(socks5_client_userpass_auth_t *inp)
   2122 {
   2123  return inp->passwd.elts_;
   2124 }
   2125 const char  *
   2126 socks5_client_userpass_auth_getconstarray_passwd(const socks5_client_userpass_auth_t *inp)
   2127 {
   2128  return (const char  *)socks5_client_userpass_auth_getarray_passwd((socks5_client_userpass_auth_t*)inp);
   2129 }
   2130 int
   2131 socks5_client_userpass_auth_setlen_passwd(socks5_client_userpass_auth_t *inp, size_t newlen)
   2132 {
   2133 #if UINT8_MAX < SIZE_MAX
   2134  if (newlen > UINT8_MAX)
   2135    goto trunnel_alloc_failed;
   2136 #endif
   2137  return trunnel_string_setlen(&inp->passwd, newlen,
   2138            &inp->trunnel_error_code_);
   2139 trunnel_alloc_failed:
   2140  TRUNNEL_SET_ERROR_CODE(inp);
   2141  return -1;
   2142 }
   2143 const char *
   2144 socks5_client_userpass_auth_getstr_passwd(socks5_client_userpass_auth_t *inp)
   2145 {
   2146  return trunnel_string_getstr(&inp->passwd);
   2147 }
   2148 int
   2149 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  if (len > UINT8_MAX) {
   2153    TRUNNEL_SET_ERROR_CODE(inp);
   2154    return -1;
   2155  }
   2156 #endif
   2157  return trunnel_string_setstr0(&inp->passwd, val, len, &inp->trunnel_error_code_);
   2158 }
   2159 int
   2160 socks5_client_userpass_auth_setstr_passwd(socks5_client_userpass_auth_t *inp, const char *val)
   2161 {
   2162  return socks5_client_userpass_auth_setstr0_passwd(inp, val, strlen(val));
   2163 }
   2164 const char *
   2165 socks5_client_userpass_auth_check(const socks5_client_userpass_auth_t *obj)
   2166 {
   2167  if (obj == NULL)
   2168    return "Object was NULL";
   2169  if (obj->trunnel_error_code_)
   2170    return "A set function failed on this object";
   2171  if (! (obj->version == 1))
   2172    return "Integer out of bounds";
   2173  if (TRUNNEL_DYNARRAY_LEN(&obj->username) != obj->username_len)
   2174    return "Length mismatch for username";
   2175  if (TRUNNEL_DYNARRAY_LEN(&obj->passwd) != obj->passwd_len)
   2176    return "Length mismatch for passwd";
   2177  return NULL;
   2178 }
   2179 
   2180 ssize_t
   2181 socks5_client_userpass_auth_encoded_len(const socks5_client_userpass_auth_t *obj)
   2182 {
   2183  ssize_t result = 0;
   2184 
   2185  if (NULL != socks5_client_userpass_auth_check(obj))
   2186     return -1;
   2187 
   2188 
   2189  /* Length of u8 version IN [1] */
   2190  result += 1;
   2191 
   2192  /* Length of u8 username_len */
   2193  result += 1;
   2194 
   2195  /* Length of char username[username_len] */
   2196  result += TRUNNEL_DYNARRAY_LEN(&obj->username);
   2197 
   2198  /* Length of u8 passwd_len */
   2199  result += 1;
   2200 
   2201  /* Length of char passwd[passwd_len] */
   2202  result += TRUNNEL_DYNARRAY_LEN(&obj->passwd);
   2203  return result;
   2204 }
   2205 int
   2206 socks5_client_userpass_auth_clear_errors(socks5_client_userpass_auth_t *obj)
   2207 {
   2208  int r = obj->trunnel_error_code_;
   2209  obj->trunnel_error_code_ = 0;
   2210  return r;
   2211 }
   2212 ssize_t
   2213 socks5_client_userpass_auth_encode(uint8_t *output, const size_t avail, const socks5_client_userpass_auth_t *obj)
   2214 {
   2215  ssize_t result = 0;
   2216  size_t written = 0;
   2217  uint8_t *ptr = output;
   2218  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  if (NULL != (msg = socks5_client_userpass_auth_check(obj)))
   2224    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  trunnel_assert(written <= avail);
   2232  if (avail - written < 1)
   2233    goto truncated;
   2234  trunnel_set_uint8(ptr, (obj->version));
   2235  written += 1; ptr += 1;
   2236 
   2237  /* Encode u8 username_len */
   2238  trunnel_assert(written <= avail);
   2239  if (avail - written < 1)
   2240    goto truncated;
   2241  trunnel_set_uint8(ptr, (obj->username_len));
   2242  written += 1; ptr += 1;
   2243 
   2244  /* Encode char username[username_len] */
   2245  {
   2246    size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->username);
   2247    trunnel_assert(obj->username_len == elt_len);
   2248    trunnel_assert(written <= avail);
   2249    if (avail - written < elt_len)
   2250      goto truncated;
   2251    if (elt_len)
   2252      memcpy(ptr, obj->username.elts_, elt_len);
   2253    written += elt_len; ptr += elt_len;
   2254  }
   2255 
   2256  /* Encode u8 passwd_len */
   2257  trunnel_assert(written <= avail);
   2258  if (avail - written < 1)
   2259    goto truncated;
   2260  trunnel_set_uint8(ptr, (obj->passwd_len));
   2261  written += 1; ptr += 1;
   2262 
   2263  /* Encode char passwd[passwd_len] */
   2264  {
   2265    size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->passwd);
   2266    trunnel_assert(obj->passwd_len == elt_len);
   2267    trunnel_assert(written <= avail);
   2268    if (avail - written < elt_len)
   2269      goto truncated;
   2270    if (elt_len)
   2271      memcpy(ptr, obj->passwd.elts_, elt_len);
   2272    written += elt_len; ptr += elt_len;
   2273  }
   2274 
   2275 
   2276  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  return written;
   2286 
   2287 truncated:
   2288  result = -2;
   2289  goto fail;
   2290 check_failed:
   2291  (void)msg;
   2292  result = -1;
   2293  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 socks5_client_userpass_auth_parse_into(socks5_client_userpass_auth_t *obj, const uint8_t *input, const size_t len_in)
   2304 {
   2305  const uint8_t *ptr = input;
   2306  size_t remaining = len_in;
   2307  ssize_t result = 0;
   2308  (void)result;
   2309 
   2310  /* Parse u8 version IN [1] */
   2311  CHECK_REMAINING(1, truncated);
   2312  obj->version = (trunnel_get_uint8(ptr));
   2313  remaining -= 1; ptr += 1;
   2314  if (! (obj->version == 1))
   2315    goto fail;
   2316 
   2317  /* Parse u8 username_len */
   2318  CHECK_REMAINING(1, truncated);
   2319  obj->username_len = (trunnel_get_uint8(ptr));
   2320  remaining -= 1; ptr += 1;
   2321 
   2322  /* Parse char username[username_len] */
   2323  CHECK_REMAINING(obj->username_len, truncated);
   2324  if (socks5_client_userpass_auth_setstr0_username(obj, (const char*)ptr, obj->username_len))
   2325    goto fail;
   2326  ptr += obj->username_len; remaining -= obj->username_len;
   2327 
   2328  /* Parse u8 passwd_len */
   2329  CHECK_REMAINING(1, truncated);
   2330  obj->passwd_len = (trunnel_get_uint8(ptr));
   2331  remaining -= 1; ptr += 1;
   2332 
   2333  /* Parse char passwd[passwd_len] */
   2334  CHECK_REMAINING(obj->passwd_len, truncated);
   2335  if (socks5_client_userpass_auth_setstr0_passwd(obj, (const char*)ptr, obj->passwd_len))
   2336    goto fail;
   2337  ptr += obj->passwd_len; remaining -= obj->passwd_len;
   2338  trunnel_assert(ptr + remaining == input + len_in);
   2339  return len_in - remaining;
   2340 
   2341 truncated:
   2342  return -2;
   2343 fail:
   2344  result = -1;
   2345  return result;
   2346 }
   2347 
   2348 ssize_t
   2349 socks5_client_userpass_auth_parse(socks5_client_userpass_auth_t **output, const uint8_t *input, const size_t len_in)
   2350 {
   2351  ssize_t result;
   2352  *output = socks5_client_userpass_auth_new();
   2353  if (NULL == *output)
   2354    return -1;
   2355  result = socks5_client_userpass_auth_parse_into(*output, input, len_in);
   2356  if (result < 0) {
   2357    socks5_client_userpass_auth_free(*output);
   2358    *output = NULL;
   2359  }
   2360  return result;
   2361 }
   2362 socks5_client_version_t *
   2363 socks5_client_version_new(void)
   2364 {
   2365  socks5_client_version_t *val = trunnel_calloc(1, sizeof(socks5_client_version_t));
   2366  if (NULL == val)
   2367    return NULL;
   2368  val->version = 5;
   2369  return val;
   2370 }
   2371 
   2372 /** Release all storage held inside 'obj', but do not free 'obj'.
   2373 */
   2374 static void
   2375 socks5_client_version_clear(socks5_client_version_t *obj)
   2376 {
   2377  (void) obj;
   2378  TRUNNEL_DYNARRAY_WIPE(&obj->methods);
   2379  TRUNNEL_DYNARRAY_CLEAR(&obj->methods);
   2380 }
   2381 
   2382 void
   2383 socks5_client_version_free(socks5_client_version_t *obj)
   2384 {
   2385  if (obj == NULL)
   2386    return;
   2387  socks5_client_version_clear(obj);
   2388  trunnel_memwipe(obj, sizeof(socks5_client_version_t));
   2389  trunnel_free_(obj);
   2390 }
   2391 
   2392 uint8_t
   2393 socks5_client_version_get_version(const socks5_client_version_t *inp)
   2394 {
   2395  return inp->version;
   2396 }
   2397 int
   2398 socks5_client_version_set_version(socks5_client_version_t *inp, uint8_t val)
   2399 {
   2400  if (! ((val == 5))) {
   2401     TRUNNEL_SET_ERROR_CODE(inp);
   2402     return -1;
   2403  }
   2404  inp->version = val;
   2405  return 0;
   2406 }
   2407 uint8_t
   2408 socks5_client_version_get_n_methods(const socks5_client_version_t *inp)
   2409 {
   2410  return inp->n_methods;
   2411 }
   2412 int
   2413 socks5_client_version_set_n_methods(socks5_client_version_t *inp, uint8_t val)
   2414 {
   2415  inp->n_methods = val;
   2416  return 0;
   2417 }
   2418 size_t
   2419 socks5_client_version_getlen_methods(const socks5_client_version_t *inp)
   2420 {
   2421  return TRUNNEL_DYNARRAY_LEN(&inp->methods);
   2422 }
   2423 
   2424 uint8_t
   2425 socks5_client_version_get_methods(socks5_client_version_t *inp, size_t idx)
   2426 {
   2427  return TRUNNEL_DYNARRAY_GET(&inp->methods, idx);
   2428 }
   2429 
   2430 uint8_t
   2431 socks5_client_version_getconst_methods(const socks5_client_version_t *inp, size_t idx)
   2432 {
   2433  return socks5_client_version_get_methods((socks5_client_version_t*)inp, idx);
   2434 }
   2435 int
   2436 socks5_client_version_set_methods(socks5_client_version_t *inp, size_t idx, uint8_t elt)
   2437 {
   2438  TRUNNEL_DYNARRAY_SET(&inp->methods, idx, elt);
   2439  return 0;
   2440 }
   2441 int
   2442 socks5_client_version_add_methods(socks5_client_version_t *inp, uint8_t elt)
   2443 {
   2444 #if SIZE_MAX >= UINT8_MAX
   2445  if (inp->methods.n_ == UINT8_MAX)
   2446    goto trunnel_alloc_failed;
   2447 #endif
   2448  TRUNNEL_DYNARRAY_ADD(uint8_t, &inp->methods, elt, {});
   2449  return 0;
   2450 trunnel_alloc_failed:
   2451  TRUNNEL_SET_ERROR_CODE(inp);
   2452  return -1;
   2453 }
   2454 
   2455 uint8_t *
   2456 socks5_client_version_getarray_methods(socks5_client_version_t *inp)
   2457 {
   2458  return inp->methods.elts_;
   2459 }
   2460 const uint8_t  *
   2461 socks5_client_version_getconstarray_methods(const socks5_client_version_t *inp)
   2462 {
   2463  return (const uint8_t  *)socks5_client_version_getarray_methods((socks5_client_version_t*)inp);
   2464 }
   2465 int
   2466 socks5_client_version_setlen_methods(socks5_client_version_t *inp, size_t newlen)
   2467 {
   2468  uint8_t *newptr;
   2469 #if UINT8_MAX < SIZE_MAX
   2470  if (newlen > UINT8_MAX)
   2471    goto trunnel_alloc_failed;
   2472 #endif
   2473  newptr = trunnel_dynarray_setlen(&inp->methods.allocated_,
   2474                 &inp->methods.n_, inp->methods.elts_, newlen,
   2475                 sizeof(inp->methods.elts_[0]), (trunnel_free_fn_t) NULL,
   2476                 &inp->trunnel_error_code_);
   2477  if (newlen != 0 && newptr == NULL)
   2478    goto trunnel_alloc_failed;
   2479  inp->methods.elts_ = newptr;
   2480  return 0;
   2481 trunnel_alloc_failed:
   2482  TRUNNEL_SET_ERROR_CODE(inp);
   2483  return -1;
   2484 }
   2485 const char *
   2486 socks5_client_version_check(const socks5_client_version_t *obj)
   2487 {
   2488  if (obj == NULL)
   2489    return "Object was NULL";
   2490  if (obj->trunnel_error_code_)
   2491    return "A set function failed on this object";
   2492  if (! (obj->version == 5))
   2493    return "Integer out of bounds";
   2494  if (TRUNNEL_DYNARRAY_LEN(&obj->methods) != obj->n_methods)
   2495    return "Length mismatch for methods";
   2496  return NULL;
   2497 }
   2498 
   2499 ssize_t
   2500 socks5_client_version_encoded_len(const socks5_client_version_t *obj)
   2501 {
   2502  ssize_t result = 0;
   2503 
   2504  if (NULL != socks5_client_version_check(obj))
   2505     return -1;
   2506 
   2507 
   2508  /* Length of u8 version IN [5] */
   2509  result += 1;
   2510 
   2511  /* Length of u8 n_methods */
   2512  result += 1;
   2513 
   2514  /* Length of u8 methods[n_methods] */
   2515  result += TRUNNEL_DYNARRAY_LEN(&obj->methods);
   2516  return result;
   2517 }
   2518 int
   2519 socks5_client_version_clear_errors(socks5_client_version_t *obj)
   2520 {
   2521  int r = obj->trunnel_error_code_;
   2522  obj->trunnel_error_code_ = 0;
   2523  return r;
   2524 }
   2525 ssize_t
   2526 socks5_client_version_encode(uint8_t *output, const size_t avail, const socks5_client_version_t *obj)
   2527 {
   2528  ssize_t result = 0;
   2529  size_t written = 0;
   2530  uint8_t *ptr = output;
   2531  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  if (NULL != (msg = socks5_client_version_check(obj)))
   2537    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  trunnel_assert(written <= avail);
   2545  if (avail - written < 1)
   2546    goto truncated;
   2547  trunnel_set_uint8(ptr, (obj->version));
   2548  written += 1; ptr += 1;
   2549 
   2550  /* Encode u8 n_methods */
   2551  trunnel_assert(written <= avail);
   2552  if (avail - written < 1)
   2553    goto truncated;
   2554  trunnel_set_uint8(ptr, (obj->n_methods));
   2555  written += 1; ptr += 1;
   2556 
   2557  /* Encode u8 methods[n_methods] */
   2558  {
   2559    size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->methods);
   2560    trunnel_assert(obj->n_methods == elt_len);
   2561    trunnel_assert(written <= avail);
   2562    if (avail - written < elt_len)
   2563      goto truncated;
   2564    if (elt_len)
   2565      memcpy(ptr, obj->methods.elts_, elt_len);
   2566    written += elt_len; ptr += elt_len;
   2567  }
   2568 
   2569 
   2570  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  return written;
   2580 
   2581 truncated:
   2582  result = -2;
   2583  goto fail;
   2584 check_failed:
   2585  (void)msg;
   2586  result = -1;
   2587  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 socks5_client_version_parse_into(socks5_client_version_t *obj, const uint8_t *input, const size_t len_in)
   2598 {
   2599  const uint8_t *ptr = input;
   2600  size_t remaining = len_in;
   2601  ssize_t result = 0;
   2602  (void)result;
   2603 
   2604  /* Parse u8 version IN [5] */
   2605  CHECK_REMAINING(1, truncated);
   2606  obj->version = (trunnel_get_uint8(ptr));
   2607  remaining -= 1; ptr += 1;
   2608  if (! (obj->version == 5))
   2609    goto fail;
   2610 
   2611  /* Parse u8 n_methods */
   2612  CHECK_REMAINING(1, truncated);
   2613  obj->n_methods = (trunnel_get_uint8(ptr));
   2614  remaining -= 1; ptr += 1;
   2615 
   2616  /* Parse u8 methods[n_methods] */
   2617  CHECK_REMAINING(obj->n_methods, truncated);
   2618  TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->methods, obj->n_methods, {});
   2619  obj->methods.n_ = obj->n_methods;
   2620  if (obj->n_methods)
   2621    memcpy(obj->methods.elts_, ptr, obj->n_methods);
   2622  ptr += obj->n_methods; remaining -= obj->n_methods;
   2623  trunnel_assert(ptr + remaining == input + len_in);
   2624  return len_in - remaining;
   2625 
   2626 truncated:
   2627  return -2;
   2628 trunnel_alloc_failed:
   2629  return -1;
   2630 fail:
   2631  result = -1;
   2632  return result;
   2633 }
   2634 
   2635 ssize_t
   2636 socks5_client_version_parse(socks5_client_version_t **output, const uint8_t *input, const size_t len_in)
   2637 {
   2638  ssize_t result;
   2639  *output = socks5_client_version_new();
   2640  if (NULL == *output)
   2641    return -1;
   2642  result = socks5_client_version_parse_into(*output, input, len_in);
   2643  if (result < 0) {
   2644    socks5_client_version_free(*output);
   2645    *output = NULL;
   2646  }
   2647  return result;
   2648 }
   2649 socks5_server_method_t *
   2650 socks5_server_method_new(void)
   2651 {
   2652  socks5_server_method_t *val = trunnel_calloc(1, sizeof(socks5_server_method_t));
   2653  if (NULL == val)
   2654    return NULL;
   2655  val->version = 5;
   2656  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 socks5_server_method_free(socks5_server_method_t *obj)
   2669 {
   2670  if (obj == NULL)
   2671    return;
   2672  socks5_server_method_clear(obj);
   2673  trunnel_memwipe(obj, sizeof(socks5_server_method_t));
   2674  trunnel_free_(obj);
   2675 }
   2676 
   2677 uint8_t
   2678 socks5_server_method_get_version(const socks5_server_method_t *inp)
   2679 {
   2680  return inp->version;
   2681 }
   2682 int
   2683 socks5_server_method_set_version(socks5_server_method_t *inp, uint8_t val)
   2684 {
   2685  if (! ((val == 5))) {
   2686     TRUNNEL_SET_ERROR_CODE(inp);
   2687     return -1;
   2688  }
   2689  inp->version = val;
   2690  return 0;
   2691 }
   2692 uint8_t
   2693 socks5_server_method_get_method(const socks5_server_method_t *inp)
   2694 {
   2695  return inp->method;
   2696 }
   2697 int
   2698 socks5_server_method_set_method(socks5_server_method_t *inp, uint8_t val)
   2699 {
   2700  inp->method = val;
   2701  return 0;
   2702 }
   2703 const char *
   2704 socks5_server_method_check(const socks5_server_method_t *obj)
   2705 {
   2706  if (obj == NULL)
   2707    return "Object was NULL";
   2708  if (obj->trunnel_error_code_)
   2709    return "A set function failed on this object";
   2710  if (! (obj->version == 5))
   2711    return "Integer out of bounds";
   2712  return NULL;
   2713 }
   2714 
   2715 ssize_t
   2716 socks5_server_method_encoded_len(const socks5_server_method_t *obj)
   2717 {
   2718  ssize_t result = 0;
   2719 
   2720  if (NULL != socks5_server_method_check(obj))
   2721     return -1;
   2722 
   2723 
   2724  /* Length of u8 version IN [5] */
   2725  result += 1;
   2726 
   2727  /* Length of u8 method */
   2728  result += 1;
   2729  return result;
   2730 }
   2731 int
   2732 socks5_server_method_clear_errors(socks5_server_method_t *obj)
   2733 {
   2734  int r = obj->trunnel_error_code_;
   2735  obj->trunnel_error_code_ = 0;
   2736  return r;
   2737 }
   2738 ssize_t
   2739 socks5_server_method_encode(uint8_t *output, const size_t avail, const socks5_server_method_t *obj)
   2740 {
   2741  ssize_t result = 0;
   2742  size_t written = 0;
   2743  uint8_t *ptr = output;
   2744  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  if (NULL != (msg = socks5_server_method_check(obj)))
   2750    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  trunnel_assert(written <= avail);
   2758  if (avail - written < 1)
   2759    goto truncated;
   2760  trunnel_set_uint8(ptr, (obj->version));
   2761  written += 1; ptr += 1;
   2762 
   2763  /* Encode u8 method */
   2764  trunnel_assert(written <= avail);
   2765  if (avail - written < 1)
   2766    goto truncated;
   2767  trunnel_set_uint8(ptr, (obj->method));
   2768  written += 1; ptr += 1;
   2769 
   2770 
   2771  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 truncated:
   2783  result = -2;
   2784  goto fail;
   2785 check_failed:
   2786  (void)msg;
   2787  result = -1;
   2788  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 socks5_server_method_parse_into(socks5_server_method_t *obj, const uint8_t *input, const size_t len_in)
   2799 {
   2800  const uint8_t *ptr = input;
   2801  size_t remaining = len_in;
   2802  ssize_t result = 0;
   2803  (void)result;
   2804 
   2805  /* Parse u8 version IN [5] */
   2806  CHECK_REMAINING(1, truncated);
   2807  obj->version = (trunnel_get_uint8(ptr));
   2808  remaining -= 1; ptr += 1;
   2809  if (! (obj->version == 5))
   2810    goto fail;
   2811 
   2812  /* Parse u8 method */
   2813  CHECK_REMAINING(1, truncated);
   2814  obj->method = (trunnel_get_uint8(ptr));
   2815  remaining -= 1; ptr += 1;
   2816  trunnel_assert(ptr + remaining == input + len_in);
   2817  return len_in - remaining;
   2818 
   2819 truncated:
   2820  return -2;
   2821 fail:
   2822  result = -1;
   2823  return result;
   2824 }
   2825 
   2826 ssize_t
   2827 socks5_server_method_parse(socks5_server_method_t **output, const uint8_t *input, const size_t len_in)
   2828 {
   2829  ssize_t result;
   2830  *output = socks5_server_method_new();
   2831  if (NULL == *output)
   2832    return -1;
   2833  result = socks5_server_method_parse_into(*output, input, len_in);
   2834  if (result < 0) {
   2835    socks5_server_method_free(*output);
   2836    *output = NULL;
   2837  }
   2838  return result;
   2839 }
   2840 socks5_server_userpass_auth_t *
   2841 socks5_server_userpass_auth_new(void)
   2842 {
   2843  socks5_server_userpass_auth_t *val = trunnel_calloc(1, sizeof(socks5_server_userpass_auth_t));
   2844  if (NULL == val)
   2845    return NULL;
   2846  val->version = 1;
   2847  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 socks5_server_userpass_auth_free(socks5_server_userpass_auth_t *obj)
   2860 {
   2861  if (obj == NULL)
   2862    return;
   2863  socks5_server_userpass_auth_clear(obj);
   2864  trunnel_memwipe(obj, sizeof(socks5_server_userpass_auth_t));
   2865  trunnel_free_(obj);
   2866 }
   2867 
   2868 uint8_t
   2869 socks5_server_userpass_auth_get_version(const socks5_server_userpass_auth_t *inp)
   2870 {
   2871  return inp->version;
   2872 }
   2873 int
   2874 socks5_server_userpass_auth_set_version(socks5_server_userpass_auth_t *inp, uint8_t val)
   2875 {
   2876  if (! ((val == 1))) {
   2877     TRUNNEL_SET_ERROR_CODE(inp);
   2878     return -1;
   2879  }
   2880  inp->version = val;
   2881  return 0;
   2882 }
   2883 uint8_t
   2884 socks5_server_userpass_auth_get_status(const socks5_server_userpass_auth_t *inp)
   2885 {
   2886  return inp->status;
   2887 }
   2888 int
   2889 socks5_server_userpass_auth_set_status(socks5_server_userpass_auth_t *inp, uint8_t val)
   2890 {
   2891  inp->status = val;
   2892  return 0;
   2893 }
   2894 const char *
   2895 socks5_server_userpass_auth_check(const socks5_server_userpass_auth_t *obj)
   2896 {
   2897  if (obj == NULL)
   2898    return "Object was NULL";
   2899  if (obj->trunnel_error_code_)
   2900    return "A set function failed on this object";
   2901  if (! (obj->version == 1))
   2902    return "Integer out of bounds";
   2903  return NULL;
   2904 }
   2905 
   2906 ssize_t
   2907 socks5_server_userpass_auth_encoded_len(const socks5_server_userpass_auth_t *obj)
   2908 {
   2909  ssize_t result = 0;
   2910 
   2911  if (NULL != socks5_server_userpass_auth_check(obj))
   2912     return -1;
   2913 
   2914 
   2915  /* Length of u8 version IN [1] */
   2916  result += 1;
   2917 
   2918  /* Length of u8 status */
   2919  result += 1;
   2920  return result;
   2921 }
   2922 int
   2923 socks5_server_userpass_auth_clear_errors(socks5_server_userpass_auth_t *obj)
   2924 {
   2925  int r = obj->trunnel_error_code_;
   2926  obj->trunnel_error_code_ = 0;
   2927  return r;
   2928 }
   2929 ssize_t
   2930 socks5_server_userpass_auth_encode(uint8_t *output, const size_t avail, const socks5_server_userpass_auth_t *obj)
   2931 {
   2932  ssize_t result = 0;
   2933  size_t written = 0;
   2934  uint8_t *ptr = output;
   2935  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  if (NULL != (msg = socks5_server_userpass_auth_check(obj)))
   2941    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  trunnel_assert(written <= avail);
   2949  if (avail - written < 1)
   2950    goto truncated;
   2951  trunnel_set_uint8(ptr, (obj->version));
   2952  written += 1; ptr += 1;
   2953 
   2954  /* Encode u8 status */
   2955  trunnel_assert(written <= avail);
   2956  if (avail - written < 1)
   2957    goto truncated;
   2958  trunnel_set_uint8(ptr, (obj->status));
   2959  written += 1; ptr += 1;
   2960 
   2961 
   2962  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 truncated:
   2974  result = -2;
   2975  goto fail;
   2976 check_failed:
   2977  (void)msg;
   2978  result = -1;
   2979  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 socks5_server_userpass_auth_parse_into(socks5_server_userpass_auth_t *obj, const uint8_t *input, const size_t len_in)
   2990 {
   2991  const uint8_t *ptr = input;
   2992  size_t remaining = len_in;
   2993  ssize_t result = 0;
   2994  (void)result;
   2995 
   2996  /* Parse u8 version IN [1] */
   2997  CHECK_REMAINING(1, truncated);
   2998  obj->version = (trunnel_get_uint8(ptr));
   2999  remaining -= 1; ptr += 1;
   3000  if (! (obj->version == 1))
   3001    goto fail;
   3002 
   3003  /* Parse u8 status */
   3004  CHECK_REMAINING(1, truncated);
   3005  obj->status = (trunnel_get_uint8(ptr));
   3006  remaining -= 1; ptr += 1;
   3007  trunnel_assert(ptr + remaining == input + len_in);
   3008  return len_in - remaining;
   3009 
   3010 truncated:
   3011  return -2;
   3012 fail:
   3013  result = -1;
   3014  return result;
   3015 }
   3016 
   3017 ssize_t
   3018 socks5_server_userpass_auth_parse(socks5_server_userpass_auth_t **output, const uint8_t *input, const size_t len_in)
   3019 {
   3020  ssize_t result;
   3021  *output = socks5_server_userpass_auth_new();
   3022  if (NULL == *output)
   3023    return -1;
   3024  result = socks5_server_userpass_auth_parse_into(*output, input, len_in);
   3025  if (result < 0) {
   3026    socks5_server_userpass_auth_free(*output);
   3027    *output = NULL;
   3028  }
   3029  return result;
   3030 }
   3031 socks5_client_request_t *
   3032 socks5_client_request_new(void)
   3033 {
   3034  socks5_client_request_t *val = trunnel_calloc(1, sizeof(socks5_client_request_t));
   3035  if (NULL == val)
   3036    return NULL;
   3037  val->version = 5;
   3038  val->command = CMD_BIND;
   3039  return val;
   3040 }
   3041 
   3042 /** Release all storage held inside 'obj', but do not free 'obj'.
   3043 */
   3044 static void
   3045 socks5_client_request_clear(socks5_client_request_t *obj)
   3046 {
   3047  (void) obj;
   3048  domainname_free(obj->dest_addr_domainname);
   3049  obj->dest_addr_domainname = NULL;
   3050 }
   3051 
   3052 void
   3053 socks5_client_request_free(socks5_client_request_t *obj)
   3054 {
   3055  if (obj == NULL)
   3056    return;
   3057  socks5_client_request_clear(obj);
   3058  trunnel_memwipe(obj, sizeof(socks5_client_request_t));
   3059  trunnel_free_(obj);
   3060 }
   3061 
   3062 uint8_t
   3063 socks5_client_request_get_version(const socks5_client_request_t *inp)
   3064 {
   3065  return inp->version;
   3066 }
   3067 int
   3068 socks5_client_request_set_version(socks5_client_request_t *inp, uint8_t val)
   3069 {
   3070  if (! ((val == 5))) {
   3071     TRUNNEL_SET_ERROR_CODE(inp);
   3072     return -1;
   3073  }
   3074  inp->version = val;
   3075  return 0;
   3076 }
   3077 uint8_t
   3078 socks5_client_request_get_command(const socks5_client_request_t *inp)
   3079 {
   3080  return inp->command;
   3081 }
   3082 int
   3083 socks5_client_request_set_command(socks5_client_request_t *inp, uint8_t val)
   3084 {
   3085  if (! ((val == CMD_BIND || val == CMD_CONNECT || val == CMD_RESOLVE || val == CMD_RESOLVE_PTR || val == CMD_UDP_ASSOCIATE))) {
   3086     TRUNNEL_SET_ERROR_CODE(inp);
   3087     return -1;
   3088  }
   3089  inp->command = val;
   3090  return 0;
   3091 }
   3092 uint8_t
   3093 socks5_client_request_get_reserved(const socks5_client_request_t *inp)
   3094 {
   3095  return inp->reserved;
   3096 }
   3097 int
   3098 socks5_client_request_set_reserved(socks5_client_request_t *inp, uint8_t val)
   3099 {
   3100  if (! ((val == 0))) {
   3101     TRUNNEL_SET_ERROR_CODE(inp);
   3102     return -1;
   3103  }
   3104  inp->reserved = val;
   3105  return 0;
   3106 }
   3107 uint8_t
   3108 socks5_client_request_get_atype(const socks5_client_request_t *inp)
   3109 {
   3110  return inp->atype;
   3111 }
   3112 int
   3113 socks5_client_request_set_atype(socks5_client_request_t *inp, uint8_t val)
   3114 {
   3115  inp->atype = val;
   3116  return 0;
   3117 }
   3118 uint32_t
   3119 socks5_client_request_get_dest_addr_ipv4(const socks5_client_request_t *inp)
   3120 {
   3121  return inp->dest_addr_ipv4;
   3122 }
   3123 int
   3124 socks5_client_request_set_dest_addr_ipv4(socks5_client_request_t *inp, uint32_t val)
   3125 {
   3126  inp->dest_addr_ipv4 = val;
   3127  return 0;
   3128 }
   3129 size_t
   3130 socks5_client_request_getlen_dest_addr_ipv6(const socks5_client_request_t *inp)
   3131 {
   3132  (void)inp;  return 16;
   3133 }
   3134 
   3135 uint8_t
   3136 socks5_client_request_get_dest_addr_ipv6(socks5_client_request_t *inp, size_t idx)
   3137 {
   3138  trunnel_assert(idx < 16);
   3139  return inp->dest_addr_ipv6[idx];
   3140 }
   3141 
   3142 uint8_t
   3143 socks5_client_request_getconst_dest_addr_ipv6(const socks5_client_request_t *inp, size_t idx)
   3144 {
   3145  return socks5_client_request_get_dest_addr_ipv6((socks5_client_request_t*)inp, idx);
   3146 }
   3147 int
   3148 socks5_client_request_set_dest_addr_ipv6(socks5_client_request_t *inp, size_t idx, uint8_t elt)
   3149 {
   3150  trunnel_assert(idx < 16);
   3151  inp->dest_addr_ipv6[idx] = elt;
   3152  return 0;
   3153 }
   3154 
   3155 uint8_t *
   3156 socks5_client_request_getarray_dest_addr_ipv6(socks5_client_request_t *inp)
   3157 {
   3158  return inp->dest_addr_ipv6;
   3159 }
   3160 const uint8_t  *
   3161 socks5_client_request_getconstarray_dest_addr_ipv6(const socks5_client_request_t *inp)
   3162 {
   3163  return (const uint8_t  *)socks5_client_request_getarray_dest_addr_ipv6((socks5_client_request_t*)inp);
   3164 }
   3165 struct domainname_st *
   3166 socks5_client_request_get_dest_addr_domainname(socks5_client_request_t *inp)
   3167 {
   3168  return inp->dest_addr_domainname;
   3169 }
   3170 const struct domainname_st *
   3171 socks5_client_request_getconst_dest_addr_domainname(const socks5_client_request_t *inp)
   3172 {
   3173  return socks5_client_request_get_dest_addr_domainname((socks5_client_request_t*) inp);
   3174 }
   3175 int
   3176 socks5_client_request_set_dest_addr_domainname(socks5_client_request_t *inp, struct domainname_st *val)
   3177 {
   3178  if (inp->dest_addr_domainname && inp->dest_addr_domainname != val)
   3179    domainname_free(inp->dest_addr_domainname);
   3180  return socks5_client_request_set0_dest_addr_domainname(inp, val);
   3181 }
   3182 int
   3183 socks5_client_request_set0_dest_addr_domainname(socks5_client_request_t *inp, struct domainname_st *val)
   3184 {
   3185  inp->dest_addr_domainname = val;
   3186  return 0;
   3187 }
   3188 uint16_t
   3189 socks5_client_request_get_dest_port(const socks5_client_request_t *inp)
   3190 {
   3191  return inp->dest_port;
   3192 }
   3193 int
   3194 socks5_client_request_set_dest_port(socks5_client_request_t *inp, uint16_t val)
   3195 {
   3196  inp->dest_port = val;
   3197  return 0;
   3198 }
   3199 const char *
   3200 socks5_client_request_check(const socks5_client_request_t *obj)
   3201 {
   3202  if (obj == NULL)
   3203    return "Object was NULL";
   3204  if (obj->trunnel_error_code_)
   3205    return "A set function failed on this object";
   3206  if (! (obj->version == 5))
   3207    return "Integer out of bounds";
   3208  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  if (! (obj->reserved == 0))
   3211    return "Integer out of bounds";
   3212  switch (obj->atype) {
   3213 
   3214    case ATYPE_IPV4:
   3215      break;
   3216 
   3217    case ATYPE_IPV6:
   3218      break;
   3219 
   3220    case ATYPE_DOMAINNAME:
   3221      {
   3222        const char *msg;
   3223        if (NULL != (msg = domainname_check(obj->dest_addr_domainname)))
   3224          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 socks5_client_request_encoded_len(const socks5_client_request_t *obj)
   3237 {
   3238  ssize_t result = 0;
   3239 
   3240  if (NULL != socks5_client_request_check(obj))
   3241     return -1;
   3242 
   3243 
   3244  /* Length of u8 version IN [5] */
   3245  result += 1;
   3246 
   3247  /* Length of u8 command IN [CMD_BIND, CMD_CONNECT, CMD_RESOLVE, CMD_RESOLVE_PTR, CMD_UDP_ASSOCIATE] */
   3248  result += 1;
   3249 
   3250  /* Length of u8 reserved IN [0] */
   3251  result += 1;
   3252 
   3253  /* Length of u8 atype */
   3254  result += 1;
   3255  switch (obj->atype) {
   3256 
   3257    case ATYPE_IPV4:
   3258 
   3259      /* Length of u32 dest_addr_ipv4 */
   3260      result += 4;
   3261      break;
   3262 
   3263    case ATYPE_IPV6:
   3264 
   3265      /* Length of u8 dest_addr_ipv6[16] */
   3266      result += 16;
   3267      break;
   3268 
   3269    case ATYPE_DOMAINNAME:
   3270 
   3271      /* Length of struct domainname dest_addr_domainname */
   3272      result += domainname_encoded_len(obj->dest_addr_domainname);
   3273      break;
   3274 
   3275    default:
   3276      trunnel_assert(0);
   3277      break;
   3278  }
   3279 
   3280  /* Length of u16 dest_port */
   3281  result += 2;
   3282  return result;
   3283 }
   3284 int
   3285 socks5_client_request_clear_errors(socks5_client_request_t *obj)
   3286 {
   3287  int r = obj->trunnel_error_code_;
   3288  obj->trunnel_error_code_ = 0;
   3289  return r;
   3290 }
   3291 ssize_t
   3292 socks5_client_request_encode(uint8_t *output, const size_t avail, const socks5_client_request_t *obj)
   3293 {
   3294  ssize_t result = 0;
   3295  size_t written = 0;
   3296  uint8_t *ptr = output;
   3297  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  if (NULL != (msg = socks5_client_request_check(obj)))
   3303    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  trunnel_assert(written <= avail);
   3311  if (avail - written < 1)
   3312    goto truncated;
   3313  trunnel_set_uint8(ptr, (obj->version));
   3314  written += 1; ptr += 1;
   3315 
   3316  /* Encode u8 command IN [CMD_BIND, CMD_CONNECT, CMD_RESOLVE, CMD_RESOLVE_PTR, CMD_UDP_ASSOCIATE] */
   3317  trunnel_assert(written <= avail);
   3318  if (avail - written < 1)
   3319    goto truncated;
   3320  trunnel_set_uint8(ptr, (obj->command));
   3321  written += 1; ptr += 1;
   3322 
   3323  /* Encode u8 reserved IN [0] */
   3324  trunnel_assert(written <= avail);
   3325  if (avail - written < 1)
   3326    goto truncated;
   3327  trunnel_set_uint8(ptr, (obj->reserved));
   3328  written += 1; ptr += 1;
   3329 
   3330  /* Encode u8 atype */
   3331  trunnel_assert(written <= avail);
   3332  if (avail - written < 1)
   3333    goto truncated;
   3334  trunnel_set_uint8(ptr, (obj->atype));
   3335  written += 1; ptr += 1;
   3336 
   3337  /* Encode union dest_addr[atype] */
   3338  trunnel_assert(written <= avail);
   3339  switch (obj->atype) {
   3340 
   3341    case ATYPE_IPV4:
   3342 
   3343      /* Encode u32 dest_addr_ipv4 */
   3344      trunnel_assert(written <= avail);
   3345      if (avail - written < 4)
   3346        goto truncated;
   3347      trunnel_set_uint32(ptr, trunnel_htonl(obj->dest_addr_ipv4));
   3348      written += 4; ptr += 4;
   3349      break;
   3350 
   3351    case ATYPE_IPV6:
   3352 
   3353      /* Encode u8 dest_addr_ipv6[16] */
   3354      trunnel_assert(written <= avail);
   3355      if (avail - written < 16)
   3356        goto truncated;
   3357      memcpy(ptr, obj->dest_addr_ipv6, 16);
   3358      written += 16; ptr += 16;
   3359      break;
   3360 
   3361    case ATYPE_DOMAINNAME:
   3362 
   3363      /* Encode struct domainname dest_addr_domainname */
   3364      trunnel_assert(written <= avail);
   3365      result = domainname_encode(ptr, avail - written, obj->dest_addr_domainname);
   3366      if (result < 0)
   3367        goto fail; /* XXXXXXX !*/
   3368      written += result; ptr += result;
   3369      break;
   3370 
   3371    default:
   3372      trunnel_assert(0);
   3373      break;
   3374  }
   3375 
   3376  /* Encode u16 dest_port */
   3377  trunnel_assert(written <= avail);
   3378  if (avail - written < 2)
   3379    goto truncated;
   3380  trunnel_set_uint16(ptr, trunnel_htons(obj->dest_port));
   3381  written += 2; ptr += 2;
   3382 
   3383 
   3384  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  return written;
   3394 
   3395 truncated:
   3396  result = -2;
   3397  goto fail;
   3398 check_failed:
   3399  (void)msg;
   3400  result = -1;
   3401  goto fail;
   3402 fail:
   3403  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 socks5_client_request_parse_into(socks5_client_request_t *obj, const uint8_t *input, const size_t len_in)
   3412 {
   3413  const uint8_t *ptr = input;
   3414  size_t remaining = len_in;
   3415  ssize_t result = 0;
   3416  (void)result;
   3417 
   3418  /* Parse u8 version IN [5] */
   3419  CHECK_REMAINING(1, truncated);
   3420  obj->version = (trunnel_get_uint8(ptr));
   3421  remaining -= 1; ptr += 1;
   3422  if (! (obj->version == 5))
   3423    goto fail;
   3424 
   3425  /* Parse u8 command IN [CMD_BIND, CMD_CONNECT, CMD_RESOLVE, CMD_RESOLVE_PTR, CMD_UDP_ASSOCIATE] */
   3426  CHECK_REMAINING(1, truncated);
   3427  obj->command = (trunnel_get_uint8(ptr));
   3428  remaining -= 1; ptr += 1;
   3429  if (! (obj->command == CMD_BIND || obj->command == CMD_CONNECT || obj->command == CMD_RESOLVE || obj->command == CMD_RESOLVE_PTR || obj->command == CMD_UDP_ASSOCIATE))
   3430    goto fail;
   3431 
   3432  /* Parse u8 reserved IN [0] */
   3433  CHECK_REMAINING(1, truncated);
   3434  obj->reserved = (trunnel_get_uint8(ptr));
   3435  remaining -= 1; ptr += 1;
   3436  if (! (obj->reserved == 0))
   3437    goto fail;
   3438 
   3439  /* Parse u8 atype */
   3440  CHECK_REMAINING(1, truncated);
   3441  obj->atype = (trunnel_get_uint8(ptr));
   3442  remaining -= 1; ptr += 1;
   3443 
   3444  /* Parse union dest_addr[atype] */
   3445  switch (obj->atype) {
   3446 
   3447    case ATYPE_IPV4:
   3448 
   3449      /* Parse u32 dest_addr_ipv4 */
   3450      CHECK_REMAINING(4, truncated);
   3451      obj->dest_addr_ipv4 = trunnel_ntohl(trunnel_get_uint32(ptr));
   3452      remaining -= 4; ptr += 4;
   3453      break;
   3454 
   3455    case ATYPE_IPV6:
   3456 
   3457      /* Parse u8 dest_addr_ipv6[16] */
   3458      CHECK_REMAINING(16, truncated);
   3459      memcpy(obj->dest_addr_ipv6, ptr, 16);
   3460      remaining -= 16; ptr += 16;
   3461      break;
   3462 
   3463    case ATYPE_DOMAINNAME:
   3464 
   3465      /* Parse struct domainname dest_addr_domainname */
   3466      result = domainname_parse(&obj->dest_addr_domainname, ptr, remaining);
   3467      if (result < 0)
   3468        goto relay_fail;
   3469      trunnel_assert((size_t)result <= remaining);
   3470      remaining -= result; ptr += result;
   3471      break;
   3472 
   3473    default:
   3474      goto fail;
   3475      break;
   3476  }
   3477 
   3478  /* Parse u16 dest_port */
   3479  CHECK_REMAINING(2, truncated);
   3480  obj->dest_port = trunnel_ntohs(trunnel_get_uint16(ptr));
   3481  remaining -= 2; ptr += 2;
   3482  trunnel_assert(ptr + remaining == input + len_in);
   3483  return len_in - remaining;
   3484 
   3485 truncated:
   3486  return -2;
   3487 relay_fail:
   3488  trunnel_assert(result < 0);
   3489  return result;
   3490 fail:
   3491  result = -1;
   3492  return result;
   3493 }
   3494 
   3495 ssize_t
   3496 socks5_client_request_parse(socks5_client_request_t **output, const uint8_t *input, const size_t len_in)
   3497 {
   3498  ssize_t result;
   3499  *output = socks5_client_request_new();
   3500  if (NULL == *output)
   3501    return -1;
   3502  result = socks5_client_request_parse_into(*output, input, len_in);
   3503  if (result < 0) {
   3504    socks5_client_request_free(*output);
   3505    *output = NULL;
   3506  }
   3507  return result;
   3508 }
   3509 socks5_server_reply_t *
   3510 socks5_server_reply_new(void)
   3511 {
   3512  socks5_server_reply_t *val = trunnel_calloc(1, sizeof(socks5_server_reply_t));
   3513  if (NULL == val)
   3514    return NULL;
   3515  val->version = 5;
   3516  return val;
   3517 }
   3518 
   3519 /** Release all storage held inside 'obj', but do not free 'obj'.
   3520 */
   3521 static void
   3522 socks5_server_reply_clear(socks5_server_reply_t *obj)
   3523 {
   3524  (void) obj;
   3525  domainname_free(obj->bind_addr_domainname);
   3526  obj->bind_addr_domainname = NULL;
   3527 }
   3528 
   3529 void
   3530 socks5_server_reply_free(socks5_server_reply_t *obj)
   3531 {
   3532  if (obj == NULL)
   3533    return;
   3534  socks5_server_reply_clear(obj);
   3535  trunnel_memwipe(obj, sizeof(socks5_server_reply_t));
   3536  trunnel_free_(obj);
   3537 }
   3538 
   3539 uint8_t
   3540 socks5_server_reply_get_version(const socks5_server_reply_t *inp)
   3541 {
   3542  return inp->version;
   3543 }
   3544 int
   3545 socks5_server_reply_set_version(socks5_server_reply_t *inp, uint8_t val)
   3546 {
   3547  if (! ((val == 5))) {
   3548     TRUNNEL_SET_ERROR_CODE(inp);
   3549     return -1;
   3550  }
   3551  inp->version = val;
   3552  return 0;
   3553 }
   3554 uint8_t
   3555 socks5_server_reply_get_reply(const socks5_server_reply_t *inp)
   3556 {
   3557  return inp->reply;
   3558 }
   3559 int
   3560 socks5_server_reply_set_reply(socks5_server_reply_t *inp, uint8_t val)
   3561 {
   3562  inp->reply = val;
   3563  return 0;
   3564 }
   3565 uint8_t
   3566 socks5_server_reply_get_reserved(const socks5_server_reply_t *inp)
   3567 {
   3568  return inp->reserved;
   3569 }
   3570 int
   3571 socks5_server_reply_set_reserved(socks5_server_reply_t *inp, uint8_t val)
   3572 {
   3573  if (! ((val == 0))) {
   3574     TRUNNEL_SET_ERROR_CODE(inp);
   3575     return -1;
   3576  }
   3577  inp->reserved = val;
   3578  return 0;
   3579 }
   3580 uint8_t
   3581 socks5_server_reply_get_atype(const socks5_server_reply_t *inp)
   3582 {
   3583  return inp->atype;
   3584 }
   3585 int
   3586 socks5_server_reply_set_atype(socks5_server_reply_t *inp, uint8_t val)
   3587 {
   3588  inp->atype = val;
   3589  return 0;
   3590 }
   3591 uint32_t
   3592 socks5_server_reply_get_bind_addr_ipv4(const socks5_server_reply_t *inp)
   3593 {
   3594  return inp->bind_addr_ipv4;
   3595 }
   3596 int
   3597 socks5_server_reply_set_bind_addr_ipv4(socks5_server_reply_t *inp, uint32_t val)
   3598 {
   3599  inp->bind_addr_ipv4 = val;
   3600  return 0;
   3601 }
   3602 size_t
   3603 socks5_server_reply_getlen_bind_addr_ipv6(const socks5_server_reply_t *inp)
   3604 {
   3605  (void)inp;  return 16;
   3606 }
   3607 
   3608 uint8_t
   3609 socks5_server_reply_get_bind_addr_ipv6(socks5_server_reply_t *inp, size_t idx)
   3610 {
   3611  trunnel_assert(idx < 16);
   3612  return inp->bind_addr_ipv6[idx];
   3613 }
   3614 
   3615 uint8_t
   3616 socks5_server_reply_getconst_bind_addr_ipv6(const socks5_server_reply_t *inp, size_t idx)
   3617 {
   3618  return socks5_server_reply_get_bind_addr_ipv6((socks5_server_reply_t*)inp, idx);
   3619 }
   3620 int
   3621 socks5_server_reply_set_bind_addr_ipv6(socks5_server_reply_t *inp, size_t idx, uint8_t elt)
   3622 {
   3623  trunnel_assert(idx < 16);
   3624  inp->bind_addr_ipv6[idx] = elt;
   3625  return 0;
   3626 }
   3627 
   3628 uint8_t *
   3629 socks5_server_reply_getarray_bind_addr_ipv6(socks5_server_reply_t *inp)
   3630 {
   3631  return inp->bind_addr_ipv6;
   3632 }
   3633 const uint8_t  *
   3634 socks5_server_reply_getconstarray_bind_addr_ipv6(const socks5_server_reply_t *inp)
   3635 {
   3636  return (const uint8_t  *)socks5_server_reply_getarray_bind_addr_ipv6((socks5_server_reply_t*)inp);
   3637 }
   3638 struct domainname_st *
   3639 socks5_server_reply_get_bind_addr_domainname(socks5_server_reply_t *inp)
   3640 {
   3641  return inp->bind_addr_domainname;
   3642 }
   3643 const struct domainname_st *
   3644 socks5_server_reply_getconst_bind_addr_domainname(const socks5_server_reply_t *inp)
   3645 {
   3646  return socks5_server_reply_get_bind_addr_domainname((socks5_server_reply_t*) inp);
   3647 }
   3648 int
   3649 socks5_server_reply_set_bind_addr_domainname(socks5_server_reply_t *inp, struct domainname_st *val)
   3650 {
   3651  if (inp->bind_addr_domainname && inp->bind_addr_domainname != val)
   3652    domainname_free(inp->bind_addr_domainname);
   3653  return socks5_server_reply_set0_bind_addr_domainname(inp, val);
   3654 }
   3655 int
   3656 socks5_server_reply_set0_bind_addr_domainname(socks5_server_reply_t *inp, struct domainname_st *val)
   3657 {
   3658  inp->bind_addr_domainname = val;
   3659  return 0;
   3660 }
   3661 uint16_t
   3662 socks5_server_reply_get_bind_port(const socks5_server_reply_t *inp)
   3663 {
   3664  return inp->bind_port;
   3665 }
   3666 int
   3667 socks5_server_reply_set_bind_port(socks5_server_reply_t *inp, uint16_t val)
   3668 {
   3669  inp->bind_port = val;
   3670  return 0;
   3671 }
   3672 const char *
   3673 socks5_server_reply_check(const socks5_server_reply_t *obj)
   3674 {
   3675  if (obj == NULL)
   3676    return "Object was NULL";
   3677  if (obj->trunnel_error_code_)
   3678    return "A set function failed on this object";
   3679  if (! (obj->version == 5))
   3680    return "Integer out of bounds";
   3681  if (! (obj->reserved == 0))
   3682    return "Integer out of bounds";
   3683  switch (obj->atype) {
   3684 
   3685    case ATYPE_IPV4:
   3686      break;
   3687 
   3688    case ATYPE_IPV6:
   3689      break;
   3690 
   3691    case ATYPE_DOMAINNAME:
   3692      {
   3693        const char *msg;
   3694        if (NULL != (msg = domainname_check(obj->bind_addr_domainname)))
   3695          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 socks5_server_reply_encoded_len(const socks5_server_reply_t *obj)
   3708 {
   3709  ssize_t result = 0;
   3710 
   3711  if (NULL != socks5_server_reply_check(obj))
   3712     return -1;
   3713 
   3714 
   3715  /* Length of u8 version IN [5] */
   3716  result += 1;
   3717 
   3718  /* Length of u8 reply */
   3719  result += 1;
   3720 
   3721  /* Length of u8 reserved IN [0] */
   3722  result += 1;
   3723 
   3724  /* Length of u8 atype */
   3725  result += 1;
   3726  switch (obj->atype) {
   3727 
   3728    case ATYPE_IPV4:
   3729 
   3730      /* Length of u32 bind_addr_ipv4 */
   3731      result += 4;
   3732      break;
   3733 
   3734    case ATYPE_IPV6:
   3735 
   3736      /* Length of u8 bind_addr_ipv6[16] */
   3737      result += 16;
   3738      break;
   3739 
   3740    case ATYPE_DOMAINNAME:
   3741 
   3742      /* Length of struct domainname bind_addr_domainname */
   3743      result += domainname_encoded_len(obj->bind_addr_domainname);
   3744      break;
   3745 
   3746    default:
   3747      trunnel_assert(0);
   3748      break;
   3749  }
   3750 
   3751  /* Length of u16 bind_port */
   3752  result += 2;
   3753  return result;
   3754 }
   3755 int
   3756 socks5_server_reply_clear_errors(socks5_server_reply_t *obj)
   3757 {
   3758  int r = obj->trunnel_error_code_;
   3759  obj->trunnel_error_code_ = 0;
   3760  return r;
   3761 }
   3762 ssize_t
   3763 socks5_server_reply_encode(uint8_t *output, const size_t avail, const socks5_server_reply_t *obj)
   3764 {
   3765  ssize_t result = 0;
   3766  size_t written = 0;
   3767  uint8_t *ptr = output;
   3768  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  if (NULL != (msg = socks5_server_reply_check(obj)))
   3774    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  trunnel_assert(written <= avail);
   3782  if (avail - written < 1)
   3783    goto truncated;
   3784  trunnel_set_uint8(ptr, (obj->version));
   3785  written += 1; ptr += 1;
   3786 
   3787  /* Encode u8 reply */
   3788  trunnel_assert(written <= avail);
   3789  if (avail - written < 1)
   3790    goto truncated;
   3791  trunnel_set_uint8(ptr, (obj->reply));
   3792  written += 1; ptr += 1;
   3793 
   3794  /* Encode u8 reserved IN [0] */
   3795  trunnel_assert(written <= avail);
   3796  if (avail - written < 1)
   3797    goto truncated;
   3798  trunnel_set_uint8(ptr, (obj->reserved));
   3799  written += 1; ptr += 1;
   3800 
   3801  /* Encode u8 atype */
   3802  trunnel_assert(written <= avail);
   3803  if (avail - written < 1)
   3804    goto truncated;
   3805  trunnel_set_uint8(ptr, (obj->atype));
   3806  written += 1; ptr += 1;
   3807 
   3808  /* Encode union bind_addr[atype] */
   3809  trunnel_assert(written <= avail);
   3810  switch (obj->atype) {
   3811 
   3812    case ATYPE_IPV4:
   3813 
   3814      /* Encode u32 bind_addr_ipv4 */
   3815      trunnel_assert(written <= avail);
   3816      if (avail - written < 4)
   3817        goto truncated;
   3818      trunnel_set_uint32(ptr, trunnel_htonl(obj->bind_addr_ipv4));
   3819      written += 4; ptr += 4;
   3820      break;
   3821 
   3822    case ATYPE_IPV6:
   3823 
   3824      /* Encode u8 bind_addr_ipv6[16] */
   3825      trunnel_assert(written <= avail);
   3826      if (avail - written < 16)
   3827        goto truncated;
   3828      memcpy(ptr, obj->bind_addr_ipv6, 16);
   3829      written += 16; ptr += 16;
   3830      break;
   3831 
   3832    case ATYPE_DOMAINNAME:
   3833 
   3834      /* Encode struct domainname bind_addr_domainname */
   3835      trunnel_assert(written <= avail);
   3836      result = domainname_encode(ptr, avail - written, obj->bind_addr_domainname);
   3837      if (result < 0)
   3838        goto fail; /* XXXXXXX !*/
   3839      written += result; ptr += result;
   3840      break;
   3841 
   3842    default:
   3843      trunnel_assert(0);
   3844      break;
   3845  }
   3846 
   3847  /* Encode u16 bind_port */
   3848  trunnel_assert(written <= avail);
   3849  if (avail - written < 2)
   3850    goto truncated;
   3851  trunnel_set_uint16(ptr, trunnel_htons(obj->bind_port));
   3852  written += 2; ptr += 2;
   3853 
   3854 
   3855  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  return written;
   3865 
   3866 truncated:
   3867  result = -2;
   3868  goto fail;
   3869 check_failed:
   3870  (void)msg;
   3871  result = -1;
   3872  goto fail;
   3873 fail:
   3874  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 socks5_server_reply_parse_into(socks5_server_reply_t *obj, const uint8_t *input, const size_t len_in)
   3883 {
   3884  const uint8_t *ptr = input;
   3885  size_t remaining = len_in;
   3886  ssize_t result = 0;
   3887  (void)result;
   3888 
   3889  /* Parse u8 version IN [5] */
   3890  CHECK_REMAINING(1, truncated);
   3891  obj->version = (trunnel_get_uint8(ptr));
   3892  remaining -= 1; ptr += 1;
   3893  if (! (obj->version == 5))
   3894    goto fail;
   3895 
   3896  /* Parse u8 reply */
   3897  CHECK_REMAINING(1, truncated);
   3898  obj->reply = (trunnel_get_uint8(ptr));
   3899  remaining -= 1; ptr += 1;
   3900 
   3901  /* Parse u8 reserved IN [0] */
   3902  CHECK_REMAINING(1, truncated);
   3903  obj->reserved = (trunnel_get_uint8(ptr));
   3904  remaining -= 1; ptr += 1;
   3905  if (! (obj->reserved == 0))
   3906    goto fail;
   3907 
   3908  /* Parse u8 atype */
   3909  CHECK_REMAINING(1, truncated);
   3910  obj->atype = (trunnel_get_uint8(ptr));
   3911  remaining -= 1; ptr += 1;
   3912 
   3913  /* Parse union bind_addr[atype] */
   3914  switch (obj->atype) {
   3915 
   3916    case ATYPE_IPV4:
   3917 
   3918      /* Parse u32 bind_addr_ipv4 */
   3919      CHECK_REMAINING(4, truncated);
   3920      obj->bind_addr_ipv4 = trunnel_ntohl(trunnel_get_uint32(ptr));
   3921      remaining -= 4; ptr += 4;
   3922      break;
   3923 
   3924    case ATYPE_IPV6:
   3925 
   3926      /* Parse u8 bind_addr_ipv6[16] */
   3927      CHECK_REMAINING(16, truncated);
   3928      memcpy(obj->bind_addr_ipv6, ptr, 16);
   3929      remaining -= 16; ptr += 16;
   3930      break;
   3931 
   3932    case ATYPE_DOMAINNAME:
   3933 
   3934      /* Parse struct domainname bind_addr_domainname */
   3935      result = domainname_parse(&obj->bind_addr_domainname, ptr, remaining);
   3936      if (result < 0)
   3937        goto relay_fail;
   3938      trunnel_assert((size_t)result <= remaining);
   3939      remaining -= result; ptr += result;
   3940      break;
   3941 
   3942    default:
   3943      goto fail;
   3944      break;
   3945  }
   3946 
   3947  /* Parse u16 bind_port */
   3948  CHECK_REMAINING(2, truncated);
   3949  obj->bind_port = trunnel_ntohs(trunnel_get_uint16(ptr));
   3950  remaining -= 2; ptr += 2;
   3951  trunnel_assert(ptr + remaining == input + len_in);
   3952  return len_in - remaining;
   3953 
   3954 truncated:
   3955  return -2;
   3956 relay_fail:
   3957  trunnel_assert(result < 0);
   3958  return result;
   3959 fail:
   3960  result = -1;
   3961  return result;
   3962 }
   3963 
   3964 ssize_t
   3965 socks5_server_reply_parse(socks5_server_reply_t **output, const uint8_t *input, const size_t len_in)
   3966 {
   3967  ssize_t result;
   3968  *output = socks5_server_reply_new();
   3969  if (NULL == *output)
   3970    return -1;
   3971  result = socks5_server_reply_parse_into(*output, input, len_in);
   3972  if (result < 0) {
   3973    socks5_server_reply_free(*output);
   3974    *output = NULL;
   3975  }
   3976  return result;
   3977 }