Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/ambrop72/badvpn.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAmbroz Bizjak <abizjak.pro@gmail.com>2020-02-02 01:35:35 +0300
committerAmbroz Bizjak <abizjak.pro@gmail.com>2020-02-02 02:02:11 +0300
commite837e8d552156e26ed52a67923a91268d6e1192a (patch)
treea05d9f8d9d8bfa382cc4ff4644868a6e0d5142a7
parent6241fc29783a68934ce6ab979915abc8845900a2 (diff)
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.
-rw-r--r--socks_udp_client/SocksUdpClient.c81
-rw-r--r--socks_udp_client/SocksUdpClient.h7
-rw-r--r--socksclient/BSocksClient.c121
-rw-r--r--socksclient/BSocksClient.h77
-rw-r--r--system/BConnection.h13
-rw-r--r--system/BConnection_unix.c24
-rw-r--r--system/BConnection_win.c25
-rw-r--r--tun2socks/SocksUdpGwClient.c2
-rw-r--r--tun2socks/tun2socks.c3
9 files changed, 254 insertions, 99 deletions
diff --git a/socks_udp_client/SocksUdpClient.c b/socks_udp_client/SocksUdpClient.c
index a7446da..661d351 100644
--- a/socks_udp_client/SocksUdpClient.c
+++ b/socks_udp_client/SocksUdpClient.c
@@ -83,17 +83,52 @@ void socks_state_handler (struct SocksUdpClient_connection *con, int event)
DebugObject_Access(&con->client->d_obj);
switch (event) {
- case BSOCKSCLIENT_EVENT_UP: {
- // Figure out the localhost address.
- BIPAddr localhost;
- BIPAddr_InitLocalhost(&localhost, con->client->server_addr.type);
+ case BSOCKSCLIENT_EVENT_CONNECTED: {
+ // Get the local address of the SOCKS TCP connection.
+ BAddr tcp_local_addr;
+ if (!BSocksClient_GetLocalAddr(&con->socks, &tcp_local_addr)) {
+ BLog(BLOG_ERROR, "Failed to get TCP local address.");
+ return connection_free(con);
+ }
+
+ // Sanity check the address type (required by SetPort below).
+ if (tcp_local_addr.type != BADDR_TYPE_IPV4 &&
+ tcp_local_addr.type != BADDR_TYPE_IPV6)
+ {
+ BLog(BLOG_ERROR, "Bad address type in TCP local address.");
+ return connection_free(con);
+ }
+
+ // Bind the UDP socket to the same IP address and let the kernel pick the port.
+ BAddr udp_bound_addr = tcp_local_addr;
+ BAddr_SetPort(&udp_bound_addr, 0);
+ if (!BDatagram_Bind(&con->socket, udp_bound_addr)) {
+ BLog(BLOG_ERROR, "Failed to bind the UDP socket.");
+ return connection_free(con);
+ }
+
+ // Update udp_bound_addr to the actual address that was bound.
+ if (!BDatagram_GetLocalAddr(&con->socket, &udp_bound_addr)) {
+ BLog(BLOG_ERROR, "Failed to get UDP bound address.");
+ return connection_free(con);
+ }
+
+ // Set the DST.ADDR for SOCKS.
+ BSocksClient_SetDestAddr(&con->socks, udp_bound_addr);
+ } break;
- // Get the address to send datagrams to from BSocksClient.
+ case BSOCKSCLIENT_EVENT_UP: {
+ // The remote address to send datagrams to is the BND.ADDR provided by the
+ // SOCKS server.
BAddr remote_addr = BSocksClient_GetBindAddr(&con->socks);
- // Set the local/remote send address for BDatagram.
+ // Don't bother setting a source address for datagrams since we are bound.
+ BIPAddr local_addr;
+ BIPAddr_InitInvalid(&local_addr);
+
+ // Set the addresses for BDatagram.
// This will unblock the queue of outgoing packets.
- BDatagram_SetSendAddrs(&con->socket, remote_addr, localhost);
+ BDatagram_SetSendAddrs(&con->socket, remote_addr, local_addr);
} break;
case BSOCKSCLIENT_EVENT_ERROR: {
@@ -113,10 +148,6 @@ void socks_state_handler (struct SocksUdpClient_connection *con, int event)
connection_free(con);
} break;
-
- default: {
- BLog(BLOG_ERROR, "Unknown SOCKS event");
- } break;
}
}
@@ -294,31 +325,13 @@ struct SocksUdpClient_connection * connection_init (
goto fail2;
}
- // Bind to localhost, port 0 signals the kernel to choose an open port.
- BIPAddr localhost;
- BIPAddr_InitLocalhost(&localhost, local_addr.type);
- BAddr socket_addr = BAddr_MakeFromIpaddrAndPort(localhost, 0);
- if (!BDatagram_Bind(&con->socket, socket_addr)) {
- BLog(BLOG_ERROR, "Bind to localhost failed");
- goto fail3;
- }
-
- // Bind succeeded, so the kernel has found an open port.
- // Update socket_addr to the actual port that was bound.
- uint16_t port;
- if (!BDatagram_GetLocalPort(&con->socket, &port)) {
- BLog(BLOG_ERROR, "Failed to get bound port");
- goto fail3;
- }
- if (socket_addr.type == BADDR_TYPE_IPV4) {
- socket_addr.ipv4.port = port;
- } else {
- socket_addr.ipv6.port = port;
- }
-
+ // We will set the DST.ADDR for SOCKS later (BSOCKSCLIENT_EVENT_CONNECTED).
+ BAddr dummy_dst_addr;
+ BAddr_InitNone(&dummy_dst_addr);
+
// Initiate connection to socks server
if (!BSocksClient_Init(&con->socks, o->server_addr, o->auth_info, o->num_auth_info,
- socket_addr, true, (BSocksClient_handler)socks_state_handler, con, o->reactor))
+ dummy_dst_addr, true, (BSocksClient_handler)socks_state_handler, con, o->reactor))
{
BLog(BLOG_ERROR, "Failed to initialize SOCKS client");
goto fail3;
diff --git a/socks_udp_client/SocksUdpClient.h b/socks_udp_client/SocksUdpClient.h
index b81c2ea..52ded10 100644
--- a/socks_udp_client/SocksUdpClient.h
+++ b/socks_udp_client/SocksUdpClient.h
@@ -94,17 +94,12 @@ struct SocksUdpClient_connection {
*
* This function only initialzies the object and does not perform network access.
*
- * Currently, this function only supports connection to a SOCKS5 server that is routable from
- * localhost (i.e. running on the local machine). It may be possible to add support for
- * remote servers, but SOCKS5 does not support UDP if there is a NAT or firewall between the
- * client and the proxy.
- *
* @param o the object
* @param udp_mtu the maximum size of packets that will be sent through the tunnel
* @param max_connections how many local ports to track before dropping packets
* @param send_buf_size maximum number of buffered outgoing packets per connection
* @param keepalive_time how long to track an idle local port before forgetting it
- * @param server_addr SOCKS5 server address. MUST BE ON LOCALHOST.
+ * @param server_addr SOCKS5 server address
* @param auth_info List of authentication info for BSocksClient. The pointer must remain
* valid while this object exists, the data is not copied.
* @param num_auth_info Number of the above.
diff --git a/socksclient/BSocksClient.c b/socksclient/BSocksClient.c
index f068215..e87bf54 100644
--- a/socksclient/BSocksClient.c
+++ b/socksclient/BSocksClient.c
@@ -38,14 +38,15 @@
#include <generated/blog_channel_BSocksClient.h>
#define STATE_CONNECTING 1
-#define STATE_SENDING_HELLO 2
-#define STATE_SENT_HELLO 3
-#define STATE_SENDING_PASSWORD 10
-#define STATE_SENT_PASSWORD 11
-#define STATE_SENDING_REQUEST 4
-#define STATE_SENT_REQUEST 5
-#define STATE_RECEIVED_REPLY_HEADER 6
-#define STATE_UP 7
+#define STATE_CONNECTED_HANDLER 2
+#define STATE_SENDING_HELLO 3
+#define STATE_SENT_HELLO 4
+#define STATE_SENDING_PASSWORD 5
+#define STATE_SENT_PASSWORD 6
+#define STATE_SENDING_REQUEST 7
+#define STATE_SENT_REQUEST 8
+#define STATE_RECEIVED_REPLY_HEADER 9
+#define STATE_UP 10
static void report_error (BSocksClient *o, int error);
static void init_control_io (BSocksClient *o);
@@ -57,6 +58,7 @@ static void start_receive (BSocksClient *o, uint8_t *dest, int total);
static void do_receive (BSocksClient *o);
static void connector_handler (BSocksClient* o, int is_error);
static void connection_handler (BSocksClient* o, int event);
+static void continue_job_handler (BSocksClient *o);
static void recv_handler_done (BSocksClient *o, int data_len);
static void send_handler_done (BSocksClient *o);
static void auth_finished (BSocksClient *p);
@@ -166,12 +168,45 @@ void connector_handler (BSocksClient* o, int is_error)
// init control I/O
init_control_io(o);
+ // go to STATE_CONNECTED_HANDLER and set the continue job in order to continue
+ // in continue_job_handler
+ o->state = STATE_CONNECTED_HANDLER;
+ BPending_Set(&o->continue_job);
+
+ // call the handler with the connected event
+ o->handler(o->user, BSOCKSCLIENT_EVENT_CONNECTED);
+ return;
+
+fail0:
+ report_error(o, BSOCKSCLIENT_EVENT_ERROR);
+ return;
+}
+
+void connection_handler (BSocksClient* o, int event)
+{
+ DebugObject_Access(&o->d_obj);
+ ASSERT(o->state != STATE_CONNECTING)
+
+ if (o->state == STATE_UP && event == BCONNECTION_EVENT_RECVCLOSED) {
+ report_error(o, BSOCKSCLIENT_EVENT_ERROR_CLOSED);
+ return;
+ }
+
+ report_error(o, BSOCKSCLIENT_EVENT_ERROR);
+ return;
+}
+
+void continue_job_handler (BSocksClient *o)
+{
+ DebugObject_Access(&o->d_obj);
+ ASSERT(o->state == STATE_CONNECTED_HANDLER)
+
// check number of methods
if (o->num_auth_info == 0 || o->num_auth_info > 255) {
BLog(BLOG_ERROR, "invalid number of authentication methods");
- goto fail1;
+ goto fail0;
}
-
+
// allocate buffer for sending hello
bsize_t size = bsize_add(
bsize_fromsize(sizeof(struct socks_client_hello_header)),
@@ -181,7 +216,7 @@ void connector_handler (BSocksClient* o, int is_error)
)
);
if (!reserve_buffer(o, size)) {
- goto fail1;
+ goto fail0;
}
// write hello header
@@ -202,27 +237,10 @@ void connector_handler (BSocksClient* o, int is_error)
// set state
o->state = STATE_SENDING_HELLO;
-
- return;
-
-fail1:
- free_control_io(o);
- BConnection_Free(&o->con);
-fail0:
- report_error(o, BSOCKSCLIENT_EVENT_ERROR);
+
return;
-}
-void connection_handler (BSocksClient* o, int event)
-{
- DebugObject_Access(&o->d_obj);
- ASSERT(o->state != STATE_CONNECTING)
-
- if (o->state == STATE_UP && event == BCONNECTION_EVENT_RECVCLOSED) {
- report_error(o, BSOCKSCLIENT_EVENT_ERROR_CLOSED);
- return;
- }
-
+fail0:
report_error(o, BSOCKSCLIENT_EVENT_ERROR);
return;
}
@@ -491,8 +509,16 @@ void auth_finished (BSocksClient *o)
// allocate request buffer
bsize_t size = bsize_fromsize(sizeof(struct socks_request_header));
switch (o->dest_addr.type) {
- case BADDR_TYPE_IPV4: size = bsize_add(size, bsize_fromsize(sizeof(struct socks_addr_ipv4))); break;
- case BADDR_TYPE_IPV6: size = bsize_add(size, bsize_fromsize(sizeof(struct socks_addr_ipv6))); break;
+ case BADDR_TYPE_IPV4:
+ size = bsize_add(size, bsize_fromsize(sizeof(struct socks_addr_ipv4)));
+ break;
+ case BADDR_TYPE_IPV6:
+ size = bsize_add(size, bsize_fromsize(sizeof(struct socks_addr_ipv6)));
+ break;
+ default:
+ BLog(BLOG_ERROR, "Invalid dest_addr address type.");
+ report_error(o, BSOCKSCLIENT_EVENT_ERROR);
+ return;
}
if (!reserve_buffer(o, size)) {
report_error(o, BSOCKSCLIENT_EVENT_ERROR);
@@ -549,12 +575,11 @@ struct BSocksClient_auth_info BSocksClient_auth_password (const char *username,
return info;
}
-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)
+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)
{
ASSERT(!BAddr_IsInvalid(&server_addr))
- ASSERT(dest_addr.type == BADDR_TYPE_IPV4 || dest_addr.type == BADDR_TYPE_IPV6)
#ifndef NDEBUG
for (size_t i = 0; i < num_auth_info; i++) {
ASSERT(auth_info[i].auth_type == SOCKS_METHOD_NO_AUTHENTICATION_REQUIRED ||
@@ -573,6 +598,10 @@ int BSocksClient_Init (BSocksClient *o,
// set no buffer
o->buffer = NULL;
+
+ // init continue_job
+ BPending_Init(&o->continue_job, BReactor_PendingGroup(o->reactor),
+ (BPending_handler)continue_job_handler, o);
// init connector
if (!BConnector_Init(&o->connector, server_addr, o->reactor, o, (BConnector_handler)connector_handler)) {
@@ -588,6 +617,7 @@ int BSocksClient_Init (BSocksClient *o,
return 1;
fail0:
+ BPending_Free(&o->continue_job);
return 0;
}
@@ -612,12 +642,31 @@ void BSocksClient_Free (BSocksClient *o)
// free connector
BConnector_Free(&o->connector);
+ // free continue job
+ BPending_Free(&o->continue_job);
+
// free buffer
if (o->buffer) {
BFree(o->buffer);
}
}
+int BSocksClient_GetLocalAddr (BSocksClient *o, BAddr *local_addr)
+{
+ ASSERT(o->state != STATE_CONNECTING)
+ DebugObject_Access(&o->d_obj);
+
+ return BConnection_GetLocalAddress(&o->con, local_addr);
+}
+
+void BSocksClient_SetDestAddr (BSocksClient *o, BAddr dest_addr)
+{
+ ASSERT(o->state == STATE_CONNECTING || o->state == STATE_CONNECTED_HANDLER)
+ DebugObject_Access(&o->d_obj);
+
+ o->dest_addr = dest_addr;
+}
+
BAddr BSocksClient_GetBindAddr (BSocksClient *o)
{
ASSERT(o->state == STATE_UP)
diff --git a/socksclient/BSocksClient.h b/socksclient/BSocksClient.h
index 0936807..5311e40 100644
--- a/socksclient/BSocksClient.h
+++ b/socksclient/BSocksClient.h
@@ -43,24 +43,33 @@
#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 event type. One of BSOCKSCLIENT_EVENT_ERROR, BSOCKSCLIENT_EVENT_UP
- * and BSOCKSCLIENT_EVENT_ERROR_CLOSED.
- * If event is BSOCKSCLIENT_EVENT_UP, the object was previously in down
- * state and has transitioned to up state; I/O can be done from this point on.
- * If event is BSOCKSCLIENT_EVENT_ERROR or BSOCKSCLIENT_EVENT_ERROR_CLOSED,
- * the object must be freed from within the job closure of this handler,
- * and no further I/O must be attempted.
+ * @param event See above.
*/
typedef void (*BSocksClient_handler) (void *user, int event);
@@ -89,6 +98,7 @@ typedef struct {
char *buffer;
BConnector connector;
BConnection con;
+ BPending continue_job;
union {
struct {
PacketPassInterface *send_if;
@@ -108,8 +118,12 @@ struct BSocksClient_auth_info BSocksClient_auth_password (const char *username,
/**
* Initializes the object.
- * The object is initialized in down state. The object must transition to up
- * state before the user may begin any I/O.
+ *
+ * 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
@@ -119,16 +133,19 @@ struct BSocksClient_auth_info BSocksClient_auth_password (const char *username,
* 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 remote address
- * @param udp whether to do UDP ASSOCIATE instead of CONNECT
+ * @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;
+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.
@@ -138,12 +155,36 @@ int BSocksClient_Init (BSocksClient *o,
void BSocksClient_Free (BSocksClient *o);
/**
- * Return the bind address that the SOCKS server reported.
- * The object must be in up state. The bind address is needed for UDP ASSOCIATE
- * because it is the address that the client should send UDP packets to.
+ * 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 bind address, of type BADDR_TYPE_IPV4 or BADDR_TYPE_IPV6.
+ * @return The BND.ADDR, of type BADDR_TYPE_IPV4 or BADDR_TYPE_IPV6.
*/
BAddr BSocksClient_GetBindAddr (BSocksClient *o);
diff --git a/system/BConnection.h b/system/BConnection.h
index 0b2ca6c..e3d6a9e 100644
--- a/system/BConnection.h
+++ b/system/BConnection.h
@@ -360,6 +360,19 @@ void BConnection_SetHandlers (BConnection *o, void *user, BConnection_handler ha
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.
*
diff --git a/system/BConnection_unix.c b/system/BConnection_unix.c
index fc1e294..8c8d86c 100644
--- a/system/BConnection_unix.c
+++ b/system/BConnection_unix.c
@@ -876,6 +876,30 @@ int BConnection_SetSendBuffer (BConnection *o, int buf_size)
return 1;
}
+int BConnection_GetLocalAddress (BConnection *o, BAddr *local_addr)
+{
+ DebugObject_Access(&o->d_obj);
+
+ struct sys_addr sysaddr;
+ sysaddr.len = sizeof(sysaddr.addr);
+ if (getsockname(o->fd, &sysaddr.addr.generic, &sysaddr.len) != 0) {
+ BLog(BLOG_ERROR, "BConnection_GetLocalAddress: getsockname failed");
+ return 0;
+ }
+
+ BAddr addr;
+ addr_sys_to_socket(&addr, sysaddr);
+
+ if (addr.type == BADDR_TYPE_NONE) {
+ BLog(BLOG_ERROR, "BConnection_GetLocalAddress: Unsupported address family "
+ "from getsockname: %d", (int)sysaddr.addr.generic.sa_family);
+ return 0;
+ }
+
+ *local_addr = addr;
+ return 1;
+}
+
void BConnection_SendAsync_Init (BConnection *o)
{
DebugObject_Access(&o->d_obj);
diff --git a/system/BConnection_win.c b/system/BConnection_win.c
index 1f3f900..a5fac7e 100644
--- a/system/BConnection_win.c
+++ b/system/BConnection_win.c
@@ -792,6 +792,31 @@ int BConnection_SetSendBuffer (BConnection *o, int buf_size)
return 1;
}
+int BConnection_GetLocalAddress (BConnection *o, BAddr *local_addr)
+{
+ DebugObject_Access(&o->d_obj);
+
+ struct BDatagram_sys_addr sysaddr;
+ socklen_t addr_size = sizeof(sysaddr.addr.generic);
+ if (getsockname(o->sock, &sysaddr.addr.generic, &addr_size) != 0) {
+ BLog(BLOG_ERROR, "BConnection_GetLocalAddress: getsockname failed");
+ return 0;
+ }
+ sysaddr.len = addr_size;
+
+ BAddr addr;
+ addr_sys_to_socket(&addr, sysaddr);
+
+ if (addr.type == BADDR_TYPE_NONE) {
+ BLog(BLOG_ERROR, "BConnection_GetLocalAddress: Unsupported address family "
+ "from getsockname: %d", int(sysaddr.addr.generic.sa_family));
+ return 0;
+ }
+
+ *local_addr = addr;
+ return 1;
+}
+
void BConnection_SendAsync_Init (BConnection *o)
{
DebugObject_Access(&o->d_obj);
diff --git a/tun2socks/SocksUdpGwClient.c b/tun2socks/SocksUdpGwClient.c
index 0d38e22..61c8b9d 100644
--- a/tun2socks/SocksUdpGwClient.c
+++ b/tun2socks/SocksUdpGwClient.c
@@ -132,8 +132,6 @@ static void socks_client_handler (SocksUdpGwClient *o, int event)
// set reconnect timer
BReactor_SetTimer(o->reactor, &o->reconnect_timer);
} break;
-
- default: ASSERT(0);
}
}
diff --git a/tun2socks/tun2socks.c b/tun2socks/tun2socks.c
index 12157ca..2f5b2d1 100644
--- a/tun2socks/tun2socks.c
+++ b/tun2socks/tun2socks.c
@@ -1654,9 +1654,6 @@ void client_socks_handler (struct tcp_client *client, int event)
client_free_socks(client);
} break;
-
- default:
- ASSERT(0);
}
}