Skip to content

Commit

Permalink
Detect kernel support for MPTCP at runtime
Browse files Browse the repository at this point in the history
  • Loading branch information
darkwrat authored and Max Lv committed Jun 23, 2022
1 parent 01dd7df commit d61d09a
Show file tree
Hide file tree
Showing 8 changed files with 57 additions and 44 deletions.
2 changes: 1 addition & 1 deletion src/jconf.c
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ read_jconf(const char *file)
} else if (strcmp(name, "mptcp") == 0) {
check_json_value_type(value, json_boolean,
"invalid config file: option 'mptcp' must be a boolean");
conf.mptcp = value->u.boolean;
conf.mptcp = get_mptcp(value->u.boolean);
} else if (strcmp(name, "ipv6_first") == 0) {
check_json_value_type(value, json_boolean,
"invalid config file: option 'ipv6_first' must be a boolean");
Expand Down
19 changes: 8 additions & 11 deletions src/local.c
Original file line number Diff line number Diff line change
Expand Up @@ -1273,13 +1273,10 @@ create_remote(listen_ctx_t *listener,
}

int protocol = IPPROTO_TCP;
#ifdef IPPROTO_MPTCP
if (listener->mptcp > 0) {
protocol = IPPROTO_MPTCP;
if (listener->mptcp < 0) {
protocol = IPPROTO_MPTCP; // Enable upstream MPTCP
}
#endif
int remotefd = socket(remote_addr->sa_family, SOCK_STREAM, protocol);

if (remotefd == -1) {
ERROR("socket");
return NULL;
Expand All @@ -1291,11 +1288,11 @@ create_remote(listen_ctx_t *listener,
setsockopt(remotefd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt));
#endif

#ifndef IPPROTO_MPTCP
// Enable out-of-tree MPTCP
if (listener->mptcp > 1) {
int err = setsockopt(remotefd, SOL_TCP, listener->mptcp, &opt, sizeof(opt));
if (err == -1) {
ERROR("failed to enable multipath TCP");
ERROR("failed to enable out-of-tree multipath TCP");
}
} else if (listener->mptcp == 1) {
int i = 0;
Expand All @@ -1307,10 +1304,9 @@ create_remote(listen_ctx_t *listener,
i++;
}
if (listener->mptcp == 0) {
ERROR("failed to enable multipath TCP");
ERROR("failed to enable out-of-tree multipath TCP");
}
}
#endif

if (tcp_outgoing_sndbuf > 0) {
setsockopt(remotefd, SOL_SOCKET, SO_SNDBUF, &tcp_outgoing_sndbuf, sizeof(int));
Expand Down Expand Up @@ -1499,8 +1495,9 @@ main(int argc, char **argv)
LOGI("set MTU to %d", mtu);
break;
case GETOPT_VAL_MPTCP:
mptcp = 1;
LOGI("enable multipath TCP");
mptcp = get_mptcp(1);
if (mptcp)
LOGI("enable multipath TCP (%s)", mptcp > 0 ? "out-of-tree" : "upstream");
break;
case GETOPT_VAL_NODELAY:
no_delay = 1;
Expand Down
9 changes: 7 additions & 2 deletions src/netutils.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,19 @@ typedef struct {
char *port;
} ss_addr_t;

// Be compatible with older libc.
#ifndef IPPROTO_MPTCP
/* MPTCP_ENABLED setsockopt values for kernel 4 & 3, best behaviour to be independant of kernel version is to test from newest to the latest values */
#define IPPROTO_MPTCP 262
#endif

/* MPTCP_ENABLED setsockopt values for out-of-tree kernel 4 & 3, best behaviour
* to be independent of kernel version is to test from newest to latest values.
*/
#ifndef MPTCP_ENABLED
static const char mptcp_enabled_values[] = { 42, 26, 0 };
#else
static const char mptcp_enabled_values[] = { MPTCP_ENABLED, 0 };
#endif
#endif

#ifndef UPDATE_INTERVAL
#define UPDATE_INTERVAL 5
Expand Down
19 changes: 8 additions & 11 deletions src/redir.c
Original file line number Diff line number Diff line change
Expand Up @@ -771,11 +771,9 @@ accept_cb(EV_P_ ev_io *w, int revents)
struct sockaddr *remote_addr = listener->remote_addr[index];

int protocol = IPPROTO_TCP;
#ifdef IPPROTO_MPTCP
if (listener->mptcp > 0) {
protocol = IPPROTO_MPTCP;
if (listener->mptcp < 0) {
protocol = IPPROTO_MPTCP; // Enable upstream MPTCP
}
#endif
int remotefd = socket(remote_addr->sa_family, SOCK_STREAM, protocol);
if (remotefd == -1) {
ERROR("socket");
Expand Down Expand Up @@ -814,12 +812,11 @@ accept_cb(EV_P_ ev_io *w, int revents)
#endif
}

#ifndef IPPROTO_MPTCP
// Enable MPTCP
// Enable out-of-tree MPTCP
if (listener->mptcp > 1) {
int err = setsockopt(remotefd, SOL_TCP, listener->mptcp, &opt, sizeof(opt));
if (err == -1) {
ERROR("failed to enable multipath TCP");
ERROR("failed to enable out-of-tree multipath TCP");
}
} else if (listener->mptcp == 1) {
int i = 0;
Expand All @@ -831,10 +828,9 @@ accept_cb(EV_P_ ev_io *w, int revents)
i++;
}
if (listener->mptcp == 0) {
ERROR("failed to enable multipath TCP");
ERROR("failed to enable out-of-tree multipath TCP");
}
}
#endif

if (tcp_outgoing_sndbuf > 0) {
setsockopt(remotefd, SOL_SOCKET, SO_SNDBUF, &tcp_outgoing_sndbuf, sizeof(int));
Expand Down Expand Up @@ -959,8 +955,9 @@ main(int argc, char **argv)
LOGI("set MTU to %d", mtu);
break;
case GETOPT_VAL_MPTCP:
mptcp = 1;
LOGI("enable multipath TCP");
mptcp = get_mptcp(1);
if (mptcp)
LOGI("enable multipath TCP (%s)", mptcp > 0 ? "out-of-tree" : "upstream");
break;
case GETOPT_VAL_NODELAY:
no_delay = 1;
Expand Down
16 changes: 7 additions & 9 deletions src/server.c
Original file line number Diff line number Diff line change
Expand Up @@ -595,11 +595,9 @@ create_and_bind(const char *host, const char *port, int mptcp)

for (/*rp = result*/; rp != NULL; rp = rp->ai_next) {
int protocol = rp->ai_protocol;
#ifdef IPPROTO_MPTCP
if (mptcp == 1) {
protocol = IPPROTO_MPTCP;
if (mptcp < 0) {
protocol = IPPROTO_MPTCP; // Enable upstream MPTCP
}
#endif
listen_sock = socket(rp->ai_family, rp->ai_socktype, protocol);
if (listen_sock == -1) {
continue;
Expand All @@ -622,7 +620,7 @@ create_and_bind(const char *host, const char *port, int mptcp)
}
}

#ifndef IPPROTO_MPTCP
// Enable out-of-tree mptcp
if (mptcp == 1) {
int i = 0;
while ((mptcp = mptcp_enabled_values[i]) > 0) {
Expand All @@ -633,10 +631,9 @@ create_and_bind(const char *host, const char *port, int mptcp)
i++;
}
if (mptcp == 0) {
ERROR("failed to enable multipath TCP");
ERROR("failed to enable out-of-tree multipath TCP");
}
}
#endif

s = bind(listen_sock, rp->ai_addr, rp->ai_addrlen);
if (s == 0) {
Expand Down Expand Up @@ -1874,8 +1871,9 @@ main(int argc, char **argv)
plugin_opts = optarg;
break;
case GETOPT_VAL_MPTCP:
mptcp = 1;
LOGI("enable multipath TCP");
mptcp = get_mptcp(1);
if (mptcp)
LOGI("enable multipath TCP (%s)", mptcp > 0 ? "out-of-tree" : "upstream");
break;
case GETOPT_VAL_KEY:
key = optarg;
Expand Down
18 changes: 8 additions & 10 deletions src/tunnel.c
Original file line number Diff line number Diff line change
Expand Up @@ -737,11 +737,9 @@ accept_cb(EV_P_ ev_io *w, int revents)
struct sockaddr *remote_addr = listener->remote_addr[index];

int protocol = IPPROTO_TCP;
#ifdef IPPROTO_MPTCP
if (listener->mptcp > 0) {
protocol = IPPROTO_MPTCP;
if (listener->mptcp < 0) {
protocol = IPPROTO_MPTCP; // Enable upstream MPTCP
}
#endif
int remotefd = socket(remote_addr->sa_family, SOCK_STREAM, protocol);
if (remotefd == -1) {
ERROR("socket");
Expand Down Expand Up @@ -773,11 +771,11 @@ accept_cb(EV_P_ ev_io *w, int revents)
setsockopt(remotefd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt));
#endif

#ifndef IPPROTO_MPTCP
// Enable out-of-tree MPTCP
if (listener->mptcp > 1) {
int err = setsockopt(remotefd, SOL_TCP, listener->mptcp, &opt, sizeof(opt));
if (err == -1) {
ERROR("failed to enable multipath TCP");
ERROR("failed to enable out-of-tree multipath TCP");
}
} else if (listener->mptcp == 1) {
int i = 0;
Expand All @@ -789,10 +787,9 @@ accept_cb(EV_P_ ev_io *w, int revents)
i++;
}
if (listener->mptcp == 0) {
ERROR("failed to enable multipath TCP");
ERROR("failed to enable out-of-tree multipath TCP");
}
}
#endif

if (tcp_outgoing_sndbuf > 0) {
setsockopt(remotefd, SOL_SOCKET, SO_SNDBUF, &tcp_outgoing_sndbuf, sizeof(int));
Expand Down Expand Up @@ -956,8 +953,9 @@ main(int argc, char **argv)
LOGI("set MTU to %d", mtu);
break;
case GETOPT_VAL_MPTCP:
mptcp = 1;
LOGI("enable multipath TCP");
mptcp = get_mptcp(1);
if (mptcp)
LOGI("enable multipath TCP (%s)", mptcp > 0 ? "out-of-tree" : "upstream");
break;
case GETOPT_VAL_NODELAY:
no_delay = 1;
Expand Down
17 changes: 17 additions & 0 deletions src/utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -578,3 +578,20 @@ load16_be(const void *s)
return ((uint16_t)in[0] << 8)
| ((uint16_t)in[1]);
}

int
get_mptcp(int enable)
{
const char oldpath[] = "/proc/sys/net/mptcp/mptcp_enabled";

if (enable) {
// Check if kernel has out-of-tree MPTCP support.
if (access(oldpath, F_OK) != -1)
return 1;

// Otherwise, just use IPPROTO_MPTCP.
return -1;
}

return 0;
}
1 change: 1 addition & 0 deletions src/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -250,5 +250,6 @@ void *ss_realloc(void *ptr, size_t new_size);
int ss_is_ipv6addr(const char *addr);
char *get_default_conf(void);
uint16_t load16_be(const void *s);
int get_mptcp(int enable);

#endif // _UTILS_H

0 comments on commit d61d09a

Please sign in to comment.