#include "socks5.h" void socks5_handshake(int sock) { struct client_handshake ch = {0x05, 0x01, {0x00}}; int size = sizeof(uint8_t) * (2 + ch.nmethods); if (size != write(sock, &ch, size)) { fprintf(stderr, "partial/failed write\n"); exit(EXIT_FAILURE); } struct server_handshake sh = {0}; int err = read_entity(sock, &sh, sizeof(struct server_handshake)); if (err == -1) { perror("read"); exit(EXIT_FAILURE); } printf("[server_handshake] ver=%d, method=%d\n", sh.ver, sh.method); } void socks5_reply(int sock) { struct server_reply sr = {0}; read_entity(sock, &sr, sizeof(uint8_t) * 4); switch(sr.atyp) { case ATYP_IPV4: if (read_entity(sock, sr.bind_addr.ipv4, sizeof(uint8_t) * 4) == -1) goto read_error; break; case ATYP_DOMAINNAME: if (read_entity(sock, &sr.bind_addr.dns.len, sizeof(uint8_t) * 4) == -1) goto read_error; if (read_entity(sock, sr.bind_addr.dns.str, sizeof(char) * sr.bind_addr.dns.len) == -1) goto read_error; break; case ATYP_IPV6: if (read_entity(sock, sr.bind_addr.ipv6, sizeof(uint8_t) * 16) == -1) goto read_error; break; default: fprintf(stderr, "unsupported ATYP in server reply\n"); exit(EXIT_FAILURE); } read_entity(sock, &sr.port, sizeof(uint16_t)); printf("[server_reply] ver=%d, rep=%d, atyp=%d, port=%d\n", sr.ver, sr.rep, sr.atyp, sr.port); return; read_error: fprintf(stderr, "unsupported ATYP in server reply\n"); exit(EXIT_FAILURE); } void socks5_connect_dns(int sock, char* addr, uint16_t port) { char buffer[262]; size_t domainLength = strlen(addr); if (domainLength > 255) { fprintf(stderr, "domain is too long\n"); exit(EXIT_FAILURE); } struct client_request cr = { 0x05, CMD_CONNECT, 0x00, ATYP_DOMAINNAME, (uint8_t)domainLength, addr, htons(port) }; size_t written = 0; fill_buffer(&written, buffer, &cr, 5*sizeof(uint8_t)); fill_buffer(&written, buffer, cr.dst_addr, cr.dst_addr_len*sizeof(char)); fill_buffer(&written, buffer, &cr.port, sizeof(uint16_t)); if (written != write(sock, buffer, written)) { fprintf(stderr, "partial/failed write\n"); exit(EXIT_FAILURE); } }