1 // 2 // socks4.hpp 3 // ~~~~~~~~~~ 4 // 5 // Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) 6 // 7 // Distributed under the Boost Software License, Version 1.0. (See accompanying 8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 9 // 10 11 #ifndef SOCKS4_HPP 12 #define SOCKS4_HPP 13 14 #include <array> 15 #include <string> 16 #include <boost/asio/buffer.hpp> 17 #include <boost/asio/ip/tcp.hpp> 18 19 namespace socks4 { 20 21 const unsigned char version = 0x04; 22 23 class request 24 { 25 public: 26 enum command_type 27 { 28 connect = 0x01, 29 bind = 0x02 30 }; 31 request(command_type cmd,const boost::asio::ip::tcp::endpoint & endpoint,const std::string & user_id)32 request(command_type cmd, const boost::asio::ip::tcp::endpoint& endpoint, 33 const std::string& user_id) 34 : version_(version), 35 command_(cmd), 36 user_id_(user_id), 37 null_byte_(0) 38 { 39 // Only IPv4 is supported by the SOCKS 4 protocol. 40 if (endpoint.protocol() != boost::asio::ip::tcp::v4()) 41 { 42 throw boost::system::system_error( 43 boost::asio::error::address_family_not_supported); 44 } 45 46 // Convert port number to network byte order. 47 unsigned short port = endpoint.port(); 48 port_high_byte_ = (port >> 8) & 0xff; 49 port_low_byte_ = port & 0xff; 50 51 // Save IP address in network byte order. 52 address_ = endpoint.address().to_v4().to_bytes(); 53 } 54 buffers() const55 std::array<boost::asio::const_buffer, 7> buffers() const 56 { 57 return 58 { 59 { 60 boost::asio::buffer(&version_, 1), 61 boost::asio::buffer(&command_, 1), 62 boost::asio::buffer(&port_high_byte_, 1), 63 boost::asio::buffer(&port_low_byte_, 1), 64 boost::asio::buffer(address_), 65 boost::asio::buffer(user_id_), 66 boost::asio::buffer(&null_byte_, 1) 67 } 68 }; 69 } 70 71 private: 72 unsigned char version_; 73 unsigned char command_; 74 unsigned char port_high_byte_; 75 unsigned char port_low_byte_; 76 boost::asio::ip::address_v4::bytes_type address_; 77 std::string user_id_; 78 unsigned char null_byte_; 79 }; 80 81 class reply 82 { 83 public: 84 enum status_type 85 { 86 request_granted = 0x5a, 87 request_failed = 0x5b, 88 request_failed_no_identd = 0x5c, 89 request_failed_bad_user_id = 0x5d 90 }; 91 reply()92 reply() 93 : null_byte_(0), 94 status_() 95 { 96 } 97 buffers()98 std::array<boost::asio::mutable_buffer, 5> buffers() 99 { 100 return 101 { 102 { 103 boost::asio::buffer(&null_byte_, 1), 104 boost::asio::buffer(&status_, 1), 105 boost::asio::buffer(&port_high_byte_, 1), 106 boost::asio::buffer(&port_low_byte_, 1), 107 boost::asio::buffer(address_) 108 } 109 }; 110 } 111 success() const112 bool success() const 113 { 114 return null_byte_ == 0 && status_ == request_granted; 115 } 116 status() const117 unsigned char status() const 118 { 119 return status_; 120 } 121 endpoint() const122 boost::asio::ip::tcp::endpoint endpoint() const 123 { 124 unsigned short port = port_high_byte_; 125 port = (port << 8) & 0xff00; 126 port = port | port_low_byte_; 127 128 boost::asio::ip::address_v4 address(address_); 129 130 return boost::asio::ip::tcp::endpoint(address, port); 131 } 132 133 private: 134 unsigned char null_byte_; 135 unsigned char status_; 136 unsigned char port_high_byte_; 137 unsigned char port_low_byte_; 138 boost::asio::ip::address_v4::bytes_type address_; 139 }; 140 141 } // namespace socks4 142 143 #endif // SOCKS4_HPP 144