badvpn/socksclient/BSocksClient.h
Ambroz Bizjak e837e8d552 tun2socks: Remove localhost limination for SOCKS5 UDP.
The UDP socket is bound to the same IP address as was automatically selected for the TCP socket, and the port number is set to zero to let the kernel pick it. The actual bound address with the assigned port number is sent to the SOCKS server as DST.ADDR.
2020-02-01 15:02:11 -08:00

212 lines
7.9 KiB
C

/**
* @file BSocksClient.h
* @author Ambroz Bizjak <ambrop7@gmail.com>
*
* @section LICENSE
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the author nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @section DESCRIPTION
*
* SOCKS5 client. TCP only, no authentication.
*/
#ifndef BADVPN_SOCKS_BSOCKSCLIENT_H
#define BADVPN_SOCKS_BSOCKSCLIENT_H
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include <misc/debug.h>
#include <misc/debugerror.h>
#include <misc/socks_proto.h>
#include <misc/packed.h>
#include <base/DebugObject.h>
#include <base/BPending.h>
#include <system/BConnection.h>
#include <flow/PacketStreamSender.h>
#define BSOCKSCLIENT_EVENT_ERROR 1
#define BSOCKSCLIENT_EVENT_UP 2
#define BSOCKSCLIENT_EVENT_ERROR_CLOSED 3
#define BSOCKSCLIENT_EVENT_CONNECTED 4
/**
* Handler for events generated by the SOCKS client.
*
* The event is one of the following:
* - BSOCKSCLIENT_EVENT_ERROR: An error has occured. The object must be freed from the
* job closure of the handler and no further I/O must be attempted.
* - BSOCKSCLIENT_EVENT_ERROR_CLOSED: The server has closed the connection. This event
* can only be reported after BSOCKSCLIENT_EVENT_UP. The object must be freed from
* the job closure of the handler and no further I/O must be attempted.
* - BSOCKSCLIENT_EVENT_UP: The CONNECT or UDP ASSOCIATE operation was successful. In
* the case of CONNECT, application I/O may now begin.
* - BSOCKSCLIENT_EVENT_CONNECTED: The TCP connection to the server has been established
* and the SOCKS protocol is about to begin. The local address of the TCP connection is
* now available via @ref BSocksClient_GetLocalAddr. The job closure of this callback
* is the last chance to call @ref BSocksClient_SetDestAddr.
*
* @param user as in {@link BSocksClient_Init}
* @param event See above.
*/
typedef void (*BSocksClient_handler) (void *user, int event);
struct BSocksClient_auth_info {
int auth_type;
union {
struct {
const char *username;
size_t username_len;
const char *password;
size_t password_len;
} password;
};
};
typedef struct {
const struct BSocksClient_auth_info *auth_info;
size_t num_auth_info;
BAddr dest_addr;
bool udp;
BAddr bind_addr;
BSocksClient_handler handler;
void *user;
BReactor *reactor;
int state;
char *buffer;
BConnector connector;
BConnection con;
BPending continue_job;
union {
struct {
PacketPassInterface *send_if;
PacketStreamSender send_sender;
StreamRecvInterface *recv_if;
uint8_t *recv_dest;
int recv_len;
int recv_total;
} control;
};
DebugError d_err;
DebugObject d_obj;
} BSocksClient;
struct BSocksClient_auth_info BSocksClient_auth_none (void);
struct BSocksClient_auth_info BSocksClient_auth_password (const char *username, size_t username_len, const char *password, size_t password_len);
/**
* Initializes the object.
*
* This object connects to a SOCKS5 server and performs a CONNECT or UDP ASSOCIATE
* operation. In any case, the object reports the BSOCKSCLIENT_EVENT_UP event via the
* handler when the operation was completed successfully. In the case of CONNECT, the
* user may then use the send and receive interfaces to exchange data through the
* connection (@ref BSocksClient_GetSendInterface and @ref BSocksClient_GetRecvInterface).
*
* @param o the object
* @param server_addr SOCKS5 server address
* @param auth_info List of supported authentication methods and associated parameters.
* Initialize these using functions such as BSocksClient_auth_none() and
* BSocksClient_auth_password(). The pointer must remain valid while this object
* exists, the data is not copied.
* @param num_auth_info Number of the above. There should be at least one, otherwise it
* certainly won't work.
* @param dest_addr Address to send as DST.ADDR in the CONNECT or UDP ASSOCIATE request.
* It is also possible to specify it later from the BSOCKSCLIENT_EVENT_CONNECTED
* event callback using @ref BSocksClient_SetDestAddr; this is necessary for UDP
* if the local TCP connection address must be known to bind the UDP socket.
* @param udp false to perform a CONNECT, true to perform a UDP ASSOCIATE
* @param handler handler for up and error events
* @param user value passed to handler
* @param reactor reactor we live in
* @return 1 on success, 0 on failure
*/
int BSocksClient_Init (BSocksClient *o, BAddr server_addr,
const struct BSocksClient_auth_info *auth_info, size_t num_auth_info, BAddr dest_addr,
bool udp, BSocksClient_handler handler, void *user, BReactor *reactor) WARN_UNUSED;
/**
* Frees the object.
*
* @param o the object
*/
void BSocksClient_Free (BSocksClient *o);
/**
* Get the local address of the TCP socket for the SOCKS server connection.
*
* This may only be called after the BSOCKSCLIENT_EVENT_CONNECTED event was reported.
*
* @param o the object
* @param local_addr On success the local address is returned here.
* @return 1 on success, 0 on failure
*/
int BSocksClient_GetLocalAddr (BSocksClient *o, BAddr *local_addr);
/**
* Set the DST.ADDR to send, overriding that specified in @ref BSocksClient_Init.
*
* The last chance to call this function is in the job closure of the
* BSOCKSCLIENT_EVENT_CONNECTED event, this must not be called after that.
*
* @param o the object
* @param dest_addr DST.ADDR to set.
*/
void BSocksClient_SetDestAddr (BSocksClient *o, BAddr dest_addr);
/**
* Return the BND.ADDR that the SOCKS server reported.
*
* This may only be called after the BSOCKSCLIENT_EVENT_UP event was reported.
* This address is needed for UDP ASSOCIATE because it is the address that the
* client should send UDP packets to.
*
* @param o the object
* @return The BND.ADDR, of type BADDR_TYPE_IPV4 or BADDR_TYPE_IPV6.
*/
BAddr BSocksClient_GetBindAddr (BSocksClient *o);
/**
* Returns the send interface.
* The object must be in up state. Additionally this must not be called if the
* object was initialized in UDP ASSOCIATE mode.
*
* @param o the object
* @return send interface
*/
StreamPassInterface * BSocksClient_GetSendInterface (BSocksClient *o);
/**
* Returns the receive interface.
* The object must be in up state. Additionally this must not be called if the
* object was initialized in UDP ASSOCIATE mode.
*
* @param o the object
* @return receive interface
*/
StreamRecvInterface * BSocksClient_GetRecvInterface (BSocksClient *o);
#endif