Created
November 7, 2018 19:41
-
-
Save kaechele/3fbfcc38d5ef509d02bca3251a72cf44 to your computer and use it in GitHub Desktop.
TD v6 Client
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/client/l2tp_client.c b/client/l2tp_client.c | |
index 16fdf3c..6ea2aae 100644 | |
--- a/client/l2tp_client.c | |
+++ b/client/l2tp_client.c | |
@@ -65,6 +65,7 @@ | |
// Overhead of IP and UDP headers for measuring PMTU. | |
#define IPV4_HDR_OVERHEAD 28 | |
+#define IPV6_HDR_OVERHEAD 48 | |
// L2TP data header overhead for calculating tunnel MTU; takes | |
// the following headers into account: | |
@@ -176,7 +177,7 @@ typedef struct { | |
// External hook script. | |
char *hook; | |
// Local IP endpoint. | |
- struct sockaddr_in local_endpoint; | |
+ struct addrinfo *local_endpoint; | |
// Broker hostname. | |
char *broker_hostname; | |
// Broker port (or service name). | |
@@ -360,7 +361,7 @@ void put_u32(char **buffer, uint32_t value) | |
(*buffer) += sizeof(value); | |
} | |
-l2tp_context *context_new(char *uuid, const char *local_ip, const char *broker_hostname, | |
+l2tp_context *context_new(char *uuid, const char *local_addr, const char *broker_hostname, | |
char *broker_port, char *tunnel_iface, char *bind_iface, char *hook, int tunnel_id, int limit_bandwidth_down) | |
{ | |
l2tp_context *ctx = (l2tp_context*) calloc(1, sizeof(l2tp_context)); | |
@@ -371,11 +372,17 @@ l2tp_context *context_new(char *uuid, const char *local_ip, const char *broker_h | |
ctx->state = STATE_REINIT; | |
- ctx->local_endpoint.sin_family = AF_INET; | |
- ctx->local_endpoint.sin_port = 0; | |
- if (inet_aton(local_ip, &ctx->local_endpoint.sin_addr) < 0) { | |
- syslog(LOG_ERR, "Failed to parse local endpoint!"); | |
- goto free_and_return; | |
+ struct addrinfo hints; | |
+ memset(&hints, 0, sizeof(hints)); | |
+ hints.ai_family = AF_UNSPEC; | |
+ hints.ai_socktype = SOCK_DGRAM; | |
+ hints.ai_protocol = 0; | |
+ hints.ai_flags = AI_PASSIVE|AI_ADDRCONFIG; | |
+ struct addrinfo* res = 0; | |
+ int err = getaddrinfo(local_addr, 0, &hints, &ctx->local_endpoint); | |
+ if (err) { | |
+ syslog(LOG_ERR, "Failed to parse or resolve local endpoint! (err=%d/%s)", err, gai_strerror(err)); | |
+ goto free_and_return; | |
} | |
ctx->broker_hostname = strdup(broker_hostname); | |
@@ -421,9 +428,11 @@ int context_reinitialize(l2tp_context *ctx) | |
// because other functions than the state machine call this function. | |
ctx->state = STATE_REINIT; | |
+ struct addrinfo *local_endpoint = ctx->local_endpoint; | |
+ | |
if (ctx->fd > 0) | |
close(ctx->fd); | |
- ctx->fd = socket(AF_INET, SOCK_DGRAM, 0); | |
+ ctx->fd = socket(local_endpoint->ai_family, local_endpoint->ai_socktype, local_endpoint->ai_protocol); | |
if (ctx->fd < 0) | |
return -1; | |
@@ -438,8 +447,9 @@ int context_reinitialize(l2tp_context *ctx) | |
} | |
} | |
- if (bind(ctx->fd, (struct sockaddr*) &ctx->local_endpoint, sizeof(ctx->local_endpoint)) < 0) { | |
- syslog(LOG_ERR, "Failed to bind to local endpoint - check WAN connectivity!"); | |
+ int err = bind(ctx->fd, local_endpoint->ai_addr, local_endpoint->ai_addrlen); | |
+ if (err < 0) { | |
+ syslog(LOG_ERR, "Failed to bind to local endpoint - check WAN connectivity! (err=%s (%d))", strerror(err), err); | |
return -1; | |
} | |
@@ -491,10 +501,16 @@ void context_start_connect(l2tp_context *ctx) | |
if (ctx->state != STATE_RESOLVING) | |
return; | |
+ char *broker_host = ctx->broker_hostname; | |
+ // If this is an IPv6 address we need to cut off the brackets | |
+ if(broker_host[0] == '[') { | |
+ broker_host++[strlen(broker_host)] = 0;; | |
+ } | |
+ | |
memset(&ctx->broker_reshints, 0, sizeof(struct addrinfo)); | |
- ctx->broker_reshints.ai_family = AF_INET; | |
+ ctx->broker_reshints.ai_family = AF_UNSPEC; | |
ctx->broker_reshints.ai_socktype = SOCK_DGRAM; | |
- ctx->broker_resq = asyncns_getaddrinfo(asyncns_context, ctx->broker_hostname, ctx->broker_port, | |
+ ctx->broker_resq = asyncns_getaddrinfo(asyncns_context, broker_host, ctx->broker_port, | |
&ctx->broker_reshints); | |
ctx->timer_resolving = timer_now(); | |
@@ -543,9 +559,9 @@ void context_setup_limits(l2tp_context *ctx) | |
void context_process_control_packet(l2tp_context *ctx) | |
{ | |
char buffer[2048]; | |
- struct sockaddr_in endpoint; | |
+ struct sockaddr_in6 endpoint; | |
socklen_t endpoint_len = sizeof(endpoint); | |
- ssize_t bytes = recvfrom(ctx->fd, &buffer, sizeof(buffer), 0, (struct sockaddr*) &endpoint, | |
+ ssize_t bytes = recvfrom(ctx->fd, &buffer, sizeof(buffer), 0, (struct sockaddr_in6*) &endpoint, | |
&endpoint_len); | |
// A valid package must at least 6 byte long. | |
@@ -661,7 +677,9 @@ void context_process_control_packet(l2tp_context *ctx) | |
if (payload_length != 2) | |
break; | |
// Process a PMTU probe. | |
- uint16_t psize = parse_u16(&buf) + IPV4_HDR_OVERHEAD; | |
+ struct addrinfo *local_endpoint = ctx->local_endpoint; | |
+ int overhead = local_endpoint->ai_family == AF_INET6 ? IPV4_HDR_OVERHEAD : IPV6_HDR_OVERHEAD; | |
+ uint16_t psize = parse_u16(&buf) + overhead; | |
if (psize > ctx->probed_pmtu) | |
ctx->probed_pmtu = psize; | |
} | |
@@ -815,7 +833,9 @@ void context_send_pmtu_probe(l2tp_context *ctx, size_t size) | |
put_u8(&buf, 0); | |
// Send the packet. | |
- if (send(ctx->fd, &buffer, size - IPV4_HDR_OVERHEAD, 0) < 0) { | |
+ struct addrinfo *local_endpoint = ctx->local_endpoint; | |
+ int overhead = local_endpoint->ai_family == AF_INET6 ? IPV4_HDR_OVERHEAD : IPV6_HDR_OVERHEAD; | |
+ if (send(ctx->fd, &buffer, size - overhead, 0) < 0) { | |
switch (errno) { | |
// Sometimes EAFNOSUPPORT is emitted for messages larger than the local MTU in case of PPPoE. | |
case EAFNOSUPPORT: | |
@@ -1264,6 +1284,7 @@ void context_free(l2tp_context *ctx) | |
free(ctx->broker_hostname); | |
free(ctx->broker_port); | |
free(ctx->bind_iface); | |
+ freeaddrinfo(ctx->local_endpoint); | |
free(ctx); | |
} | |
@@ -1317,7 +1338,7 @@ int main(int argc, char **argv) | |
// Parse program options. | |
int log_option = 0; | |
- char *uuid = NULL, *local_ip = "0.0.0.0", *tunnel_iface = NULL, *bind_iface_opt = NULL; | |
+ char *uuid = NULL, *local_ip = "::", *tunnel_iface = NULL, *bind_iface_opt = NULL; | |
char *hook = NULL; | |
unsigned int tunnel_id = 1; | |
int limit_bandwidth_down = 0; | |
@@ -1346,7 +1367,7 @@ int main(int argc, char **argv) | |
return 1; | |
} | |
- char *pos = strchr(optarg, ':'); | |
+ char *pos = strrchr(optarg, ':'); | |
if (!pos) { | |
fprintf(stderr, "ERROR: Each broker must be passed in the format 'host:port'!\n"); | |
return 1; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment