Added support for the "new" type of IP6 support in AnyConnect.

If the client sends "X-CSTP-Full-IPv6-Capability: true", then we
use the headers:
     X-CSTP-Address-IP6: 2001:db8:1000:1000::1/64
     X-CSTP-Split-Include-IP6: 2001:db8:1000:1001::/64
     X-CSTP-Split-Include-IP6: 2001:db8:1000:1002::/64

(see corresponding openconnect change)
This commit is contained in:
Nikos Mavrogiannopoulos
2014-02-15 13:51:03 +01:00
parent 4e8d7e7a58
commit 3b9971b7e8
10 changed files with 86 additions and 28 deletions
+3 -3
View File
@@ -112,7 +112,6 @@ static struct cfg_options available_options[] = {
{ .name = "ipv6-nbns", .type = OPTION_MULTI_LINE, .mandatory = 0 }, /* alias nbns */ { .name = "ipv6-nbns", .type = OPTION_MULTI_LINE, .mandatory = 0 }, /* alias nbns */
{ .name = "ipv6-network", .type = OPTION_STRING, .mandatory = 0 }, { .name = "ipv6-network", .type = OPTION_STRING, .mandatory = 0 },
{ .name = "ipv6-netmask", .type = OPTION_STRING, .mandatory = 0 },
{ .name = "ipv6-prefix", .type = OPTION_NUMERIC, .mandatory = 0 }, { .name = "ipv6-prefix", .type = OPTION_NUMERIC, .mandatory = 0 },
{ .name = "route-add-cmd", .type = OPTION_STRING, .mandatory = 0 }, { .name = "route-add-cmd", .type = OPTION_STRING, .mandatory = 0 },
{ .name = "route-del-cmd", .type = OPTION_STRING, .mandatory = 0 }, { .name = "route-del-cmd", .type = OPTION_STRING, .mandatory = 0 },
@@ -416,11 +415,12 @@ unsigned force_cert_auth;
READ_STRING("ipv4-netmask", config->network.ipv4_netmask); READ_STRING("ipv4-netmask", config->network.ipv4_netmask);
READ_STRING("ipv6-network", config->network.ipv6); READ_STRING("ipv6-network", config->network.ipv6);
READ_STRING("ipv6-netmask", config->network.ipv6_netmask);
READ_NUMERIC("ipv6-prefix", prefix); READ_NUMERIC("ipv6-prefix", prefix);
if (prefix > 0) if (prefix > 0) {
config->network.ipv6_netmask = ipv6_prefix_to_mask(prefix); config->network.ipv6_netmask = ipv6_prefix_to_mask(prefix);
config->network.ipv6_prefix = prefix;
}
READ_MULTI_LINE("custom-header", config->custom_header, config->custom_header_size); READ_MULTI_LINE("custom-header", config->custom_header, config->custom_header_size);
READ_MULTI_LINE("split-dns", config->split_dns, config->split_dns_size); READ_MULTI_LINE("split-dns", config->split_dns, config->split_dns_size);
+4 -3
View File
@@ -52,7 +52,6 @@ static struct cfg_options available_options[] = {
{ .name = "ipv6-network", .type = OPTION_STRING }, { .name = "ipv6-network", .type = OPTION_STRING },
{ .name = "ipv4-netmask", .type = OPTION_STRING }, { .name = "ipv4-netmask", .type = OPTION_STRING },
{ .name = "ipv6-prefix", .type = OPTION_NUMERIC }, { .name = "ipv6-prefix", .type = OPTION_NUMERIC },
{ .name = "ipv6-netmask", .type = OPTION_STRING },
{ .name = "rx-data-per-sec", .type = OPTION_NUMERIC, }, { .name = "rx-data-per-sec", .type = OPTION_NUMERIC, },
{ .name = "tx-data-per-sec", .type = OPTION_NUMERIC, }, { .name = "tx-data-per-sec", .type = OPTION_NUMERIC, },
{ .name = "net-priority", .type = OPTION_STRING, }, { .name = "net-priority", .type = OPTION_STRING, },
@@ -168,10 +167,12 @@ unsigned prefix = 0;
READ_RAW_STRING("ipv4-network", config->ipv4_network); READ_RAW_STRING("ipv4-network", config->ipv4_network);
READ_RAW_STRING("ipv6-network", config->ipv6_network); READ_RAW_STRING("ipv6-network", config->ipv6_network);
READ_RAW_STRING("ipv4-netmask", config->ipv4_netmask); READ_RAW_STRING("ipv4-netmask", config->ipv4_netmask);
READ_RAW_STRING("ipv6-netmask", config->ipv6_netmask);
READ_RAW_NUMERIC("ipv6-prefix", prefix); READ_RAW_NUMERIC("ipv6-prefix", prefix);
if (prefix > 0) if (prefix > 0) {
config->ipv6_netmask = ipv6_prefix_to_mask(prefix); config->ipv6_netmask = ipv6_prefix_to_mask(prefix);
config->ipv6_prefix = prefix;
}
READ_RAW_NUMERIC("rx-data-per-sec", config->rx_per_sec); READ_RAW_NUMERIC("rx-data-per-sec", config->rx_per_sec);
READ_RAW_NUMERIC("tx-data-per-sec", config->tx_per_sec); READ_RAW_NUMERIC("tx-data-per-sec", config->tx_per_sec);
+7 -6
View File
@@ -91,12 +91,13 @@ message auth_reply_msg
/* additional config */ /* additional config */
optional string ipv4_netmask = 15; optional string ipv4_netmask = 15;
optional string ipv6_netmask = 16; optional string ipv6_netmask = 16;
optional uint32 rx_per_sec = 17; optional uint32 ipv6_prefix = 17;
optional uint32 tx_per_sec = 18; optional uint32 rx_per_sec = 18;
optional uint32 net_priority = 19; optional uint32 tx_per_sec = 19;
repeated string routes = 20; optional uint32 net_priority = 20;
repeated string dns = 21; repeated string routes = 21;
repeated string nbns = 22; repeated string dns = 22;
repeated string nbns = 23;
} }
/* RESUME_FETCH_REQ + RESUME_DELETE_REQ */ /* RESUME_FETCH_REQ + RESUME_DELETE_REQ */
+1
View File
@@ -109,6 +109,7 @@ int send_auth_reply(main_server_st* s, struct proc_st* proc,
msg.ipv4_netmask = proc->config.ipv4_netmask; msg.ipv4_netmask = proc->config.ipv4_netmask;
msg.ipv6_netmask = proc->config.ipv6_netmask; msg.ipv6_netmask = proc->config.ipv6_netmask;
msg.ipv6_prefix = proc->config.ipv6_prefix;
if (proc->config.rx_per_sec != 0) { if (proc->config.rx_per_sec != 0) {
msg.has_rx_per_sec = 1; msg.has_rx_per_sec = 1;
msg.rx_per_sec = proc->config.rx_per_sec; msg.rx_per_sec = proc->config.rx_per_sec;
+4
View File
@@ -216,6 +216,10 @@ static int read_additional_config_file(main_server_st * s, struct proc_st *proc,
cfg.ipv6_netmask = NULL; cfg.ipv6_netmask = NULL;
} }
if (proc->config.ipv6_prefix != 0) {
proc->config.ipv6_prefix = cfg.ipv6_prefix;
}
if (proc->config.cgroup == NULL) { if (proc->config.cgroup == NULL) {
proc->config.cgroup = cfg.cgroup; proc->config.cgroup = cfg.cgroup;
cfg.cgroup = NULL; cfg.cgroup = NULL;
+3
View File
@@ -125,6 +125,7 @@ struct group_cfg_st {
char *ipv4_network; char *ipv4_network;
char *ipv6_network; char *ipv6_network;
unsigned ipv6_prefix;
char *ipv4_netmask; char *ipv4_netmask;
char *ipv6_netmask; char *ipv6_netmask;
@@ -142,6 +143,8 @@ struct vpn_st {
char *ipv4; char *ipv4;
char *ipv4_local; /* local IPv4 address */ char *ipv4_local; /* local IPv4 address */
char *ipv6_netmask; char *ipv6_netmask;
unsigned ipv6_prefix;
char *ipv6; char *ipv6;
char *ipv6_local; /* local IPv6 address */ char *ipv6_local; /* local IPv6 address */
unsigned int mtu; unsigned int mtu;
+2
View File
@@ -310,6 +310,8 @@ static int recv_auth_reply(worker_st * ws, char *txt, size_t max_txt_size)
strdup(msg->ipv6_netmask); strdup(msg->ipv6_netmask);
} }
ws->config->network.ipv6_prefix = msg->ipv6_prefix;
if (msg->has_rx_per_sec) if (msg->has_rx_per_sec)
ws->config->rx_per_sec = msg->rx_per_sec; ws->config->rx_per_sec = msg->rx_per_sec;
+1
View File
@@ -164,6 +164,7 @@ int complete_vpn_info(worker_st * ws, struct vpn_st *vinfo)
vinfo->ipv4_netmask = ws->config->network.ipv4_netmask; vinfo->ipv4_netmask = ws->config->network.ipv4_netmask;
vinfo->ipv6_netmask = ws->config->network.ipv6_netmask; vinfo->ipv6_netmask = ws->config->network.ipv6_netmask;
vinfo->ipv6_prefix = ws->config->network.ipv6_prefix;
if (ws->config->network.mtu != 0) { if (ws->config->network.mtu != 0) {
vinfo->mtu = ws->config->network.mtu; vinfo->mtu = ws->config->network.mtu;
+56 -16
View File
@@ -181,6 +181,7 @@ int url_cb(http_parser * parser, const char *at, size_t length)
#define STR_HDR_CMTU "X-CSTP-MTU" #define STR_HDR_CMTU "X-CSTP-MTU"
#define STR_HDR_ATYPE "X-CSTP-Address-Type" #define STR_HDR_ATYPE "X-CSTP-Address-Type"
#define STR_HDR_HOST "X-CSTP-Hostname" #define STR_HDR_HOST "X-CSTP-Hostname"
#define STR_HDR_FULL_IPV6 "X-CSTP-Full-IPv6-Capability"
#define CS_ESALSA20 "OC-DTLS1_2-ESALSA20-SHA" #define CS_ESALSA20 "OC-DTLS1_2-ESALSA20-SHA"
#define CS_SALSA20 "OC-DTLS1_2-SALSA20-SHA" #define CS_SALSA20 "OC-DTLS1_2-SALSA20-SHA"
@@ -327,6 +328,11 @@ static void value_check(struct worker_st *ws, struct http_req_st *req)
NULL) NULL)
req->no_ipv6 = 1; req->no_ipv6 = 1;
break; break;
case HEADER_FULL_IPV6:
if (memmem(value, value_length, "true", 4) !=
NULL)
ws->full_ipv6 = 1;
break;
case HEADER_DTLS_MTU: case HEADER_DTLS_MTU:
req->dtls_mtu = atoi((char *)value); req->dtls_mtu = atoi((char *)value);
break; break;
@@ -443,6 +449,10 @@ static void header_check(struct http_req_st *req)
strncmp((char *)req->header.data, STR_HDR_USER_AGENT, strncmp((char *)req->header.data, STR_HDR_USER_AGENT,
req->header.length) == 0) { req->header.length) == 0) {
req->next_header = HEADER_USER_AGENT; req->next_header = HEADER_USER_AGENT;
} else if (req->header.length == sizeof(STR_HDR_FULL_IPV6) - 1 &&
strncmp((char *)req->header.data, STR_HDR_FULL_IPV6,
req->header.length) == 0) {
req->next_header = HEADER_FULL_IPV6;
} else { } else {
req->next_header = 0; req->next_header = 0;
} }
@@ -1024,7 +1034,7 @@ static int connect_handler(worker_st * ws)
unsigned tls_pending, dtls_pending = 0, i; unsigned tls_pending, dtls_pending = 0, i;
time_t udp_recv_time = 0, now; time_t udp_recv_time = 0, now;
struct timespec tnow; struct timespec tnow;
unsigned mtu_overhead = 0; unsigned mtu_overhead = 0, ip6;
int sndbuf; int sndbuf;
socklen_t sl; socklen_t sl;
bandwidth_st b_tx; bandwidth_st b_tx;
@@ -1140,16 +1150,23 @@ static int connect_handler(worker_st * ws)
if (ws->vinfo.ipv6 && req->no_ipv6 == 0) { if (ws->vinfo.ipv6 && req->no_ipv6 == 0) {
oclog(ws, LOG_DEBUG, "sending IPv6 %s", ws->vinfo.ipv6); oclog(ws, LOG_DEBUG, "sending IPv6 %s", ws->vinfo.ipv6);
ret = if (ws->full_ipv6 && ws->vinfo.ipv6_prefix) {
tls_printf(ws->session, "X-CSTP-Address: %s\r\n",
ws->vinfo.ipv6);
SEND_ERR(ret);
if (ws->vinfo.ipv6_netmask) {
ret = ret =
tls_printf(ws->session, "X-CSTP-Netmask: %s\r\n", tls_printf(ws->session, "X-CSTP-Address-IP6: %s/%u\r\n",
ws->vinfo.ipv6_netmask); ws->vinfo.ipv6, ws->vinfo.ipv6_prefix);
SEND_ERR(ret); SEND_ERR(ret);
} else {
ret =
tls_printf(ws->session, "X-CSTP-Address: %s\r\n",
ws->vinfo.ipv6);
SEND_ERR(ret);
if (ws->vinfo.ipv6_netmask) {
ret =
tls_printf(ws->session, "X-CSTP-Netmask: %s\r\n",
ws->vinfo.ipv6_netmask);
SEND_ERR(ret);
}
} }
} }
@@ -1185,25 +1202,48 @@ static int connect_handler(worker_st * ws)
} }
for (i = 0; i < ws->vinfo.routes_size; i++) { for (i = 0; i < ws->vinfo.routes_size; i++) {
if (req->no_ipv6 != 0 && strchr(ws->vinfo.routes[i], ':') != 0) if (strchr(ws->vinfo.routes[i], ':') != 0)
ip6 = 1;
else
ip6 = 0;
if (req->no_ipv6 != 0 && ip6 != 0)
continue; continue;
if (req->no_ipv4 != 0 && strchr(ws->vinfo.routes[i], '.') != 0) if (req->no_ipv4 != 0 && strchr(ws->vinfo.routes[i], '.') != 0)
continue; continue;
oclog(ws, LOG_DEBUG, "adding route %s", ws->vinfo.routes[i]); oclog(ws, LOG_DEBUG, "adding route %s", ws->vinfo.routes[i]);
ret = tls_printf(ws->session,
"X-CSTP-Split-Include: %s\r\n", if (ip6 != 0 && ws->full_ipv6) {
ws->vinfo.routes[i]); ret = tls_printf(ws->session,
"X-CSTP-Split-Include-IP6: %s\r\n",
ws->vinfo.routes[i]);
} else {
ret = tls_printf(ws->session,
"X-CSTP-Split-Include: %s\r\n",
ws->vinfo.routes[i]);
}
SEND_ERR(ret); SEND_ERR(ret);
} }
for (i = 0; i < ws->routes_size; i++) { for (i = 0; i < ws->routes_size; i++) {
if (req->no_ipv6 != 0 && strchr(ws->routes[i], ':') != 0) if (strchr(ws->routes[i], ':') != 0)
ip6 = 1;
else
ip6 = 0;
if (req->no_ipv6 != 0 && ip6 != 0)
continue; continue;
if (req->no_ipv4 != 0 && strchr(ws->routes[i], '.') != 0) if (req->no_ipv4 != 0 && strchr(ws->routes[i], '.') != 0)
continue; continue;
oclog(ws, LOG_DEBUG, "adding private route %s", ws->routes[i]); oclog(ws, LOG_DEBUG, "adding private route %s", ws->routes[i]);
ret = tls_printf(ws->session,
"X-CSTP-Split-Include: %s\r\n", ws->routes[i]); if (ip6 != 0 && ws->full_ipv6) {
ret = tls_printf(ws->session,
"X-CSTP-Split-Include-IP6: %s\r\n", ws->routes[i]);
} else {
ret = tls_printf(ws->session,
"X-CSTP-Split-Include: %s\r\n", ws->routes[i]);
}
SEND_ERR(ret); SEND_ERR(ret);
} }
ret = ret =
+5
View File
@@ -51,6 +51,7 @@ enum {
HEADER_DTLS_MTU, HEADER_DTLS_MTU,
HEADER_DTLS_CIPHERSUITE, HEADER_DTLS_CIPHERSUITE,
HEADER_CONNECTION, HEADER_CONNECTION,
HEADER_FULL_IPV6,
HEADER_USER_AGENT, HEADER_USER_AGENT,
}; };
@@ -146,6 +147,10 @@ typedef struct worker_st {
unsigned last_bad_mtu; unsigned last_bad_mtu;
unsigned conn_mtu; unsigned conn_mtu;
/* Indicates whether the new IPv6 headers will
* be sent or the old */
unsigned full_ipv6;
/* Buffer used by worker */ /* Buffer used by worker */
uint8_t * buffer; uint8_t * buffer;
unsigned buffer_size; unsigned buffer_size;