badvpn/system/BConnection.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

438 lines
14 KiB
C

/**
* @file BConnection.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.
*/
#ifndef BADVPN_SYSTEM_BCONNECTION
#define BADVPN_SYSTEM_BCONNECTION
#include <misc/debug.h>
#include <flow/StreamPassInterface.h>
#include <flow/StreamRecvInterface.h>
#include <system/BAddr.h>
#include <system/BReactor.h>
#include <system/BNetwork.h>
/**
* Checks if the given address is supported by {@link BConnection} and related objects.
*
* @param addr address to check. Must be a proper {@link BAddr} object according to
* {@link BIPAddr_Assert}.
* @return 1 if supported, 0 if not
*/
int BConnection_AddressSupported (BAddr addr);
#define BLISCON_FROM_ADDR 1
#define BLISCON_FROM_UNIX 2
struct BLisCon_from {
int type;
union {
struct {
BAddr addr;
} from_addr;
#ifndef BADVPN_USE_WINAPI
struct {
char const *socket_path;
} from_unix;
#endif
} u;
};
static struct BLisCon_from BLisCon_from_addr (BAddr addr)
{
struct BLisCon_from res;
res.type = BLISCON_FROM_ADDR;
res.u.from_addr.addr = addr;
return res;
}
#ifndef BADVPN_USE_WINAPI
static struct BLisCon_from BLisCon_from_unix (char const *socket_path)
{
struct BLisCon_from res;
res.type = BLISCON_FROM_UNIX;
res.u.from_unix.socket_path = socket_path;
return res;
}
#endif
struct BListener_s;
/**
* Object which listens for connections on an address.
* When a connection is ready, the {@link BListener_handler} handler is called, from which
* the connection can be accepted into a new {@link BConnection} object.
*/
typedef struct BListener_s BListener;
/**
* Handler called when a new connection is ready.
* The connection can be accepted by calling {@link BConnection_Init} with the a
* BCONNECTION_SOURCE_LISTENER 'source' argument.
* If no attempt is made to accept the connection from the job closure of this handler,
* the connection will be discarded.
*
* @param user as in {@link BListener_Init}
*/
typedef void (*BListener_handler) (void *user);
/**
* Common listener initialization function.
*
* The other type-specific init functions are wrappers around this one.
*/
int BListener_InitFrom (BListener *o, struct BLisCon_from from,
BReactor *reactor, void *user,
BListener_handler handler) WARN_UNUSED;
/**
* Initializes the object for listening on an address.
* {@link BNetwork_GlobalInit} must have been done.
*
* @param o the object
* @param addr address to listen on
* @param reactor reactor we live in
* @param user argument to handler
* @param handler handler called when a connection can be accepted
* @return 1 on success, 0 on failure
*/
int BListener_Init (BListener *o, BAddr addr, BReactor *reactor, void *user,
BListener_handler handler) WARN_UNUSED;
#ifndef BADVPN_USE_WINAPI
/**
* Initializes the object for listening on a Unix socket.
* {@link BNetwork_GlobalInit} must have been done.
*
* @param o the object
* @param socket_path socket path for listening
* @param reactor reactor we live in
* @param user argument to handler
* @param handler handler called when a connection can be accepted
* @return 1 on success, 0 on failure
*/
int BListener_InitUnix (BListener *o, const char *socket_path, BReactor *reactor, void *user,
BListener_handler handler) WARN_UNUSED;
#endif
/**
* Frees the object.
*
* @param o the object
*/
void BListener_Free (BListener *o);
struct BConnector_s;
/**
* Object which connects to an address.
* When the connection attempt finishes, the {@link BConnector_handler} handler is called, from which,
* if successful, the resulting connection can be moved to a new {@link BConnection} object.
*/
typedef struct BConnector_s BConnector;
/**
* Handler called when the connection attempt finishes.
* If the connection attempt succeeded (is_error==0), the new connection can be used by calling
* {@link BConnection_Init} with a BCONNECTION_SOURCE_TYPE_CONNECTOR 'source' argument.
* This handler will be called at most once. The connector object need not be freed after it
* is called.
*
* @param user as in {@link BConnector_Init}
* @param is_error whether the connection attempt succeeded (0) or failed (1)
*/
typedef void (*BConnector_handler) (void *user, int is_error);
/**
* Common connector initialization function.
*
* The other type-specific init functions are wrappers around this one.
*/
int BConnector_InitFrom (BConnector *o, struct BLisCon_from from, BReactor *reactor, void *user,
BConnector_handler handler) WARN_UNUSED;
/**
* Initializes the object for connecting to an address.
* {@link BNetwork_GlobalInit} must have been done.
*
* @param o the object
* @param addr address to connect to
* @param reactor reactor we live in
* @param user argument to handler
* @param handler handler called when the connection attempt finishes
* @return 1 on success, 0 on failure
*/
int BConnector_Init (BConnector *o, BAddr addr, BReactor *reactor, void *user,
BConnector_handler handler) WARN_UNUSED;
#ifndef BADVPN_USE_WINAPI
/**
* Initializes the object for connecting to a Unix socket.
* {@link BNetwork_GlobalInit} must have been done.
*
* @param o the object
* @param socket_path socket path for connecting
* @param reactor reactor we live in
* @param user argument to handler
* @param handler handler called when the connection attempt finishes
* @return 1 on success, 0 on failure
*/
int BConnector_InitUnix (BConnector *o, const char *socket_path, BReactor *reactor, void *user,
BConnector_handler handler) WARN_UNUSED;
#endif
/**
* Frees the object.
*
* @param o the object
*/
void BConnector_Free (BConnector *o);
#define BCONNECTION_SOURCE_TYPE_LISTENER 1
#define BCONNECTION_SOURCE_TYPE_CONNECTOR 2
#define BCONNECTION_SOURCE_TYPE_PIPE 3
struct BConnection_source {
int type;
union {
struct {
BListener *listener;
BAddr *out_addr;
} listener;
struct {
BConnector *connector;
} connector;
#ifndef BADVPN_USE_WINAPI
struct {
int pipefd;
int close_it;
} pipe;
#endif
} u;
};
static struct BConnection_source BConnection_source_listener (BListener *listener, BAddr *out_addr)
{
struct BConnection_source s;
s.type = BCONNECTION_SOURCE_TYPE_LISTENER;
s.u.listener.listener = listener;
s.u.listener.out_addr = out_addr;
return s;
}
static struct BConnection_source BConnection_source_connector (BConnector *connector)
{
struct BConnection_source s;
s.type = BCONNECTION_SOURCE_TYPE_CONNECTOR;
s.u.connector.connector = connector;
return s;
}
#ifndef BADVPN_USE_WINAPI
static struct BConnection_source BConnection_source_pipe (int pipefd, int close_it)
{
struct BConnection_source s;
s.type = BCONNECTION_SOURCE_TYPE_PIPE;
s.u.pipe.pipefd = pipefd;
s.u.pipe.close_it = close_it;
return s;
}
#endif
struct BConnection_s;
/**
* Object which represents a stream connection. This is usually a TCP connection, either client
* or server, but may also be used with any file descriptor (e.g. pipe) on Unix-like systems.
* Sending and receiving is performed via {@link StreamPassInterface} and {@link StreamRecvInterface},
* respectively.
*/
typedef struct BConnection_s BConnection;
#define BCONNECTION_EVENT_ERROR 1
#define BCONNECTION_EVENT_RECVCLOSED 2
/**
* Handler called when an error occurs or the receive end of the connection was closed
* by the remote peer.
* - If event is BCONNECTION_EVENT_ERROR, the connection is no longer usable and must be freed
* from withing the job closure of this handler. No further I/O or interface initialization
* must occur.
* - If event is BCONNECTION_EVENT_RECVCLOSED, no further receive I/O or receive interface
* initialization must occur. It is guarantted that the receive interface was initialized.
*
* @param user as in {@link BConnection_Init} or {@link BConnection_SetHandlers}
* @param event what happened - BCONNECTION_EVENT_ERROR or BCONNECTION_EVENT_RECVCLOSED
*/
typedef void (*BConnection_handler) (void *user, int event);
/**
* Initializes the object.
* {@link BNetwork_GlobalInit} must have been done.
*
* @param o the object
* @param source specifies what the connection comes from. This argument must be created with one of the
* following macros:
* - BCONNECTION_SOURCE_LISTENER(BListener *, BAddr *)
* Accepts a connection ready on a {@link BListener} object. Must be called from the job
* closure of the listener's {@link BListener_handler}, and must be the first attempt
* for this handler invocation. The address of the client is written if the address
* argument is not NULL (theoretically an invalid address may be returned).
* - BCONNECTION_SOURCE_CONNECTOR(Bconnector *)
* Uses a connection establised with {@link BConnector}. Must be called from the job
* closure of the connector's {@link BConnector_handler}, the handler must be reporting
* successful connection, and must be the first attempt for this handler invocation.
* - BCONNECTION_SOURCE_PIPE(int pipefd, int close_it)
* On Unix-like systems, uses the provided file descriptor. The file descriptor number must
* be >=0. If close_it is true, the connector will take responsibility of closing the
* pipefd. Note that it will be closed even when this Init fails.
* @param reactor reactor we live in
* @param user argument to handler
* @param handler handler called when an error occurs or the receive end of the connection was closed
* by the remote peer.
* @return 1 on success, 0 on failure
*/
int BConnection_Init (BConnection *o, struct BConnection_source source, BReactor *reactor, void *user,
BConnection_handler handler) WARN_UNUSED;
/**
* Frees the object.
* The send and receive interfaces must not be initialized.
* If the connection was created with a BCONNECTION_SOURCE_PIPE 'source' argument, the file descriptor
* will not be closed.
*
* @param o the object
*/
void BConnection_Free (BConnection *o);
/**
* Updates the handler function.
*
* @param o the object
* @param user argument to handler
* @param handler new handler function, as in {@link BConnection_Init}. Additionally, may be NULL to
* remove the current handler. In this case, a proper handler must be set before anything
* can happen with the connection. This is used when moving the connection ownership from
* one module to another.
*/
void BConnection_SetHandlers (BConnection *o, void *user, BConnection_handler handler);
/**
* Sets the SO_SNDBUF socket option.
*
* @param o the object
* @param buf_size value for SO_SNDBUF option
* @return 1 on success, 0 on failure
*/
int BConnection_SetSendBuffer (BConnection *o, int buf_size);
/**
* Determines the local address.
*
* This calls getsockname() to determine the local address and returns the result as
* BAddr. This function fails if the address cannot be determined or translated to
* BAddr (it never succeeds but returns a BADDR_TYPE_NONE address).
*
* @param o the object
* @param local_addr returns the local bound address.
* @return 1 on success, 0 on failure
*/
int BConnection_GetLocalAddress (BConnection *o, BAddr *local_addr);
/**
* Initializes the send interface for the connection.
* The send interface must not be initialized.
*
* @param o the object
*/
void BConnection_SendAsync_Init (BConnection *o);
/**
* Frees the send interface for the connection.
* The send interface must be initialized.
* If the send interface was busy when this is called, the connection is no longer usable and must be
* freed before any further I/O or interface initialization.
*
* @param o the object
*/
void BConnection_SendAsync_Free (BConnection *o);
/**
* Returns the send interface.
* The send interface must be initialized.
*
* @param o the object
* @return send interface
*/
StreamPassInterface * BConnection_SendAsync_GetIf (BConnection *o);
/**
* Initializes the receive interface for the connection.
* The receive interface must not be initialized.
*
* @param o the object
*/
void BConnection_RecvAsync_Init (BConnection *o);
/**
* Frees the receive interface for the connection.
* The receive interface must be initialized.
* If the receive interface was busy when this is called, the connection is no longer usable and must be
* freed before any further I/O or interface initialization.
*
* @param o the object
*/
void BConnection_RecvAsync_Free (BConnection *o);
/**
* Returns the receive interface.
* The receive interface must be initialized.
*
* @param o the object
* @return receive interface
*/
StreamRecvInterface * BConnection_RecvAsync_GetIf (BConnection *o);
#ifdef BADVPN_USE_WINAPI
#include "BConnection_win.h"
#else
#include "BConnection_unix.h"
#endif
#endif