diff --git a/common/tor.c b/common/tor.c index 7a293f536..3252afa6a 100644 --- a/common/tor.c +++ b/common/tor.c @@ -238,16 +238,6 @@ bool create_tor_hidden_service_conn(struct lightningd * ld) return true; } -bool do_we_use_tor_addr(const struct wireaddr * wireaddr) -{ - for (int i = 0; i < tal_count(wireaddr); i++) { - if ((wireaddr[i].type == ADDR_TYPE_TOR_V2) - || (wireaddr[i].type == ADDR_TYPE_TOR_V3)) - return true; - } - return false; -} - bool check_return_from_service_call(void) { return return_from_service_call; diff --git a/common/tor.h b/common/tor.h index 318c18329..54d4dccc5 100644 --- a/common/tor.h +++ b/common/tor.h @@ -10,5 +10,4 @@ bool check_return_from_service_call(void); bool parse_tor_wireaddr(const char *arg,u8 *ip_ld,u16 *port_ld); bool create_tor_hidden_service_conn(struct lightningd *); -bool do_we_use_tor_addr(const struct wireaddr *wireaddrs); #endif /* LIGHTNING_COMMON_TOR_H */ diff --git a/gossipd/Makefile b/gossipd/Makefile index c9e894c64..5a83ada50 100644 --- a/gossipd/Makefile +++ b/gossipd/Makefile @@ -13,14 +13,15 @@ LIGHTNINGD_GOSSIP_CONTROL_OBJS := $(LIGHTNINGD_GOSSIP_CONTROL_SRC:.c=.o) # gossipd needs these: LIGHTNINGD_GOSSIP_HEADERS := gossipd/gen_gossip_wire.h \ + gossipd/gossip.h \ gossipd/gen_gossip_store.h \ gossipd/gossip_store.h \ gossipd/handshake.h \ gossipd/netaddress.h \ gossipd/routing.h \ + gossipd/tor.h \ gossipd/broadcast.h -LIGHTNINGD_GOSSIP_SRC := gossipd/gossip.c \ - $(LIGHTNINGD_GOSSIP_HEADERS:.h=.c) +LIGHTNINGD_GOSSIP_SRC := $(LIGHTNINGD_GOSSIP_HEADERS:.h=.c) LIGHTNINGD_GOSSIP_OBJS := $(LIGHTNINGD_GOSSIP_SRC:.c=.o) # Make sure these depend on everything. @@ -56,7 +57,6 @@ GOSSIPD_COMMON_OBJS := \ common/status_wire.o \ common/subdaemon.o \ common/timeout.o \ - common/tor.o \ common/type_to_string.o \ common/utils.o \ common/utxo.o \ diff --git a/gossipd/gossip.c b/gossipd/gossip.c index 7c1e24a10..7510d56e2 100644 --- a/gossipd/gossip.c +++ b/gossipd/gossip.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include @@ -34,9 +33,11 @@ #include #include #include +#include #include #include #include +#include #include #include #include @@ -56,174 +57,6 @@ #define GOSSIP_MAX_REACH_ATTEMPTS 10 -#define SOCKS_NOAUTH 0 -#define SOCKS_ERROR 0xff -#define SOCKS_CONNECT 1 -#define SOCKS_TYP_IPV4 1 -#define SOCKS_DOMAIN 3 -#define SOCKS_TYP_IPV6 4 -#define SOCKS_V5 5 - -#define MAX_SIZE_OF_SOCKS5_REQ_OR_RESP 255 -#define SIZE_OF_RESPONSE 4 -#define SIZE_OF_REQUEST 3 -#define SIZE_OF_IPV4_RESPONSE 6 -#define SIZE_OF_IPV6_RESPONSE 18 -#define SOCK_REQ_METH_LEN 3 -#define SOCK_REQ_V5_LEN 5 -#define SOCK_REQ_V5_HEADER_LEN 7 - -/* some crufts can not forward ipv6*/ -#undef BIND_FIRST_TO_IPV6 - -struct reaching_socks { - - u8 buffer[MAX_SIZE_OF_SOCKS5_REQ_OR_RESP]; - size_t hlen; - in_port_t port; - char *host; - struct reaching *reach; -}; - -static struct io_plan *connect_finish(struct io_conn *, - struct reaching_socks *); - -static struct io_plan *connect_finish2(struct io_conn *, - struct reaching_socks *); - -static struct io_plan *connect_out(struct io_conn *, struct reaching_socks *); - -static struct io_plan *io_tor_connect_after_req_to_connect(struct io_conn *, - struct reaching_socks - *); -static struct io_plan *io_tor_connect_after_req_host(struct io_conn *, - struct reaching_socks *); - -static struct io_plan *io_tor_connect_do_req(struct io_conn *, - struct reaching_socks *); - -static struct io_plan *connect_out(struct io_conn *, struct reaching_socks *); - -static struct io_plan *io_tor_connect_do_req(struct io_conn *, - struct reaching_socks *); - -static struct io_plan *io_tor_connect_after_resp_to_connect(struct io_conn - *conn, - struct - reaching_socks *); - -static struct io_plan *io_tor_connect(struct io_conn *, struct reaching *); - -static struct io_plan *io_tor_connect_after_resp_to_connect(struct io_conn - *conn, - struct - reaching_socks - *reach) -{ - if (reach->buffer[1] == SOCKS_ERROR) { - status_trace("Connected out for %s error", reach->host); - return io_close(conn); - } - /* make the V5 request */ - reach->hlen = strlen(reach->host); - reach->buffer[0] = SOCKS_V5; - reach->buffer[1] = SOCKS_CONNECT; - reach->buffer[2] = 0; - reach->buffer[3] = SOCKS_DOMAIN; - reach->buffer[4] = reach->hlen; - - memcpy(reach->buffer + SOCK_REQ_V5_LEN, reach->host, reach->hlen); - memcpy(reach->buffer + SOCK_REQ_V5_LEN + strlen(reach->host), - &(reach->port), sizeof reach->port); - - return io_write(conn, reach->buffer, - SOCK_REQ_V5_HEADER_LEN + reach->hlen, - io_tor_connect_after_req_host, reach); -} - -static struct io_plan *io_tor_connect_after_req_to_connect(struct io_conn *conn, - struct reaching_socks - *reach) -{ - - return io_read(conn, reach->buffer, 2, - &io_tor_connect_after_resp_to_connect, reach); -} - -static struct io_plan *io_tor_connect_do_req(struct io_conn *conn, - struct reaching_socks *reach) -{ - /* make the init request */ - reach->buffer[0] = SOCKS_V5; - reach->buffer[1] = 1; - reach->buffer[2] = SOCKS_NOAUTH; - - return io_write(conn, reach->buffer, SOCK_REQ_METH_LEN, - &io_tor_connect_after_req_to_connect, reach); -} - -static struct io_plan *connection_out(struct io_conn *conn, - struct reaching *reach); - -static struct io_plan *connect_finish2(struct io_conn *conn, - struct reaching_socks *reach) -{ - status_trace("Now try LN connect out for host %s", reach->host); - return connection_out(conn, reach->reach); -} - -static struct io_plan *connect_finish(struct io_conn *conn, - struct reaching_socks *reach) -{ - - if ( reach->buffer[1] == '\0') { - if ( reach->buffer[3] == SOCKS_TYP_IPV6) { - return io_read(conn, - (reach->buffer + SIZE_OF_RESPONSE - - SIZE_OF_IPV4_RESPONSE), - SIZE_OF_IPV6_RESPONSE - - SIZE_OF_RESPONSE - SIZE_OF_IPV4_RESPONSE, - &connect_finish2, reach); - - } else if ( reach->buffer[3] == SOCKS_TYP_IPV4) { - status_trace("Now try LN connect out for host %s", - reach->host); - return connection_out(conn, reach->reach); - } else { - status_trace - ("Tor connect out for host %s error invalid type return ", - reach->host); - return io_close(conn); - } - } else { - status_trace("Tor connect out for host %s error: %x ", - reach->host, reach->buffer[1]); - return io_close(conn); - } -} - -static struct io_plan *connect_out(struct io_conn *conn, - struct reaching_socks *reach) -{ - return io_read(conn, reach->buffer, - SIZE_OF_IPV4_RESPONSE + SIZE_OF_RESPONSE, - &connect_finish, reach); - -} - -/* called when TOR responds */ -static struct io_plan *io_tor_connect_after_req_host(struct io_conn *conn, - struct reaching_socks - *reach) -{ - if (reach->buffer[0] == '0') { - status_trace("Connected out over tor for %s failed", - reach->host); - return io_close(conn); - } - return connect_out(conn, reach); -} - #define HSM_FD 3 #define INITIAL_WAIT_SECONDS 1 @@ -404,49 +237,6 @@ static bool send_peer_with_fds(struct peer *peer, const u8 *msg); static void wake_pkt_out(struct peer *peer); static void retry_important(struct important_peerid *imp); -// called when we want to connect to TOR SOCKS5 -static struct io_plan *io_tor_connect(struct io_conn *conn, - struct reaching *reach) -{ - struct addrinfo *ai_tor = tal(reach, struct addrinfo); - char *port_addr = tal(reach, char); - struct io_plan *plan; - struct reaching_socks *reach_tor = tal(reach, struct reaching_socks); - - assert(reach->addr.itype == ADDR_INTERNAL_WIREADDR); - reach_tor->port = htons(reach->addr.u.wireaddr.port); - port_addr = tal_fmt(reach, "%u", reach->daemon->tor_proxyaddrs->port); - getaddrinfo((char *) - fmt_wireaddr_without_port(tmpctx, - reach->daemon->tor_proxyaddrs), - port_addr, NULL, &ai_tor); - status_trace("Tor proxyaddr : %s", - fmt_wireaddr(reach, reach->daemon->tor_proxyaddrs)); - reach_tor->host = tal_strdup(reach, ""); - - if ((reach->addr.u.wireaddr.type) == ADDR_TYPE_TOR_V3) - reach_tor->host = - tal_fmt(reach, "%.62s", - fmt_wireaddr_without_port(tmpctx, &reach->addr.u.wireaddr)); - else if ((reach->addr.u.wireaddr.type) == ADDR_TYPE_TOR_V2) - reach_tor->host = - tal_fmt(reach, "%.22s", - fmt_wireaddr_without_port(tmpctx, &reach->addr.u.wireaddr)); - else if ((reach->addr.u.wireaddr.type) == ADDR_TYPE_IPV4) - reach_tor->host = - tal_fmt(reach, "%s", - fmt_wireaddr_without_port(tmpctx, &reach->addr.u.wireaddr)); - else if ((reach->addr.u.wireaddr.type) == ADDR_TYPE_IPV6) - reach_tor->host = - tal_fmt(reach, "%s", - fmt_wireaddr_without_port(tmpctx, &reach->addr.u.wireaddr)); - reach_tor->reach = reach; - - plan = io_connect(conn, ai_tor, &io_tor_connect_do_req, reach_tor); - - return plan; -} - static void destroy_peer(struct peer *peer) { struct important_peerid *imp; @@ -2040,8 +1830,7 @@ static struct io_plan *handshake_out_success(struct io_conn *conn, } -static struct io_plan *connection_out(struct io_conn *conn, - struct reaching *reach) +struct io_plan *connection_out(struct io_conn *conn, struct reaching *reach) { /* FIXME: Timeout */ status_trace("Connected out for %s", @@ -2149,8 +1938,11 @@ static struct io_plan *conn_init(struct io_conn *conn, struct reaching *reach) } io_set_finish(conn, connect_failed, reach); - if (use_tor) - return io_tor_connect(conn, reach); + if (use_tor) { + assert(reach->addr.itype == ADDR_INTERNAL_WIREADDR); + return io_tor_connect(conn, reach->daemon->tor_proxyaddrs, + &reach->addr.u.wireaddr, reach); + } return io_connect(conn, &ai, connection_out, reach); } diff --git a/gossipd/gossip.h b/gossipd/gossip.h new file mode 100644 index 000000000..70c8377bf --- /dev/null +++ b/gossipd/gossip.h @@ -0,0 +1,10 @@ +#ifndef LIGHTNING_GOSSIPD_GOSSIP_H +#define LIGHTNING_GOSSIPD_GOSSIP_H +#include "config.h" + +struct io_conn; +struct reaching; + +struct io_plan *connection_out(struct io_conn *conn, struct reaching *reach); + +#endif /* LIGHTNING_GOSSIPD_GOSSIP_H */ diff --git a/gossipd/tor.c b/gossipd/tor.c new file mode 100644 index 000000000..4f9595090 --- /dev/null +++ b/gossipd/tor.c @@ -0,0 +1,230 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SOCKS_NOAUTH 0 +#define SOCKS_ERROR 0xff +#define SOCKS_CONNECT 1 +#define SOCKS_TYP_IPV4 1 +#define SOCKS_DOMAIN 3 +#define SOCKS_TYP_IPV6 4 +#define SOCKS_V5 5 + +#define MAX_SIZE_OF_SOCKS5_REQ_OR_RESP 255 +#define SIZE_OF_RESPONSE 4 +#define SIZE_OF_REQUEST 3 +#define SIZE_OF_IPV4_RESPONSE 6 +#define SIZE_OF_IPV6_RESPONSE 18 +#define SOCK_REQ_METH_LEN 3 +#define SOCK_REQ_V5_LEN 5 +#define SOCK_REQ_V5_HEADER_LEN 7 + +/* some crufts can not forward ipv6*/ +#undef BIND_FIRST_TO_IPV6 + +struct reaching_socks { + u8 buffer[MAX_SIZE_OF_SOCKS5_REQ_OR_RESP]; + size_t hlen; + in_port_t port; + char *host; + struct reaching *reach; +}; + +static struct io_plan *connect_finish(struct io_conn *, + struct reaching_socks *); + +static struct io_plan *connect_finish2(struct io_conn *, + struct reaching_socks *); + +static struct io_plan *connect_out(struct io_conn *, struct reaching_socks *); + +static struct io_plan *io_tor_connect_after_req_to_connect(struct io_conn *, + struct reaching_socks + *); +static struct io_plan *io_tor_connect_after_req_host(struct io_conn *, + struct reaching_socks *); + +static struct io_plan *io_tor_connect_do_req(struct io_conn *, + struct reaching_socks *); + +static struct io_plan *connect_out(struct io_conn *, struct reaching_socks *); + +static struct io_plan *io_tor_connect_do_req(struct io_conn *, + struct reaching_socks *); + +static struct io_plan *io_tor_connect_after_resp_to_connect(struct io_conn + *conn, + struct + reaching_socks *); + +static struct io_plan *io_tor_connect_after_resp_to_connect(struct io_conn + *conn, + struct + reaching_socks + *reach) +{ + if (reach->buffer[1] == SOCKS_ERROR) { + status_trace("Connected out for %s error", reach->host); + return io_close(conn); + } + /* make the V5 request */ + reach->hlen = strlen(reach->host); + reach->buffer[0] = SOCKS_V5; + reach->buffer[1] = SOCKS_CONNECT; + reach->buffer[2] = 0; + reach->buffer[3] = SOCKS_DOMAIN; + reach->buffer[4] = reach->hlen; + + memcpy(reach->buffer + SOCK_REQ_V5_LEN, reach->host, reach->hlen); + memcpy(reach->buffer + SOCK_REQ_V5_LEN + strlen(reach->host), + &(reach->port), sizeof reach->port); + + return io_write(conn, reach->buffer, + SOCK_REQ_V5_HEADER_LEN + reach->hlen, + io_tor_connect_after_req_host, reach); +} + +static struct io_plan *io_tor_connect_after_req_to_connect(struct io_conn *conn, + struct reaching_socks + *reach) +{ + + return io_read(conn, reach->buffer, 2, + &io_tor_connect_after_resp_to_connect, reach); +} + +static struct io_plan *io_tor_connect_do_req(struct io_conn *conn, + struct reaching_socks *reach) +{ + /* make the init request */ + reach->buffer[0] = SOCKS_V5; + reach->buffer[1] = 1; + reach->buffer[2] = SOCKS_NOAUTH; + + return io_write(conn, reach->buffer, SOCK_REQ_METH_LEN, + &io_tor_connect_after_req_to_connect, reach); +} + +static struct io_plan *connect_finish2(struct io_conn *conn, + struct reaching_socks *reach) +{ + status_trace("Now try LN connect out for host %s", reach->host); + return connection_out(conn, reach->reach); +} + +static struct io_plan *connect_finish(struct io_conn *conn, + struct reaching_socks *reach) +{ + + if ( reach->buffer[1] == '\0') { + if ( reach->buffer[3] == SOCKS_TYP_IPV6) { + return io_read(conn, + (reach->buffer + SIZE_OF_RESPONSE - + SIZE_OF_IPV4_RESPONSE), + SIZE_OF_IPV6_RESPONSE - + SIZE_OF_RESPONSE - SIZE_OF_IPV4_RESPONSE, + &connect_finish2, reach); + + } else if ( reach->buffer[3] == SOCKS_TYP_IPV4) { + status_trace("Now try LN connect out for host %s", + reach->host); + return connection_out(conn, reach->reach); + } else { + status_trace + ("Tor connect out for host %s error invalid type return ", + reach->host); + return io_close(conn); + } + } else { + status_trace("Tor connect out for host %s error: %x ", + reach->host, reach->buffer[1]); + return io_close(conn); + } +} + +static struct io_plan *connect_out(struct io_conn *conn, + struct reaching_socks *reach) +{ + return io_read(conn, reach->buffer, + SIZE_OF_IPV4_RESPONSE + SIZE_OF_RESPONSE, + &connect_finish, reach); + +} + +/* called when TOR responds */ +static struct io_plan *io_tor_connect_after_req_host(struct io_conn *conn, + struct reaching_socks + *reach) +{ + if (reach->buffer[0] == '0') { + status_trace("Connected out over tor for %s failed", + reach->host); + return io_close(conn); + } + return connect_out(conn, reach); +} + +// called when we want to connect to TOR SOCKS5 +struct io_plan *io_tor_connect(struct io_conn *conn, + const struct wireaddr *tor_proxyaddrs, + const struct wireaddr *addr, + struct reaching *reach) +{ + struct addrinfo *ai_tor = tal(reach, struct addrinfo); + char *port_addr = tal(reach, char); + struct io_plan *plan; + struct reaching_socks *reach_tor = tal(reach, struct reaching_socks); + + reach_tor->port = htons(addr->port); + port_addr = tal_fmt(reach, "%u", tor_proxyaddrs->port); + getaddrinfo((char *) + fmt_wireaddr_without_port(tmpctx, + tor_proxyaddrs), + port_addr, NULL, &ai_tor); + status_trace("Tor proxyaddr : %s", + fmt_wireaddr(reach, tor_proxyaddrs)); + reach_tor->host = tal_strdup(reach, ""); + + if (addr->type == ADDR_TYPE_TOR_V3) + reach_tor->host = + tal_fmt(reach, "%.62s", + fmt_wireaddr_without_port(tmpctx, addr)); + else if (addr->type == ADDR_TYPE_TOR_V2) + reach_tor->host = + tal_fmt(reach, "%.22s", + fmt_wireaddr_without_port(tmpctx, addr)); + else if (addr->type == ADDR_TYPE_IPV4) + reach_tor->host = + tal_fmt(reach, "%s", + fmt_wireaddr_without_port(tmpctx, addr)); + else if (addr->type == ADDR_TYPE_IPV6) + reach_tor->host = + tal_fmt(reach, "%s", + fmt_wireaddr_without_port(tmpctx, addr)); + reach_tor->reach = reach; + + plan = io_connect(conn, ai_tor, &io_tor_connect_do_req, reach_tor); + + return plan; +} + +bool do_we_use_tor_addr(const struct wireaddr *wireaddr) +{ + for (int i = 0; i < tal_count(wireaddr); i++) { + if ((wireaddr[i].type == ADDR_TYPE_TOR_V2) + || (wireaddr[i].type == ADDR_TYPE_TOR_V3)) + return true; + } + return false; +} diff --git a/gossipd/tor.h b/gossipd/tor.h new file mode 100644 index 000000000..8b0eb082d --- /dev/null +++ b/gossipd/tor.h @@ -0,0 +1,17 @@ +#ifndef LIGHTNING_GOSSIPD_TOR_H +#define LIGHTNING_GOSSIPD_TOR_H +#include "config.h" +#include + +struct wireaddr; +struct io_conn; +struct reaching; + +bool do_we_use_tor_addr(const struct wireaddr *wireaddrs); + +struct io_plan *io_tor_connect(struct io_conn *conn, + const struct wireaddr *tor_proxyaddrs, + const struct wireaddr *addr, + struct reaching *reach); + +#endif /* LIGHTNING_GOSSIPD_TOR_H */