aboutsummaryrefslogtreecommitdiff
path: root/src/trunnel
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2018-07-12 11:47:25 -0400
committerNick Mathewson <nickm@torproject.org>2018-07-12 11:47:25 -0400
commit7556933537b5777a9bef21230bb91a08aa70d60e (patch)
treea23d84b861cd801d1c805804efc3cd1881252582 /src/trunnel
parent0317eb143ec6869e5a27c1ffc6d3d89be4c35c32 (diff)
parentba3121191b59ea254e3ebab697430bdc03857b6d (diff)
downloadtor-7556933537b5777a9bef21230bb91a08aa70d60e.tar.gz
tor-7556933537b5777a9bef21230bb91a08aa70d60e.zip
Merge branch 'socks_trunnel4_squashed' into socks_trunnel4_squashed_merged
Diffstat (limited to 'src/trunnel')
-rw-r--r--src/trunnel/include.am9
-rw-r--r--src/trunnel/socks5.c3978
-rw-r--r--src/trunnel/socks5.h995
-rw-r--r--src/trunnel/socks5.trunnel94
4 files changed, 5073 insertions, 3 deletions
diff --git a/src/trunnel/include.am b/src/trunnel/include.am
index 5a0a79c3a0..03c1753e96 100644
--- a/src/trunnel/include.am
+++ b/src/trunnel/include.am
@@ -10,7 +10,8 @@ TRUNNELINPUTS = \
src/trunnel/ed25519_cert.trunnel \
src/trunnel/link_handshake.trunnel \
src/trunnel/pwbox.trunnel \
- src/trunnel/channelpadding_negotiation.trunnel
+ src/trunnel/channelpadding_negotiation.trunnel \
+ src/trunner/socks5.trunnel
TRUNNELSOURCES = \
src/ext/trunnel/trunnel.c \
@@ -21,7 +22,8 @@ TRUNNELSOURCES = \
src/trunnel/hs/cell_establish_intro.c \
src/trunnel/hs/cell_introduce1.c \
src/trunnel/hs/cell_rendezvous.c \
- src/trunnel/channelpadding_negotiation.c
+ src/trunnel/channelpadding_negotiation.c \
+ src/trunnel/socks5.c
TRUNNELHEADERS = \
src/ext/trunnel/trunnel.h \
@@ -34,7 +36,8 @@ TRUNNELHEADERS = \
src/trunnel/hs/cell_establish_intro.h \
src/trunnel/hs/cell_introduce1.h \
src/trunnel/hs/cell_rendezvous.h \
- src/trunnel/channelpadding_negotiation.h
+ src/trunnel/channelpadding_negotiation.h \
+ src/trunnel/socks5.h
src_trunnel_libor_trunnel_a_SOURCES = $(TRUNNELSOURCES)
src_trunnel_libor_trunnel_a_CPPFLAGS = \
diff --git a/src/trunnel/socks5.c b/src/trunnel/socks5.c
new file mode 100644
index 0000000000..9e5f6fcfed
--- /dev/null
+++ b/src/trunnel/socks5.c
@@ -0,0 +1,3978 @@
+/* socks5.c -- generated by Trunnel v1.5.2.
+ * https://gitweb.torproject.org/trunnel.git
+ * You probably shouldn't edit this file.
+ */
+#include <stdlib.h>
+#include "trunnel-impl.h"
+
+#include "socks5.h"
+
+#define TRUNNEL_SET_ERROR_CODE(obj) \
+ do { \
+ (obj)->trunnel_error_code_ = 1; \
+ } while (0)
+
+#if defined(__COVERITY__) || defined(__clang_analyzer__)
+/* If we're running a static analysis tool, we don't want it to complain
+ * that some of our remaining-bytes checks are dead-code. */
+int socks_deadcode_dummy__ = 0;
+#define OR_DEADCODE_DUMMY || socks_deadcode_dummy__
+#else
+#define OR_DEADCODE_DUMMY
+#endif
+
+#define CHECK_REMAINING(nbytes, label) \
+ do { \
+ if (remaining < (nbytes) OR_DEADCODE_DUMMY) { \
+ goto label; \
+ } \
+ } while (0)
+
+domainname_t *
+domainname_new(void)
+{
+ domainname_t *val = trunnel_calloc(1, sizeof(domainname_t));
+ if (NULL == val)
+ return NULL;
+ return val;
+}
+
+/** Release all storage held inside 'obj', but do not free 'obj'.
+ */
+static void
+domainname_clear(domainname_t *obj)
+{
+ (void) obj;
+ TRUNNEL_DYNARRAY_WIPE(&obj->name);
+ TRUNNEL_DYNARRAY_CLEAR(&obj->name);
+}
+
+void
+domainname_free(domainname_t *obj)
+{
+ if (obj == NULL)
+ return;
+ domainname_clear(obj);
+ trunnel_memwipe(obj, sizeof(domainname_t));
+ trunnel_free_(obj);
+}
+
+uint8_t
+domainname_get_len(const domainname_t *inp)
+{
+ return inp->len;
+}
+int
+domainname_set_len(domainname_t *inp, uint8_t val)
+{
+ inp->len = val;
+ return 0;
+}
+size_t
+domainname_getlen_name(const domainname_t *inp)
+{
+ return TRUNNEL_DYNARRAY_LEN(&inp->name);
+}
+
+char
+domainname_get_name(domainname_t *inp, size_t idx)
+{
+ return TRUNNEL_DYNARRAY_GET(&inp->name, idx);
+}
+
+char
+domainname_getconst_name(const domainname_t *inp, size_t idx)
+{
+ return domainname_get_name((domainname_t*)inp, idx);
+}
+int
+domainname_set_name(domainname_t *inp, size_t idx, char elt)
+{
+ TRUNNEL_DYNARRAY_SET(&inp->name, idx, elt);
+ return 0;
+}
+int
+domainname_add_name(domainname_t *inp, char elt)
+{
+#if SIZE_MAX >= UINT8_MAX
+ if (inp->name.n_ == UINT8_MAX)
+ goto trunnel_alloc_failed;
+#endif
+ TRUNNEL_DYNARRAY_ADD(char, &inp->name, elt, {});
+ return 0;
+ trunnel_alloc_failed:
+ TRUNNEL_SET_ERROR_CODE(inp);
+ return -1;
+}
+
+char *
+domainname_getarray_name(domainname_t *inp)
+{
+ return inp->name.elts_;
+}
+const char *
+domainname_getconstarray_name(const domainname_t *inp)
+{
+ return (const char *)domainname_getarray_name((domainname_t*)inp);
+}
+int
+domainname_setlen_name(domainname_t *inp, size_t newlen)
+{
+#if UINT8_MAX < SIZE_MAX
+ if (newlen > UINT8_MAX)
+ goto trunnel_alloc_failed;
+#endif
+ return trunnel_string_setlen(&inp->name, newlen,
+ &inp->trunnel_error_code_);
+ trunnel_alloc_failed:
+ TRUNNEL_SET_ERROR_CODE(inp);
+ return -1;
+}
+const char *
+domainname_getstr_name(domainname_t *inp)
+{
+ return trunnel_string_getstr(&inp->name);
+}
+int
+domainname_setstr0_name(domainname_t *inp, const char *val, size_t len)
+{
+#if UINT8_MAX < SIZE_MAX
+ if (len > UINT8_MAX) {
+ TRUNNEL_SET_ERROR_CODE(inp);
+ return -1;
+ }
+#endif
+ return trunnel_string_setstr0(&inp->name, val, len, &inp->trunnel_error_code_);
+}
+int
+domainname_setstr_name(domainname_t *inp, const char *val)
+{
+ return domainname_setstr0_name(inp, val, strlen(val));
+}
+const char *
+domainname_check(const domainname_t *obj)
+{
+ if (obj == NULL)
+ return "Object was NULL";
+ if (obj->trunnel_error_code_)
+ return "A set function failed on this object";
+ if (TRUNNEL_DYNARRAY_LEN(&obj->name) != obj->len)
+ return "Length mismatch for name";
+ return NULL;
+}
+
+ssize_t
+domainname_encoded_len(const domainname_t *obj)
+{
+ ssize_t result = 0;
+
+ if (NULL != domainname_check(obj))
+ return -1;
+
+
+ /* Length of u8 len */
+ result += 1;
+
+ /* Length of char name[len] */
+ result += TRUNNEL_DYNARRAY_LEN(&obj->name);
+ return result;
+}
+int
+domainname_clear_errors(domainname_t *obj)
+{
+ int r = obj->trunnel_error_code_;
+ obj->trunnel_error_code_ = 0;
+ return r;
+}
+ssize_t
+domainname_encode(uint8_t *output, const size_t avail, const domainname_t *obj)
+{
+ ssize_t result = 0;
+ size_t written = 0;
+ uint8_t *ptr = output;
+ const char *msg;
+#ifdef TRUNNEL_CHECK_ENCODED_LEN
+ const ssize_t encoded_len = domainname_encoded_len(obj);
+#endif
+
+ if (NULL != (msg = domainname_check(obj)))
+ goto check_failed;
+
+#ifdef TRUNNEL_CHECK_ENCODED_LEN
+ trunnel_assert(encoded_len >= 0);
+#endif
+
+ /* Encode u8 len */
+ trunnel_assert(written <= avail);
+ if (avail - written < 1)
+ goto truncated;
+ trunnel_set_uint8(ptr, (obj->len));
+ written += 1; ptr += 1;
+
+ /* Encode char name[len] */
+ {
+ size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->name);
+ trunnel_assert(obj->len == elt_len);
+ trunnel_assert(written <= avail);
+ if (avail - written < elt_len)
+ goto truncated;
+ if (elt_len)
+ memcpy(ptr, obj->name.elts_, elt_len);
+ written += elt_len; ptr += elt_len;
+ }
+
+
+ trunnel_assert(ptr == output + written);
+#ifdef TRUNNEL_CHECK_ENCODED_LEN
+ {
+ trunnel_assert(encoded_len >= 0);
+ trunnel_assert((size_t)encoded_len == written);
+ }
+
+#endif
+
+ return written;
+
+ truncated:
+ result = -2;
+ goto fail;
+ check_failed:
+ (void)msg;
+ result = -1;
+ goto fail;
+ fail:
+ trunnel_assert(result < 0);
+ return result;
+}
+
+/** As domainname_parse(), but do not allocate the output object.
+ */
+static ssize_t
+domainname_parse_into(domainname_t *obj, const uint8_t *input, const size_t len_in)
+{
+ const uint8_t *ptr = input;
+ size_t remaining = len_in;
+ ssize_t result = 0;
+ (void)result;
+
+ /* Parse u8 len */
+ CHECK_REMAINING(1, truncated);
+ obj->len = (trunnel_get_uint8(ptr));
+ remaining -= 1; ptr += 1;
+
+ /* Parse char name[len] */
+ CHECK_REMAINING(obj->len, truncated);
+ if (domainname_setstr0_name(obj, (const char*)ptr, obj->len))
+ goto fail;
+ ptr += obj->len; remaining -= obj->len;
+ trunnel_assert(ptr + remaining == input + len_in);
+ return len_in - remaining;
+
+ truncated:
+ return -2;
+ fail:
+ result = -1;
+ return result;
+}
+
+ssize_t
+domainname_parse(domainname_t **output, const uint8_t *input, const size_t len_in)
+{
+ ssize_t result;
+ *output = domainname_new();
+ if (NULL == *output)
+ return -1;
+ result = domainname_parse_into(*output, input, len_in);
+ if (result < 0) {
+ domainname_free(*output);
+ *output = NULL;
+ }
+ return result;
+}
+socks4_client_request_t *
+socks4_client_request_new(void)
+{
+ socks4_client_request_t *val = trunnel_calloc(1, sizeof(socks4_client_request_t));
+ if (NULL == val)
+ return NULL;
+ val->version = 4;
+ val->command = CMD_BIND;
+ return val;
+}
+
+/** Release all storage held inside 'obj', but do not free 'obj'.
+ */
+static void
+socks4_client_request_clear(socks4_client_request_t *obj)
+{
+ (void) obj;
+ trunnel_wipestr(obj->username);
+ trunnel_free(obj->username);
+ trunnel_wipestr(obj->socks4a_addr_hostname);
+ trunnel_free(obj->socks4a_addr_hostname);
+}
+
+void
+socks4_client_request_free(socks4_client_request_t *obj)
+{
+ if (obj == NULL)
+ return;
+ socks4_client_request_clear(obj);
+ trunnel_memwipe(obj, sizeof(socks4_client_request_t));
+ trunnel_free_(obj);
+}
+
+uint8_t
+socks4_client_request_get_version(const socks4_client_request_t *inp)
+{
+ return inp->version;
+}
+int
+socks4_client_request_set_version(socks4_client_request_t *inp, uint8_t val)
+{
+ if (! ((val == 4))) {
+ TRUNNEL_SET_ERROR_CODE(inp);
+ return -1;
+ }
+ inp->version = val;
+ return 0;
+}
+uint8_t
+socks4_client_request_get_command(const socks4_client_request_t *inp)
+{
+ return inp->command;
+}
+int
+socks4_client_request_set_command(socks4_client_request_t *inp, uint8_t val)
+{
+ if (! ((val == CMD_BIND || val == CMD_CONNECT || val == CMD_RESOLVE || val == CMD_RESOLVE_PTR))) {
+ TRUNNEL_SET_ERROR_CODE(inp);
+ return -1;
+ }
+ inp->command = val;
+ return 0;
+}
+uint16_t
+socks4_client_request_get_port(const socks4_client_request_t *inp)
+{
+ return inp->port;
+}
+int
+socks4_client_request_set_port(socks4_client_request_t *inp, uint16_t val)
+{
+ inp->port = val;
+ return 0;
+}
+uint32_t
+socks4_client_request_get_addr(const socks4_client_request_t *inp)
+{
+ return inp->addr;
+}
+int
+socks4_client_request_set_addr(socks4_client_request_t *inp, uint32_t val)
+{
+ inp->addr = val;
+ return 0;
+}
+const char *
+socks4_client_request_get_username(const socks4_client_request_t *inp)
+{
+ return inp->username;
+}
+int
+socks4_client_request_set_username(socks4_client_request_t *inp, const char *val)
+{
+ trunnel_free(inp->username);
+ if (NULL == (inp->username = trunnel_strdup(val))) {
+ TRUNNEL_SET_ERROR_CODE(inp);
+ return -1;
+ }
+ return 0;
+}
+const char *
+socks4_client_request_get_socks4a_addr_hostname(const socks4_client_request_t *inp)
+{
+ return inp->socks4a_addr_hostname;
+}
+int
+socks4_client_request_set_socks4a_addr_hostname(socks4_client_request_t *inp, const char *val)
+{
+ trunnel_free(inp->socks4a_addr_hostname);
+ if (NULL == (inp->socks4a_addr_hostname = trunnel_strdup(val))) {
+ TRUNNEL_SET_ERROR_CODE(inp);
+ return -1;
+ }
+ return 0;
+}
+const char *
+socks4_client_request_check(const socks4_client_request_t *obj)
+{
+ if (obj == NULL)
+ return "Object was NULL";
+ if (obj->trunnel_error_code_)
+ return "A set function failed on this object";
+ if (! (obj->version == 4))
+ return "Integer out of bounds";
+ if (! (obj->command == CMD_BIND || obj->command == CMD_CONNECT || obj->command == CMD_RESOLVE || obj->command == CMD_RESOLVE_PTR))
+ return "Integer out of bounds";
+ if (NULL == obj->username)
+ return "Missing username";
+ switch (obj->addr) {
+
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ case 13:
+ case 14:
+ case 15:
+ case 16:
+ case 17:
+ case 18:
+ case 19:
+ case 20:
+ case 21:
+ case 22:
+ case 23:
+ case 24:
+ case 25:
+ case 26:
+ case 27:
+ case 28:
+ case 29:
+ case 30:
+ case 31:
+ case 32:
+ case 33:
+ case 34:
+ case 35:
+ case 36:
+ case 37:
+ case 38:
+ case 39:
+ case 40:
+ case 41:
+ case 42:
+ case 43:
+ case 44:
+ case 45:
+ case 46:
+ case 47:
+ case 48:
+ case 49:
+ case 50:
+ case 51:
+ case 52:
+ case 53:
+ case 54:
+ case 55:
+ case 56:
+ case 57:
+ case 58:
+ case 59:
+ case 60:
+ case 61:
+ case 62:
+ case 63:
+ case 64:
+ case 65:
+ case 66:
+ case 67:
+ case 68:
+ case 69:
+ case 70:
+ case 71:
+ case 72:
+ case 73:
+ case 74:
+ case 75:
+ case 76:
+ case 77:
+ case 78:
+ case 79:
+ case 80:
+ case 81:
+ case 82:
+ case 83:
+ case 84:
+ case 85:
+ case 86:
+ case 87:
+ case 88:
+ case 89:
+ case 90:
+ case 91:
+ case 92:
+ case 93:
+ case 94:
+ case 95:
+ case 96:
+ case 97:
+ case 98:
+ case 99:
+ case 100:
+ case 101:
+ case 102:
+ case 103:
+ case 104:
+ case 105:
+ case 106:
+ case 107:
+ case 108:
+ case 109:
+ case 110:
+ case 111:
+ case 112:
+ case 113:
+ case 114:
+ case 115:
+ case 116:
+ case 117:
+ case 118:
+ case 119:
+ case 120:
+ case 121:
+ case 122:
+ case 123:
+ case 124:
+ case 125:
+ case 126:
+ case 127:
+ case 128:
+ case 129:
+ case 130:
+ case 131:
+ case 132:
+ case 133:
+ case 134:
+ case 135:
+ case 136:
+ case 137:
+ case 138:
+ case 139:
+ case 140:
+ case 141:
+ case 142:
+ case 143:
+ case 144:
+ case 145:
+ case 146:
+ case 147:
+ case 148:
+ case 149:
+ case 150:
+ case 151:
+ case 152:
+ case 153:
+ case 154:
+ case 155:
+ case 156:
+ case 157:
+ case 158:
+ case 159:
+ case 160:
+ case 161:
+ case 162:
+ case 163:
+ case 164:
+ case 165:
+ case 166:
+ case 167:
+ case 168:
+ case 169:
+ case 170:
+ case 171:
+ case 172:
+ case 173:
+ case 174:
+ case 175:
+ case 176:
+ case 177:
+ case 178:
+ case 179:
+ case 180:
+ case 181:
+ case 182:
+ case 183:
+ case 184:
+ case 185:
+ case 186:
+ case 187:
+ case 188:
+ case 189:
+ case 190:
+ case 191:
+ case 192:
+ case 193:
+ case 194:
+ case 195:
+ case 196:
+ case 197:
+ case 198:
+ case 199:
+ case 200:
+ case 201:
+ case 202:
+ case 203:
+ case 204:
+ case 205:
+ case 206:
+ case 207:
+ case 208:
+ case 209:
+ case 210:
+ case 211:
+ case 212:
+ case 213:
+ case 214:
+ case 215:
+ case 216:
+ case 217:
+ case 218:
+ case 219:
+ case 220:
+ case 221:
+ case 222:
+ case 223:
+ case 224:
+ case 225:
+ case 226:
+ case 227:
+ case 228:
+ case 229:
+ case 230:
+ case 231:
+ case 232:
+ case 233:
+ case 234:
+ case 235:
+ case 236:
+ case 237:
+ case 238:
+ case 239:
+ case 240:
+ case 241:
+ case 242:
+ case 243:
+ case 244:
+ case 245:
+ case 246:
+ case 247:
+ case 248:
+ case 249:
+ case 250:
+ case 251:
+ case 252:
+ case 253:
+ case 254:
+ case 255:
+ if (NULL == obj->socks4a_addr_hostname)
+ return "Missing socks4a_addr_hostname";
+ break;
+
+ default:
+ break;
+ }
+ return NULL;
+}
+
+ssize_t
+socks4_client_request_encoded_len(const socks4_client_request_t *obj)
+{
+ ssize_t result = 0;
+
+ if (NULL != socks4_client_request_check(obj))
+ return -1;
+
+
+ /* Length of u8 version IN [4] */
+ result += 1;
+
+ /* Length of u8 command IN [CMD_BIND, CMD_CONNECT, CMD_RESOLVE, CMD_RESOLVE_PTR] */
+ result += 1;
+
+ /* Length of u16 port */
+ result += 2;
+
+ /* Length of u32 addr */
+ result += 4;
+
+ /* Length of nulterm username */
+ result += strlen(obj->username) + 1;
+ switch (obj->addr) {
+
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ case 13:
+ case 14:
+ case 15:
+ case 16:
+ case 17:
+ case 18:
+ case 19:
+ case 20:
+ case 21:
+ case 22:
+ case 23:
+ case 24:
+ case 25:
+ case 26:
+ case 27:
+ case 28:
+ case 29:
+ case 30:
+ case 31:
+ case 32:
+ case 33:
+ case 34:
+ case 35:
+ case 36:
+ case 37:
+ case 38:
+ case 39:
+ case 40:
+ case 41:
+ case 42:
+ case 43:
+ case 44:
+ case 45:
+ case 46:
+ case 47:
+ case 48:
+ case 49:
+ case 50:
+ case 51:
+ case 52:
+ case 53:
+ case 54:
+ case 55:
+ case 56:
+ case 57:
+ case 58:
+ case 59:
+ case 60:
+ case 61:
+ case 62:
+ case 63:
+ case 64:
+ case 65:
+ case 66:
+ case 67:
+ case 68:
+ case 69:
+ case 70:
+ case 71:
+ case 72:
+ case 73:
+ case 74:
+ case 75:
+ case 76:
+ case 77:
+ case 78:
+ case 79:
+ case 80:
+ case 81:
+ case 82:
+ case 83:
+ case 84:
+ case 85:
+ case 86:
+ case 87:
+ case 88:
+ case 89:
+ case 90:
+ case 91:
+ case 92:
+ case 93:
+ case 94:
+ case 95:
+ case 96:
+ case 97:
+ case 98:
+ case 99:
+ case 100:
+ case 101:
+ case 102:
+ case 103:
+ case 104:
+ case 105:
+ case 106:
+ case 107:
+ case 108:
+ case 109:
+ case 110:
+ case 111:
+ case 112:
+ case 113:
+ case 114:
+ case 115:
+ case 116:
+ case 117:
+ case 118:
+ case 119:
+ case 120:
+ case 121:
+ case 122:
+ case 123:
+ case 124:
+ case 125:
+ case 126:
+ case 127:
+ case 128:
+ case 129:
+ case 130:
+ case 131:
+ case 132:
+ case 133:
+ case 134:
+ case 135:
+ case 136:
+ case 137:
+ case 138:
+ case 139:
+ case 140:
+ case 141:
+ case 142:
+ case 143:
+ case 144:
+ case 145:
+ case 146:
+ case 147:
+ case 148:
+ case 149:
+ case 150:
+ case 151:
+ case 152:
+ case 153:
+ case 154:
+ case 155:
+ case 156:
+ case 157:
+ case 158:
+ case 159:
+ case 160:
+ case 161:
+ case 162:
+ case 163:
+ case 164:
+ case 165:
+ case 166:
+ case 167:
+ case 168:
+ case 169:
+ case 170:
+ case 171:
+ case 172:
+ case 173:
+ case 174:
+ case 175:
+ case 176:
+ case 177:
+ case 178:
+ case 179:
+ case 180:
+ case 181:
+ case 182:
+ case 183:
+ case 184:
+ case 185:
+ case 186:
+ case 187:
+ case 188:
+ case 189:
+ case 190:
+ case 191:
+ case 192:
+ case 193:
+ case 194:
+ case 195:
+ case 196:
+ case 197:
+ case 198:
+ case 199:
+ case 200:
+ case 201:
+ case 202:
+ case 203:
+ case 204:
+ case 205:
+ case 206:
+ case 207:
+ case 208:
+ case 209:
+ case 210:
+ case 211:
+ case 212:
+ case 213:
+ case 214:
+ case 215:
+ case 216:
+ case 217:
+ case 218:
+ case 219:
+ case 220:
+ case 221:
+ case 222:
+ case 223:
+ case 224:
+ case 225:
+ case 226:
+ case 227:
+ case 228:
+ case 229:
+ case 230:
+ case 231:
+ case 232:
+ case 233:
+ case 234:
+ case 235:
+ case 236:
+ case 237:
+ case 238:
+ case 239:
+ case 240:
+ case 241:
+ case 242:
+ case 243:
+ case 244:
+ case 245:
+ case 246:
+ case 247:
+ case 248:
+ case 249:
+ case 250:
+ case 251:
+ case 252:
+ case 253:
+ case 254:
+ case 255:
+
+ /* Length of nulterm socks4a_addr_hostname */
+ result += strlen(obj->socks4a_addr_hostname) + 1;
+ break;
+
+ default:
+ break;
+ }
+ return result;
+}
+int
+socks4_client_request_clear_errors(socks4_client_request_t *obj)
+{
+ int r = obj->trunnel_error_code_;
+ obj->trunnel_error_code_ = 0;
+ return r;
+}
+ssize_t
+socks4_client_request_encode(uint8_t *output, const size_t avail, const socks4_client_request_t *obj)
+{
+ ssize_t result = 0;
+ size_t written = 0;
+ uint8_t *ptr = output;
+ const char *msg;
+#ifdef TRUNNEL_CHECK_ENCODED_LEN
+ const ssize_t encoded_len = socks4_client_request_encoded_len(obj);
+#endif
+
+ if (NULL != (msg = socks4_client_request_check(obj)))
+ goto check_failed;
+
+#ifdef TRUNNEL_CHECK_ENCODED_LEN
+ trunnel_assert(encoded_len >= 0);
+#endif
+
+ /* Encode u8 version IN [4] */
+ trunnel_assert(written <= avail);
+ if (avail - written < 1)
+ goto truncated;
+ trunnel_set_uint8(ptr, (obj->version));
+ written += 1; ptr += 1;
+
+ /* Encode u8 command IN [CMD_BIND, CMD_CONNECT, CMD_RESOLVE, CMD_RESOLVE_PTR] */
+ trunnel_assert(written <= avail);
+ if (avail - written < 1)
+ goto truncated;
+ trunnel_set_uint8(ptr, (obj->command));
+ written += 1; ptr += 1;
+
+ /* Encode u16 port */
+ trunnel_assert(written <= avail);
+ if (avail - written < 2)
+ goto truncated;
+ trunnel_set_uint16(ptr, trunnel_htons(obj->port));
+ written += 2; ptr += 2;
+
+ /* Encode u32 addr */
+ trunnel_assert(written <= avail);
+ if (avail - written < 4)
+ goto truncated;
+ trunnel_set_uint32(ptr, trunnel_htonl(obj->addr));
+ written += 4; ptr += 4;
+
+ /* Encode nulterm username */
+ {
+ size_t len = strlen(obj->username);
+ trunnel_assert(written <= avail);
+ if (avail - written < len + 1)
+ goto truncated;
+ memcpy(ptr, obj->username, len + 1);
+ ptr += len + 1; written += len + 1;
+ }
+
+ /* Encode union socks4a_addr[addr] */
+ trunnel_assert(written <= avail);
+ switch (obj->addr) {
+
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ case 13:
+ case 14:
+ case 15:
+ case 16:
+ case 17:
+ case 18:
+ case 19:
+ case 20:
+ case 21:
+ case 22:
+ case 23:
+ case 24:
+ case 25:
+ case 26:
+ case 27:
+ case 28:
+ case 29:
+ case 30:
+ case 31:
+ case 32:
+ case 33:
+ case 34:
+ case 35:
+ case 36:
+ case 37:
+ case 38:
+ case 39:
+ case 40:
+ case 41:
+ case 42:
+ case 43:
+ case 44:
+ case 45:
+ case 46:
+ case 47:
+ case 48:
+ case 49:
+ case 50:
+ case 51:
+ case 52:
+ case 53:
+ case 54:
+ case 55:
+ case 56:
+ case 57:
+ case 58:
+ case 59:
+ case 60:
+ case 61:
+ case 62:
+ case 63:
+ case 64:
+ case 65:
+ case 66:
+ case 67:
+ case 68:
+ case 69:
+ case 70:
+ case 71:
+ case 72:
+ case 73:
+ case 74:
+ case 75:
+ case 76:
+ case 77:
+ case 78:
+ case 79:
+ case 80:
+ case 81:
+ case 82:
+ case 83:
+ case 84:
+ case 85:
+ case 86:
+ case 87:
+ case 88:
+ case 89:
+ case 90:
+ case 91:
+ case 92:
+ case 93:
+ case 94:
+ case 95:
+ case 96:
+ case 97:
+ case 98:
+ case 99:
+ case 100:
+ case 101:
+ case 102:
+ case 103:
+ case 104:
+ case 105:
+ case 106:
+ case 107:
+ case 108:
+ case 109:
+ case 110:
+ case 111:
+ case 112:
+ case 113:
+ case 114:
+ case 115:
+ case 116:
+ case 117:
+ case 118:
+ case 119:
+ case 120:
+ case 121:
+ case 122:
+ case 123:
+ case 124:
+ case 125:
+ case 126:
+ case 127:
+ case 128:
+ case 129:
+ case 130:
+ case 131:
+ case 132:
+ case 133:
+ case 134:
+ case 135:
+ case 136:
+ case 137:
+ case 138:
+ case 139:
+ case 140:
+ case 141:
+ case 142:
+ case 143:
+ case 144:
+ case 145:
+ case 146:
+ case 147:
+ case 148:
+ case 149:
+ case 150:
+ case 151:
+ case 152:
+ case 153:
+ case 154:
+ case 155:
+ case 156:
+ case 157:
+ case 158:
+ case 159:
+ case 160:
+ case 161:
+ case 162:
+ case 163:
+ case 164:
+ case 165:
+ case 166:
+ case 167:
+ case 168:
+ case 169:
+ case 170:
+ case 171:
+ case 172:
+ case 173:
+ case 174:
+ case 175:
+ case 176:
+ case 177:
+ case 178:
+ case 179:
+ case 180:
+ case 181:
+ case 182:
+ case 183:
+ case 184:
+ case 185:
+ case 186:
+ case 187:
+ case 188:
+ case 189:
+ case 190:
+ case 191:
+ case 192:
+ case 193:
+ case 194:
+ case 195:
+ case 196:
+ case 197:
+ case 198:
+ case 199:
+ case 200:
+ case 201:
+ case 202:
+ case 203:
+ case 204:
+ case 205:
+ case 206:
+ case 207:
+ case 208:
+ case 209:
+ case 210:
+ case 211:
+ case 212:
+ case 213:
+ case 214:
+ case 215:
+ case 216:
+ case 217:
+ case 218:
+ case 219:
+ case 220:
+ case 221:
+ case 222:
+ case 223:
+ case 224:
+ case 225:
+ case 226:
+ case 227:
+ case 228:
+ case 229: