mirror of
https://github.com/OpenVPN/openvpn.git
synced 2026-05-21 17:38:19 -04:00
Merge b5d6a30ee3 into 74d39dfba2
This commit is contained in:
commit
ffda72755d
13 changed files with 598 additions and 130 deletions
|
|
@ -45,6 +45,9 @@
|
|||
|
||||
#include "memdbg.h"
|
||||
|
||||
#include <sys/select.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
counter_type link_read_bytes_global; /* GLOBAL */
|
||||
counter_type link_write_bytes_global; /* GLOBAL */
|
||||
|
||||
|
|
@ -612,6 +615,21 @@ buffer_turnover(const uint8_t *orig_buf, struct buffer *dest_stub, struct buffer
|
|||
}
|
||||
}
|
||||
|
||||
uint8_t *buff_prepsize(uint8_t *buff, int *size)
|
||||
{
|
||||
buff[0] = (uint8_t)((*size >> 8) & 0xff);
|
||||
buff[1] = (uint8_t)((*size >> 0) & 0xff);
|
||||
buff += 2;
|
||||
return buff;
|
||||
}
|
||||
|
||||
uint8_t *buff_postsize(uint8_t *buff, int *size)
|
||||
{
|
||||
*size = ((buff[0] << 8) + (buff[1] << 0));
|
||||
buff += 2;
|
||||
return buff;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compress, fragment, encrypt and HMAC-sign an outgoing packet.
|
||||
* Input: c->c2.buf
|
||||
|
|
@ -889,7 +907,7 @@ socks_postprocess_incoming_link(struct context *c, struct link_socket *sock)
|
|||
{
|
||||
if (sock->socks_proxy && sock->info.proto == PROTO_UDP)
|
||||
{
|
||||
socks_process_incoming_udp(&c->c2.buf, &c->c2.from);
|
||||
socks_process_incoming_udp(&c->c2.buf2, &c->c2.from);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -919,7 +937,7 @@ link_socket_write_post_size_adjust(int *size, int size_delta, struct buffer *buf
|
|||
}
|
||||
|
||||
/*
|
||||
* Output: c->c2.buf
|
||||
* Output: c->c2.buf2
|
||||
*/
|
||||
|
||||
void
|
||||
|
|
@ -933,10 +951,10 @@ read_incoming_link(struct context *c, struct link_socket *sock)
|
|||
|
||||
/*ASSERT (!c->c2.to_tun.len);*/
|
||||
|
||||
c->c2.buf = c->c2.buffers->read_link_buf;
|
||||
ASSERT(buf_init(&c->c2.buf, c->c2.frame.buf.headroom));
|
||||
c->c2.buf2 = c->c2.buffers->read_link_buf;
|
||||
ASSERT(buf_init(&c->c2.buf2, c->c2.frame.buf.headroom));
|
||||
|
||||
status = link_socket_read(sock, &c->c2.buf, &c->c2.from);
|
||||
status = link_socket_read(sock, &c->c2.buf2, &c->c2.from);
|
||||
|
||||
if (socket_connection_reset(sock, status))
|
||||
{
|
||||
|
|
@ -989,11 +1007,11 @@ process_incoming_link_part1(struct context *c, struct link_socket_info *lsi, boo
|
|||
struct gc_arena gc = gc_new();
|
||||
bool decrypt_status = false;
|
||||
|
||||
if (c->c2.buf.len > 0)
|
||||
if (c->c2.buf2.len > 0)
|
||||
{
|
||||
c->c2.link_read_bytes += c->c2.buf.len;
|
||||
link_read_bytes_global += c->c2.buf.len;
|
||||
c->c2.original_recv_size = c->c2.buf.len;
|
||||
c->c2.link_read_bytes += c->c2.buf2.len;
|
||||
link_read_bytes_global += c->c2.buf2.len;
|
||||
c->c2.original_recv_size = c->c2.buf2.len;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1006,21 +1024,22 @@ process_incoming_link_part1(struct context *c, struct link_socket_info *lsi, boo
|
|||
{
|
||||
if (!ask_gremlin(c->options.gremlin))
|
||||
{
|
||||
c->c2.buf.len = 0;
|
||||
c->c2.buf2.len = 0;
|
||||
}
|
||||
corrupt_gremlin(&c->c2.buf, c->options.gremlin);
|
||||
corrupt_gremlin(&c->c2.buf2, c->options.gremlin);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* log incoming packet */
|
||||
#ifdef LOG_RW
|
||||
if (c->c2.log_rw && c->c2.buf.len > 0)
|
||||
if (c->c2.log_rw && c->c2.buf2.len > 0)
|
||||
{
|
||||
fprintf(stderr, "R");
|
||||
}
|
||||
#endif
|
||||
|
||||
msg(D_LINK_RW, "%s READ [%d] from %s: %s", proto2ascii(lsi->proto, lsi->af, true),
|
||||
BLEN(&c->c2.buf), print_link_socket_actual(&c->c2.from, &gc), PROTO_DUMP(&c->c2.buf, &gc));
|
||||
BLEN(&c->c2.buf2), print_link_socket_actual(&c->c2.from, &gc), PROTO_DUMP(&c->c2.buf2, &gc));
|
||||
|
||||
/*
|
||||
* Good, non-zero length packet received.
|
||||
|
|
@ -1029,18 +1048,18 @@ process_incoming_link_part1(struct context *c, struct link_socket_info *lsi, boo
|
|||
* If any stage fails, it sets buf.len to 0 or -1,
|
||||
* telling downstream stages to ignore the packet.
|
||||
*/
|
||||
if (c->c2.buf.len > 0)
|
||||
if (c->c2.buf2.len > 0)
|
||||
{
|
||||
struct crypto_options *co = NULL;
|
||||
const uint8_t *ad_start = NULL;
|
||||
if (!link_socket_verify_incoming_addr(&c->c2.buf, lsi, &c->c2.from))
|
||||
if (!link_socket_verify_incoming_addr(&c->c2.buf2, lsi, &c->c2.from))
|
||||
{
|
||||
link_socket_bad_incoming_addr(&c->c2.buf, lsi, &c->c2.from);
|
||||
link_socket_bad_incoming_addr(&c->c2.buf2, lsi, &c->c2.from);
|
||||
}
|
||||
|
||||
if (c->c2.tls_multi)
|
||||
{
|
||||
uint8_t opcode = *BPTR(&c->c2.buf) >> P_OPCODE_SHIFT;
|
||||
uint8_t opcode = *BPTR(&c->c2.buf2) >> P_OPCODE_SHIFT;
|
||||
|
||||
/*
|
||||
* If DCO is enabled, the kernel drivers require that the
|
||||
|
|
@ -1054,7 +1073,7 @@ process_incoming_link_part1(struct context *c, struct link_socket_info *lsi, boo
|
|||
{
|
||||
msg(D_LINK_ERRORS, "Data Channel Offload doesn't support DATA_V1 packets. "
|
||||
"Upgrade your server to 2.4.5 or newer.");
|
||||
c->c2.buf.len = 0;
|
||||
c->c2.buf2.len = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1067,7 +1086,7 @@ process_incoming_link_part1(struct context *c, struct link_socket_info *lsi, boo
|
|||
* will load crypto_options with the correct encryption key
|
||||
* and return false.
|
||||
*/
|
||||
if (tls_pre_decrypt(c->c2.tls_multi, &c->c2.from, &c->c2.buf, &co, floated, &ad_start))
|
||||
if (tls_pre_decrypt(c->c2.tls_multi, &c->c2.from, &c->c2.buf2, &co, floated, &ad_start))
|
||||
{
|
||||
interval_action(&c->c2.tmp_int);
|
||||
|
||||
|
|
@ -1090,12 +1109,12 @@ process_incoming_link_part1(struct context *c, struct link_socket_info *lsi, boo
|
|||
*/
|
||||
if (c->c2.tls_multi && c->c2.tls_multi->multi_state < CAS_CONNECT_DONE)
|
||||
{
|
||||
c->c2.buf.len = 0;
|
||||
c->c2.buf2.len = 0;
|
||||
}
|
||||
|
||||
/* authenticate and decrypt the incoming packet */
|
||||
decrypt_status =
|
||||
openvpn_decrypt(&c->c2.buf, c->c2.buffers->decrypt_buf, co, &c->c2.frame, ad_start);
|
||||
openvpn_decrypt(&c->c2.buf2, c->c2.buffers->decrypt_buf, co, &c->c2.frame, ad_start);
|
||||
|
||||
if (!decrypt_status
|
||||
/* on the instance context we have only one socket, so just check the first one */
|
||||
|
|
@ -1120,12 +1139,12 @@ void
|
|||
process_incoming_link_part2(struct context *c, struct link_socket_info *lsi,
|
||||
const uint8_t *orig_buf)
|
||||
{
|
||||
if (c->c2.buf.len > 0)
|
||||
if (c->c2.buf2.len > 0)
|
||||
{
|
||||
#ifdef ENABLE_FRAGMENT
|
||||
if (c->c2.fragment)
|
||||
{
|
||||
fragment_incoming(c->c2.fragment, &c->c2.buf, &c->c2.frame_fragment);
|
||||
fragment_incoming(c->c2.fragment, &c->c2.buf2, &c->c2.frame_fragment);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -1133,14 +1152,14 @@ process_incoming_link_part2(struct context *c, struct link_socket_info *lsi,
|
|||
/* decompress the incoming packet */
|
||||
if (c->c2.comp_context)
|
||||
{
|
||||
(*c->c2.comp_context->alg.decompress)(&c->c2.buf, c->c2.buffers->decompress_buf,
|
||||
(*c->c2.comp_context->alg.decompress)(&c->c2.buf2, c->c2.buffers->decompress_buf,
|
||||
c->c2.comp_context, &c->c2.frame);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef PACKET_TRUNCATION_CHECK
|
||||
/* if (c->c2.buf.len > 1) --c->c2.buf.len; */
|
||||
ipv4_packet_size_verify(BPTR(&c->c2.buf), BLEN(&c->c2.buf), TUNNEL_TYPE(c->c1.tuntap),
|
||||
/* if (c->c2.buf2.len > 1) --c->c2.buf2.len; */
|
||||
ipv4_packet_size_verify(BPTR(&c->c2.buf2), BLEN(&c->c2.buf2), TUNNEL_TYPE(c->c1.tuntap),
|
||||
"POST_DECRYPT", &c->c2.n_trunc_post_decrypt);
|
||||
#endif
|
||||
|
||||
|
|
@ -1153,39 +1172,39 @@ process_incoming_link_part2(struct context *c, struct link_socket_info *lsi,
|
|||
*
|
||||
* Also, update the persisted version of our packet-id.
|
||||
*/
|
||||
if (!TLS_MODE(c) && c->c2.buf.len > 0)
|
||||
if (!TLS_MODE(c) && c->c2.buf2.len > 0)
|
||||
{
|
||||
link_socket_set_outgoing_addr(lsi, &c->c2.from, NULL, c->c2.es);
|
||||
}
|
||||
|
||||
/* reset packet received timer */
|
||||
if (c->options.ping_rec_timeout && c->c2.buf.len > 0)
|
||||
if (c->options.ping_rec_timeout && c->c2.buf2.len > 0)
|
||||
{
|
||||
event_timeout_reset(&c->c2.ping_rec_interval);
|
||||
}
|
||||
|
||||
/* increment authenticated receive byte count */
|
||||
if (c->c2.buf.len > 0)
|
||||
if (c->c2.buf2.len > 0)
|
||||
{
|
||||
c->c2.link_read_bytes_auth += c->c2.buf.len;
|
||||
c->c2.link_read_bytes_auth += c->c2.buf2.len;
|
||||
c->c2.max_recv_size_local =
|
||||
max_int(c->c2.original_recv_size, c->c2.max_recv_size_local);
|
||||
}
|
||||
|
||||
/* Did we just receive an openvpn ping packet? */
|
||||
if (is_ping_msg(&c->c2.buf))
|
||||
if (is_ping_msg(&c->c2.buf2))
|
||||
{
|
||||
dmsg(D_PING, "RECEIVED PING PACKET");
|
||||
c->c2.buf.len = 0; /* drop packet */
|
||||
c->c2.buf2.len = 0; /* drop packet */
|
||||
}
|
||||
|
||||
/* Did we just receive an OCC packet? */
|
||||
if (is_occ_msg(&c->c2.buf))
|
||||
if (is_occ_msg(&c->c2.buf2))
|
||||
{
|
||||
process_received_occ_msg(c);
|
||||
}
|
||||
|
||||
buffer_turnover(orig_buf, &c->c2.to_tun, &c->c2.buf, &c->c2.buffers->read_link_buf);
|
||||
buffer_turnover(orig_buf, &c->c2.to_tun, &c->c2.buf2, &c->c2.buffers->read_link_buf);
|
||||
|
||||
/* to_tun defined + unopened tuntap can cause deadlock */
|
||||
if (!tuntap_defined(c->c1.tuntap))
|
||||
|
|
@ -1199,14 +1218,31 @@ process_incoming_link_part2(struct context *c, struct link_socket_info *lsi,
|
|||
}
|
||||
}
|
||||
|
||||
void process_incoming_link_part3(struct context *c)
|
||||
{
|
||||
if (BULK_MODE(c))
|
||||
{
|
||||
if (c->c2.buf2.len > 0)
|
||||
{
|
||||
c->c2.to_tun.offset += 2;
|
||||
c->c2.buf2.offset += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
buf_reset(&c->c2.to_tun);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
process_incoming_link(struct context *c, struct link_socket *sock)
|
||||
{
|
||||
struct link_socket_info *lsi = &sock->info;
|
||||
const uint8_t *orig_buf = c->c2.buf.data;
|
||||
const uint8_t *orig_buf = c->c2.buf2.data;
|
||||
|
||||
process_incoming_link_part1(c, lsi, false);
|
||||
process_incoming_link_part2(c, lsi, orig_buf);
|
||||
process_incoming_link_part3(c);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -1297,7 +1333,7 @@ process_incoming_dco(dco_context_t *dco)
|
|||
*/
|
||||
|
||||
void
|
||||
read_incoming_tun(struct context *c)
|
||||
read_incoming_tun_part2(struct context *c)
|
||||
{
|
||||
/*
|
||||
* Setup for read() call on TUN/TAP device.
|
||||
|
|
@ -1352,6 +1388,63 @@ read_incoming_tun(struct context *c)
|
|||
check_status(c->c2.buf.len, "read from TUN/TAP", NULL, c->c1.tuntap);
|
||||
}
|
||||
|
||||
void read_incoming_tun_part3(struct context *c)
|
||||
{
|
||||
fd_set rfds;
|
||||
struct timeval timo;
|
||||
int plen = 0, pidx = -1;
|
||||
int fdno = c->c1.tuntap->fd;
|
||||
for (int x = 0; x < TUN_BAT_MIN; ++x)
|
||||
{
|
||||
int leng = plen, indx = (pidx + 1);
|
||||
if (leng < 1)
|
||||
{
|
||||
FD_ZERO(&rfds);
|
||||
FD_SET(fdno, &rfds);
|
||||
timo.tv_sec = 0;
|
||||
timo.tv_usec = 0;
|
||||
select(fdno+1, &rfds, NULL, NULL, &timo);
|
||||
if (FD_ISSET(fdno, &rfds))
|
||||
{
|
||||
read_incoming_tun_part2(c);
|
||||
plen = BLEN(&c->c2.buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
leng = plen;
|
||||
if (leng > 0)
|
||||
{
|
||||
c->c2.buffers->read_tun_bufs[indx].offset = TUN_BAT_OFF;
|
||||
c->c2.buffers->read_tun_bufs[indx].len = leng;
|
||||
bcopy(BPTR(&c->c2.buf), BPTR(&c->c2.buffers->read_tun_bufs[indx]), leng);
|
||||
c->c2.bufs[indx] = c->c2.buffers->read_tun_bufs[indx];
|
||||
pidx = indx;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
plen = 0;
|
||||
}
|
||||
c->c2.buffers->bulk_indx = 0;
|
||||
c->c2.buffers->bulk_leng = (pidx + 1);
|
||||
}
|
||||
|
||||
void read_incoming_tun(struct context *c)
|
||||
{
|
||||
if (!BULK_MODE(c))
|
||||
{
|
||||
read_incoming_tun_part2(c);
|
||||
}
|
||||
else
|
||||
{
|
||||
read_incoming_tun_part3(c);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Drops UDP packets which OS decided to route via tun.
|
||||
*
|
||||
|
|
@ -1476,7 +1569,7 @@ drop_if_recursive_routing(struct context *c, struct buffer *buf)
|
|||
*/
|
||||
|
||||
void
|
||||
process_incoming_tun(struct context *c, struct link_socket *out_sock)
|
||||
process_incoming_tun_part2(struct context *c, struct link_socket *out_sock)
|
||||
{
|
||||
if (c->c2.buf.len > 0)
|
||||
{
|
||||
|
|
@ -1491,7 +1584,7 @@ process_incoming_tun(struct context *c, struct link_socket *out_sock)
|
|||
#endif
|
||||
|
||||
/* Show packet content */
|
||||
dmsg(D_TUN_RW, "TUN READ [%d]", BLEN(&c->c2.buf));
|
||||
dmsg(D_TUN_RW, "TUN READ [%d] [%d]", BLEN(&c->c2.buf), c->c2.frame.buf.payload_size);
|
||||
|
||||
if (c->c2.buf.len > 0)
|
||||
{
|
||||
|
|
@ -1515,7 +1608,10 @@ process_incoming_tun(struct context *c, struct link_socket *out_sock)
|
|||
}
|
||||
if (c->c2.buf.len > 0)
|
||||
{
|
||||
encrypt_sign(c, true);
|
||||
if (!BULK_MODE(c))
|
||||
{
|
||||
encrypt_sign(c, true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1523,6 +1619,60 @@ process_incoming_tun(struct context *c, struct link_socket *out_sock)
|
|||
}
|
||||
}
|
||||
|
||||
void process_incoming_tun_part3(struct context *c, struct link_socket *out_sock)
|
||||
{
|
||||
if (BULK_DATA(c->c2.buffers))
|
||||
{
|
||||
c->c2.buffers->read_tun_max.offset = TUN_BAT_OFF;
|
||||
c->c2.buffers->read_tun_max.len = 0;
|
||||
uint8_t *temp = BPTR(&c->c2.buffers->read_tun_max);
|
||||
int leng = c->c2.buffers->bulk_leng;
|
||||
int plen = 0, maxl = 0;
|
||||
for (int x = 0; x < leng; ++x)
|
||||
{
|
||||
c->c2.buf = c->c2.bufs[x];
|
||||
process_incoming_tun_part2(c, out_sock);
|
||||
plen = BLEN(&c->c2.buf);
|
||||
if (plen > 0)
|
||||
{
|
||||
temp = buff_prepsize(temp, &plen);
|
||||
bcopy(BPTR(&c->c2.buf), temp, plen);
|
||||
temp += plen; maxl += (plen + 2);
|
||||
}
|
||||
c->c2.bufs[x].len = 0;
|
||||
}
|
||||
if (maxl > 0)
|
||||
{
|
||||
c->c2.buffers->read_tun_max.offset = TUN_BAT_OFF;
|
||||
c->c2.buffers->read_tun_max.len = maxl;
|
||||
c->c2.buf = c->c2.buffers->read_tun_max;
|
||||
encrypt_sign(c, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
buf_reset(&c->c2.to_link);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
buf_reset(&c->c2.to_link);
|
||||
}
|
||||
c->c2.buffers->bulk_indx = -1;
|
||||
c->c2.buffers->bulk_leng = -1;
|
||||
}
|
||||
|
||||
void process_incoming_tun(struct context *c, struct link_socket *out_sock)
|
||||
{
|
||||
if (!BULK_MODE(c))
|
||||
{
|
||||
process_incoming_tun_part2(c, out_sock);
|
||||
}
|
||||
else
|
||||
{
|
||||
process_incoming_tun_part3(c, out_sock);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Forges a IPv6 ICMP packet with a no route to host error code from the
|
||||
* IPv6 packet in buf and sends it directly back to the client via the tun
|
||||
|
|
@ -1748,7 +1898,7 @@ process_outgoing_link(struct context *c, struct link_socket *sock)
|
|||
struct gc_arena gc = gc_new();
|
||||
int error_code = 0;
|
||||
|
||||
if (c->c2.to_link.len > 0 && c->c2.to_link.len <= c->c2.frame.buf.payload_size)
|
||||
if (c->c2.to_link.len > 0 && (c->c2.to_link.len <= c->c2.frame.buf.payload_size || c->c2.frame.bulk_size > 0))
|
||||
{
|
||||
/*
|
||||
* Setup for call to send/sendto which will send
|
||||
|
|
@ -1793,6 +1943,7 @@ process_outgoing_link(struct context *c, struct link_socket *sock)
|
|||
fprintf(stderr, "W");
|
||||
}
|
||||
#endif
|
||||
|
||||
msg(D_LINK_RW, "%s WRITE [%d] to %s: %s",
|
||||
proto2ascii(sock->info.proto, sock->info.af, true), BLEN(&c->c2.to_link),
|
||||
print_link_socket_actual(c->c2.to_link_addr, &gc), PROTO_DUMP(&c->c2.to_link, &gc));
|
||||
|
|
@ -1877,7 +2028,7 @@ process_outgoing_link(struct context *c, struct link_socket *sock)
|
|||
*/
|
||||
|
||||
void
|
||||
process_outgoing_tun(struct context *c, struct link_socket *in_sock)
|
||||
process_outgoing_tun_part2(struct context *c, struct link_socket *in_sock)
|
||||
{
|
||||
/*
|
||||
* Set up for write() call to TUN/TAP
|
||||
|
|
@ -1908,7 +2059,8 @@ process_outgoing_tun(struct context *c, struct link_socket *in_sock)
|
|||
fprintf(stderr, "w");
|
||||
}
|
||||
#endif
|
||||
dmsg(D_TUN_RW, "TUN WRITE [%d]", BLEN(&c->c2.to_tun));
|
||||
|
||||
dmsg(D_TUN_RW, "TUN WRITE [%d] [%d]", BLEN(&c->c2.to_tun), c->c2.frame.buf.payload_size);
|
||||
|
||||
#ifdef PACKET_TRUNCATION_CHECK
|
||||
ipv4_packet_size_verify(BPTR(&c->c2.to_tun), BLEN(&c->c2.to_tun), TUNNEL_TYPE(c->c1.tuntap),
|
||||
|
|
@ -1962,6 +2114,49 @@ process_outgoing_tun(struct context *c, struct link_socket *in_sock)
|
|||
buf_reset(&c->c2.to_tun);
|
||||
}
|
||||
|
||||
void process_outgoing_tun_part3(struct context *c, struct link_socket *in_sock)
|
||||
{
|
||||
if ((c->c2.to_tun.len > 0) && (c->c2.to_tun.offset > 1))
|
||||
{
|
||||
c->c2.to_tun.offset -= 2;
|
||||
buf_init(&c->c2.buffers->send_tun_max, TUN_BAT_OFF);
|
||||
buf_copy(&c->c2.buffers->send_tun_max, &c->c2.to_tun);
|
||||
int maxl = 0, plen = 0;
|
||||
int leng = BLEN(&c->c2.buffers->send_tun_max);
|
||||
uint8_t *temp = BPTR(&c->c2.buffers->send_tun_max);
|
||||
for (int x = 0; x < TUN_BAT_MIN; ++x)
|
||||
{
|
||||
temp = buff_postsize(temp, &plen);
|
||||
if ((leng > 0) && (plen > 0) && ((maxl + plen) < leng))
|
||||
{
|
||||
c->c2.to_tun = c->c2.buffers->to_tun_max;
|
||||
c->c2.to_tun.offset = TUN_BAT_OFF;
|
||||
c->c2.to_tun.len = plen;
|
||||
bcopy(temp, BPTR(&c->c2.to_tun), plen);
|
||||
temp += plen; maxl += (plen + 2);
|
||||
process_outgoing_tun_part2(c, in_sock);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
buf_reset(&c->c2.to_tun);
|
||||
}
|
||||
|
||||
void process_outgoing_tun(struct context *c, struct link_socket *in_sock)
|
||||
{
|
||||
if (!BULK_MODE(c))
|
||||
{
|
||||
process_outgoing_tun_part2(c, in_sock);
|
||||
}
|
||||
else
|
||||
{
|
||||
process_outgoing_tun_part3(c, in_sock);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
pre_select(struct context *c)
|
||||
{
|
||||
|
|
@ -2213,7 +2408,7 @@ io_wait(struct context *c, const unsigned int flags)
|
|||
|
||||
if (!c->sig->signal_received)
|
||||
{
|
||||
if (!(flags & IOW_CHECK_RESIDUAL) || !sockets_read_residual(c))
|
||||
if (true)
|
||||
{
|
||||
int status;
|
||||
|
||||
|
|
@ -2265,9 +2460,9 @@ io_wait(struct context *c, const unsigned int flags)
|
|||
c->c2.event_set_status = ES_TIMEOUT;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (sockets_read_residual(c))
|
||||
{
|
||||
c->c2.event_set_status = SOCKET_READ;
|
||||
c->c2.event_set_status |= (SOCKET_READ << SOCKET_SHIFT);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -34,6 +34,11 @@
|
|||
* file
|
||||
*/
|
||||
|
||||
#define BULK_MODE(c) (c && c->c2.frame.bulk_size > 0)
|
||||
#define BULK_DATA(b) (b && (b->bulk_leng > 0) && (b->bulk_indx < b->bulk_leng))
|
||||
#define INST_LENG(a) (a && (a->inst_leng > 0) && (a->inst_indx < a->inst_leng))
|
||||
#define LINK_LEFT(i) (i && sockets_read_residual(i))
|
||||
|
||||
#define TUN_OUT(c) (BLEN(&(c)->c2.to_tun) > 0)
|
||||
#define LINK_OUT(c) (BLEN(&(c)->c2.to_link) > 0)
|
||||
#define ANY_OUT(c) (TUN_OUT(c) || LINK_OUT(c))
|
||||
|
|
@ -193,6 +198,8 @@ bool process_incoming_link_part1(struct context *c, struct link_socket_info *lsi
|
|||
void process_incoming_link_part2(struct context *c, struct link_socket_info *lsi,
|
||||
const uint8_t *orig_buf);
|
||||
|
||||
void process_incoming_link_part3(struct context *c);
|
||||
|
||||
/**
|
||||
* Transfers \c float_sa data extracted from an incoming DCO
|
||||
* PEER_FLOAT_NTF to \c out_osaddr for later processing.
|
||||
|
|
|
|||
|
|
@ -2962,6 +2962,11 @@ frame_finalize_options(struct context *c, const struct options *o)
|
|||
tailroom += COMP_EXTRA_BUFFER(payload_size);
|
||||
#endif
|
||||
|
||||
if (frame->bulk_size > 0)
|
||||
{
|
||||
payload_size = BAT_SIZE(TUN_BAT_ONE, frame->tun_mtu, TUN_BAT_OFF);
|
||||
}
|
||||
|
||||
frame->buf.payload_size = payload_size;
|
||||
frame->buf.headroom = headroom;
|
||||
frame->buf.tailroom = tailroom;
|
||||
|
|
@ -3485,6 +3490,10 @@ do_init_frame_tls(struct context *c)
|
|||
if (c->c2.tls_multi)
|
||||
{
|
||||
tls_multi_init_finalize(c->c2.tls_multi, c->options.ce.tls_mtu);
|
||||
if (c->c2.frame.bulk_size > 0)
|
||||
{
|
||||
c->c2.tls_multi->opt.frame.buf.payload_size = c->c2.frame.tun_mtu;
|
||||
}
|
||||
ASSERT(c->c2.tls_multi->opt.frame.buf.payload_size <= c->c2.frame.buf.payload_size);
|
||||
frame_print(&c->c2.tls_multi->opt.frame, D_MTU_INFO, "Control Channel MTU parms");
|
||||
|
||||
|
|
@ -3552,6 +3561,14 @@ do_init_frame(struct context *c)
|
|||
c->c2.frame.extra_tun += c->options.ce.tun_mtu_extra;
|
||||
}
|
||||
|
||||
/*
|
||||
* Adjust bulk size based on the --bulk-mode parameter.
|
||||
*/
|
||||
if (c->options.ce.bulk_mode)
|
||||
{
|
||||
c->c2.frame.bulk_size = c->options.ce.tun_mtu;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill in the blanks in the frame parameters structure,
|
||||
* make sure values are rational, etc.
|
||||
|
|
@ -3692,9 +3709,45 @@ init_context_buffers(const struct frame *frame)
|
|||
|
||||
size_t buf_size = BUF_SIZE(frame);
|
||||
|
||||
if (frame->bulk_size > 0)
|
||||
{
|
||||
size_t off_size = (frame->buf.headroom + TUN_BAT_OFF + frame->buf.tailroom);
|
||||
buf_size = BAT_SIZE(TUN_BAT_MAX, frame->tun_mtu, off_size);
|
||||
}
|
||||
|
||||
dmsg(M_INFO, "BULK bufs [%ld] [%d+%d+%d]", buf_size, frame->buf.headroom, frame->buf.payload_size, frame->buf.tailroom);
|
||||
|
||||
b->read_link_buf = alloc_buf(buf_size);
|
||||
b->read_tun_buf = alloc_buf(buf_size);
|
||||
|
||||
if (frame->bulk_size > 0)
|
||||
{
|
||||
size_t off_size = (frame->buf.headroom + TUN_BAT_OFF + frame->buf.tailroom);
|
||||
size_t one_size = BAT_SIZE(TUN_BAT_ONE, frame->tun_mtu, off_size);
|
||||
|
||||
for (int x = 0; x < TUN_BAT_MAX; ++x)
|
||||
{
|
||||
b->read_tun_bufs[x] = alloc_buf(one_size);
|
||||
b->read_tun_bufs[x].offset = TUN_BAT_OFF;
|
||||
b->read_tun_bufs[x].len = 0;
|
||||
}
|
||||
|
||||
b->read_tun_max = alloc_buf(buf_size);
|
||||
b->read_tun_max.offset = TUN_BAT_OFF;
|
||||
b->read_tun_max.len = 0;
|
||||
|
||||
b->send_tun_max = alloc_buf(buf_size);
|
||||
b->send_tun_max.offset = TUN_BAT_OFF;
|
||||
b->send_tun_max.len = 0;
|
||||
|
||||
b->to_tun_max = alloc_buf(buf_size);
|
||||
b->to_tun_max.offset = TUN_BAT_OFF;
|
||||
b->to_tun_max.len = 0;
|
||||
}
|
||||
|
||||
b->bulk_indx = -1;
|
||||
b->bulk_leng = -1;
|
||||
|
||||
b->aux_buf = alloc_buf(buf_size);
|
||||
|
||||
b->encrypt_buf = alloc_buf(buf_size);
|
||||
|
|
@ -3717,6 +3770,17 @@ free_context_buffers(struct context_buffers *b)
|
|||
free_buf(&b->read_tun_buf);
|
||||
free_buf(&b->aux_buf);
|
||||
|
||||
if (b->to_tun_max.data)
|
||||
{
|
||||
free_buf(&b->to_tun_max);
|
||||
free_buf(&b->send_tun_max);
|
||||
free_buf(&b->read_tun_max);
|
||||
for (int x = 0; x < TUN_BAT_MAX; ++x)
|
||||
{
|
||||
free_buf(&b->read_tun_bufs[x]);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_COMP
|
||||
free_buf(&b->compress_buf);
|
||||
free_buf(&b->decompress_buf);
|
||||
|
|
|
|||
|
|
@ -41,9 +41,16 @@ void
|
|||
alloc_buf_sock_tun(struct buffer *buf, const struct frame *frame)
|
||||
{
|
||||
/* allocate buffer for overlapped I/O */
|
||||
*buf = alloc_buf(BUF_SIZE(frame));
|
||||
int alen = BUF_SIZE(frame);
|
||||
int blen = frame->buf.payload_size;
|
||||
if (frame->bulk_size > 0)
|
||||
{
|
||||
alen = BAT_SIZE(TUN_BAT_MAX, frame->tun_mtu, TUN_BAT_OFF);
|
||||
blen = BAT_SIZE(TUN_BAT_MAX, frame->tun_mtu, TUN_BAT_NOP);
|
||||
}
|
||||
*buf = alloc_buf(alen);
|
||||
ASSERT(buf_init(buf, frame->buf.headroom));
|
||||
buf->len = frame->buf.payload_size;
|
||||
buf->len = blen;
|
||||
ASSERT(buf_safe(buf, 0));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -58,6 +58,15 @@
|
|||
*/
|
||||
#define TUN_MTU_MIN 100
|
||||
|
||||
/*
|
||||
* Bulk mode static define values.
|
||||
*/
|
||||
#define TUN_BAT_MIN 6
|
||||
#define TUN_BAT_MAX 9
|
||||
#define TUN_BAT_OFF 250
|
||||
#define TUN_BAT_NOP 0
|
||||
#define TUN_BAT_ONE 1
|
||||
|
||||
/*
|
||||
* Default MTU of network over which tunnel data will pass by TCP/UDP.
|
||||
*/
|
||||
|
|
@ -162,6 +171,11 @@ struct frame
|
|||
* which defaults to 0 for tun and 32
|
||||
* (\c TAP_MTU_EXTRA_DEFAULT) for tap.
|
||||
* */
|
||||
|
||||
int bulk_size; /**< Configure and setup in the init library
|
||||
* frame function to signal and inform the various
|
||||
* related function calls to process bulk mode data transfers.
|
||||
* */
|
||||
};
|
||||
|
||||
/* Forward declarations, to prevent includes */
|
||||
|
|
@ -181,6 +195,7 @@ struct options;
|
|||
* larger than the headroom.
|
||||
*/
|
||||
#define BUF_SIZE(f) ((f)->buf.headroom + (f)->buf.payload_size + (f)->buf.tailroom)
|
||||
#define BAT_SIZE(a, b, c) ((a * b) + c)
|
||||
|
||||
/*
|
||||
* Function prototypes.
|
||||
|
|
|
|||
|
|
@ -367,16 +367,16 @@ unsigned int
|
|||
p2mp_iow_flags(const struct multi_context *m)
|
||||
{
|
||||
unsigned int flags = IOW_WAIT_SIGNAL;
|
||||
if (m->pending)
|
||||
if (m->pending || m->pending2)
|
||||
{
|
||||
if (TUN_OUT(&m->pending->context))
|
||||
{
|
||||
flags |= IOW_TO_TUN;
|
||||
}
|
||||
if (LINK_OUT(&m->pending->context))
|
||||
if (m->pending && LINK_OUT(&m->pending->context))
|
||||
{
|
||||
flags |= IOW_TO_LINK;
|
||||
}
|
||||
if (m->pending2 && TUN_OUT(&m->pending2->context))
|
||||
{
|
||||
flags |= IOW_TO_TUN;
|
||||
}
|
||||
}
|
||||
else if (mbuf_defined(m->mbuf))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -412,6 +412,10 @@ multi_init(struct context *t)
|
|||
}
|
||||
|
||||
m->deferred_shutdown_signal.signal_received = 0;
|
||||
|
||||
m->inst_indx = -1;
|
||||
m->inst_leng = -1;
|
||||
m->inst_list = calloc(TUN_BAT_MAX, sizeof(struct multi_instance *));
|
||||
}
|
||||
|
||||
const char *
|
||||
|
|
@ -572,6 +576,10 @@ multi_close_instance(struct multi_context *m, struct multi_instance *mi, bool sh
|
|||
{
|
||||
multi_set_pending(m, NULL);
|
||||
}
|
||||
if (m->pending2 == mi)
|
||||
{
|
||||
multi_set_pending2(m, NULL);
|
||||
}
|
||||
if (m->earliest_wakeup == mi)
|
||||
{
|
||||
m->earliest_wakeup = NULL;
|
||||
|
|
@ -692,6 +700,10 @@ multi_uninit(struct multi_context *m)
|
|||
multi_reap_free(m->reaper);
|
||||
mroute_helper_free(m->route_helper);
|
||||
multi_io_free(m->multi_io);
|
||||
|
||||
m->inst_indx = -1;
|
||||
m->inst_leng = -1;
|
||||
free(m->inst_list);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2982,8 +2994,7 @@ multi_process_post(struct multi_context *m, struct multi_instance *mi, const uns
|
|||
{
|
||||
bool ret = true;
|
||||
|
||||
if (!IS_SIG(&mi->context)
|
||||
&& ((flags & MPP_PRE_SELECT)))
|
||||
if (!IS_SIG(&mi->context) && (flags & MPP_PRE_SELECT) && !LINK_OUT(&mi->context))
|
||||
{
|
||||
#if defined(ENABLE_ASYNC_PUSH)
|
||||
bool was_unauthenticated = true;
|
||||
|
|
@ -3050,10 +3061,11 @@ multi_process_post(struct multi_context *m, struct multi_instance *mi, const uns
|
|||
else
|
||||
{
|
||||
/* continue to pend on output? */
|
||||
multi_set_pending(m, ANY_OUT(&mi->context) ? mi : NULL);
|
||||
multi_set_pending(m, LINK_OUT(&mi->context) ? mi : NULL);
|
||||
multi_set_pending2(m, TUN_OUT(&mi->context) ? mi : NULL);
|
||||
|
||||
#ifdef MULTI_DEBUG_EVENT_LOOP
|
||||
printf("POST %s[%d] to=%d lo=%d/%d w=%" PRIi64 "/%ld\n", id(mi), (int)(mi == m->pending),
|
||||
printf("POST %s[%d][%d] to=%d lo=%d/%d w=%" PRIi64 "/%ld\n", id(mi), (int)(mi == m->pending), (int)(mi == m->pending2),
|
||||
mi ? mi->context.c2.to_tun.len : -1, mi ? mi->context.c2.to_link.len : -1,
|
||||
(mi && mi->context.c2.fragment) ? mi->context.c2.fragment->outgoing.len : -1,
|
||||
(int64_t)mi->context.c2.timeval.tv_sec, (long)mi->context.c2.timeval.tv_usec);
|
||||
|
|
@ -3112,7 +3124,7 @@ multi_process_float(struct multi_context *m, struct multi_instance *mi, struct l
|
|||
msg(D_MULTI_LOW, "Disallow float to an address taken by another client %s",
|
||||
multi_instance_string(ex_mi, false, &gc));
|
||||
|
||||
mi->context.c2.buf.len = 0;
|
||||
mi->context.c2.buf2.len = 0;
|
||||
|
||||
goto done;
|
||||
}
|
||||
|
|
@ -3315,7 +3327,7 @@ multi_process_incoming_link(struct multi_context *m, struct multi_instance *inst
|
|||
bool ret = true;
|
||||
bool floated = false;
|
||||
|
||||
if (m->pending)
|
||||
if (m->pending2)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
|
@ -3323,26 +3335,26 @@ multi_process_incoming_link(struct multi_context *m, struct multi_instance *inst
|
|||
if (!instance)
|
||||
{
|
||||
#ifdef MULTI_DEBUG_EVENT_LOOP
|
||||
printf("TCP/UDP -> TUN [%d]\n", BLEN(&m->top.c2.buf));
|
||||
printf("TCP/UDP -> TUN [%d]\n", BLEN(&m->top.c2.buf2));
|
||||
#endif
|
||||
multi_set_pending(m, multi_get_create_instance_udp(m, &floated, sock));
|
||||
multi_set_pending2(m, multi_get_create_instance_udp(m, &floated, sock));
|
||||
}
|
||||
else
|
||||
{
|
||||
multi_set_pending(m, instance);
|
||||
multi_set_pending2(m, instance);
|
||||
}
|
||||
|
||||
if (m->pending)
|
||||
if (m->pending2)
|
||||
{
|
||||
set_prefix(m->pending);
|
||||
set_prefix(m->pending2);
|
||||
|
||||
/* get instance context */
|
||||
c = &m->pending->context;
|
||||
c = &m->pending2->context;
|
||||
|
||||
if (!instance)
|
||||
{
|
||||
/* transfer packet pointer from top-level context buffer to instance */
|
||||
c->c2.buf = m->top.c2.buf;
|
||||
c->c2.buf2 = m->top.c2.buf2;
|
||||
|
||||
/* transfer from-addr from top-level context buffer to instance */
|
||||
if (!floated)
|
||||
|
|
@ -3351,7 +3363,7 @@ multi_process_incoming_link(struct multi_context *m, struct multi_instance *inst
|
|||
}
|
||||
}
|
||||
|
||||
if (BLEN(&c->c2.buf) > 0)
|
||||
if (BLEN(&c->c2.buf2) > 0)
|
||||
{
|
||||
struct link_socket_info *lsi;
|
||||
const uint8_t *orig_buf;
|
||||
|
|
@ -3359,16 +3371,17 @@ multi_process_incoming_link(struct multi_context *m, struct multi_instance *inst
|
|||
/* decrypt in instance context */
|
||||
|
||||
lsi = &sock->info;
|
||||
orig_buf = c->c2.buf.data;
|
||||
orig_buf = c->c2.buf2.data;
|
||||
if (process_incoming_link_part1(c, lsi, floated))
|
||||
{
|
||||
/* nonzero length means that we have a valid, decrypted packed */
|
||||
if (floated && c->c2.buf.len > 0)
|
||||
if (floated && c->c2.buf2.len > 0)
|
||||
{
|
||||
multi_process_float(m, m->pending, sock);
|
||||
multi_process_float(m, m->pending2, sock);
|
||||
}
|
||||
|
||||
process_incoming_link_part2(c, lsi, orig_buf);
|
||||
process_incoming_link_part3(c);
|
||||
}
|
||||
|
||||
if (TUNNEL_TYPE(m->top.c1.tuntap) == DEV_TYPE_TUN)
|
||||
|
|
@ -3383,7 +3396,7 @@ multi_process_incoming_link(struct multi_context *m, struct multi_instance *inst
|
|||
c->c2.to_tun.len = 0;
|
||||
}
|
||||
/* make sure that source address is associated with this client */
|
||||
else if (multi_get_instance_by_virtual_addr(m, &src, true) != m->pending)
|
||||
else if (multi_get_instance_by_virtual_addr(m, &src, true) != m->pending2)
|
||||
{
|
||||
/* IPv6 link-local address (fe80::xxx)? */
|
||||
if ((src.type & MR_ADDR_MASK) == MR_ADDR_IPV6
|
||||
|
|
@ -3406,7 +3419,7 @@ multi_process_incoming_link(struct multi_context *m, struct multi_instance *inst
|
|||
if (mroute_flags & MROUTE_EXTRACT_MCAST)
|
||||
{
|
||||
/* for now, treat multicast as broadcast */
|
||||
multi_bcast(m, &c->c2.to_tun, m->pending, 0);
|
||||
multi_bcast(m, &c->c2.to_tun, m->pending2, 0);
|
||||
}
|
||||
else /* possible client to client routing */
|
||||
{
|
||||
|
|
@ -3448,14 +3461,14 @@ multi_process_incoming_link(struct multi_context *m, struct multi_instance *inst
|
|||
|
||||
if (mroute_flags & MROUTE_EXTRACT_SUCCEEDED)
|
||||
{
|
||||
if (multi_learn_addr(m, m->pending, &src, 0) == m->pending)
|
||||
if (multi_learn_addr(m, m->pending2, &src, 0) == m->pending2)
|
||||
{
|
||||
/* check for broadcast */
|
||||
if (m->enable_c2c)
|
||||
{
|
||||
if (mroute_flags & (MROUTE_EXTRACT_BCAST | MROUTE_EXTRACT_MCAST))
|
||||
{
|
||||
multi_bcast(m, &c->c2.to_tun, m->pending, vid);
|
||||
multi_bcast(m, &c->c2.to_tun, m->pending2, vid);
|
||||
}
|
||||
else /* try client-to-client routing */
|
||||
{
|
||||
|
|
@ -3487,7 +3500,7 @@ multi_process_incoming_link(struct multi_context *m, struct multi_instance *inst
|
|||
}
|
||||
|
||||
/* postprocess and set wakeup */
|
||||
ret = multi_process_post(m, m->pending, mpp_flags);
|
||||
ret = multi_process_post(m, m->pending2, mpp_flags);
|
||||
|
||||
clear_prefix();
|
||||
}
|
||||
|
|
@ -3496,12 +3509,19 @@ multi_process_incoming_link(struct multi_context *m, struct multi_instance *inst
|
|||
return ret;
|
||||
}
|
||||
|
||||
int min_max(int a, int b, int c)
|
||||
{
|
||||
if (a > c) { return c; }
|
||||
if (a < b) { return b; }
|
||||
return a;
|
||||
}
|
||||
|
||||
/*
|
||||
* Process packets in the TUN/TAP interface -> TCP/UDP socket direction,
|
||||
* i.e. server -> client direction.
|
||||
*/
|
||||
bool
|
||||
multi_process_incoming_tun(struct multi_context *m, const unsigned int mpp_flags)
|
||||
multi_process_incoming_tun_part2(struct multi_context *m, const unsigned int mpp_flags)
|
||||
{
|
||||
bool ret = true;
|
||||
|
||||
|
|
@ -3547,10 +3567,30 @@ multi_process_incoming_tun(struct multi_context *m, const unsigned int mpp_flags
|
|||
/* for now, treat multicast as broadcast */
|
||||
multi_bcast(m, &m->top.c2.buf, NULL, vid);
|
||||
}
|
||||
else if (m->inst_indx == -9)
|
||||
{
|
||||
struct multi_instance *inst = multi_get_instance_by_virtual_addr(m, &dest, dev_type == DEV_TYPE_TUN);
|
||||
if (inst)
|
||||
{
|
||||
int leng = m->inst_leng;
|
||||
for (int x = 0; x < leng; ++x)
|
||||
{
|
||||
if (m->inst_list[x] == inst)
|
||||
{
|
||||
m->inst_indx = x;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
leng = min_max(leng, 0, TUN_BAT_MIN - 1);
|
||||
m->inst_list[leng] = inst;
|
||||
m->inst_indx = leng;
|
||||
m->inst_leng = (leng + 1);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
multi_set_pending(
|
||||
m, multi_get_instance_by_virtual_addr(m, &dest, dev_type == DEV_TYPE_TUN));
|
||||
multi_set_pending(m, multi_get_instance_by_virtual_addr(m, &dest, dev_type == DEV_TYPE_TUN));
|
||||
|
||||
if (m->pending)
|
||||
{
|
||||
|
|
@ -3588,6 +3628,113 @@ multi_process_incoming_tun(struct multi_context *m, const unsigned int mpp_flags
|
|||
return ret;
|
||||
}
|
||||
|
||||
bool multi_process_inp_tun_post(struct multi_context *m, const unsigned int mpp_flags)
|
||||
{
|
||||
if (!INST_LENG(m))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (m->pending)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
while (m->inst_indx < m->inst_leng)
|
||||
{
|
||||
struct multi_instance *i = m->inst_list[m->inst_indx];
|
||||
if (i)
|
||||
{
|
||||
if (!(multi_output_queue_ready(m, i)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
multi_set_pending(m, i);
|
||||
set_prefix(m->pending);
|
||||
multi_process_post(m, m->pending, mpp_flags);
|
||||
clear_prefix();
|
||||
m->inst_list[m->inst_indx] = NULL;
|
||||
}
|
||||
m->inst_indx += 1;
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool multi_process_incoming_tun_part3(struct multi_context *m, const unsigned int mpp_flags)
|
||||
{
|
||||
struct context *c, *b = &(m->top);
|
||||
struct multi_instance *i;
|
||||
int leng = b->c2.buffers->bulk_leng;
|
||||
m->inst_indx = -1;
|
||||
m->inst_leng = -1;
|
||||
for (int x = 0; x < leng; ++x)
|
||||
{
|
||||
m->inst_indx = -9;
|
||||
b->c2.buf = b->c2.bufs[x];
|
||||
multi_process_incoming_tun_part2(m, mpp_flags);
|
||||
if (m->inst_indx > -1)
|
||||
{
|
||||
i = m->inst_list[m->inst_indx];
|
||||
c = &(i->context);
|
||||
int y = min_max(c->c2.buffers->bulk_leng, 0, TUN_BAT_MIN - 1);
|
||||
c->c2.buffers->read_tun_bufs[y].offset = TUN_BAT_OFF;
|
||||
c->c2.buffers->read_tun_bufs[y].len = BLEN(&b->c2.bufs[x]);
|
||||
bcopy(BPTR(&b->c2.bufs[x]), BPTR(&c->c2.buffers->read_tun_bufs[y]), BLEN(&b->c2.bufs[x]));
|
||||
c->c2.bufs[y] = c->c2.buffers->read_tun_bufs[y];
|
||||
c->c2.buffers->bulk_indx = 0;
|
||||
c->c2.buffers->bulk_leng = (y + 1);
|
||||
}
|
||||
}
|
||||
leng = m->inst_leng;
|
||||
b->c2.buffers->bulk_indx = -1;
|
||||
b->c2.buffers->bulk_leng = -1;
|
||||
for (int x = 0; x < leng; ++x)
|
||||
{
|
||||
i = m->inst_list[x];
|
||||
c = &(i->context);
|
||||
c->c2.buf = c->c2.bufs[0];
|
||||
process_incoming_tun(c, c->c2.link_sockets[0]);
|
||||
}
|
||||
m->inst_indx = 0;
|
||||
b->c2.buf.len = 0;
|
||||
buf_reset(&b->c2.to_link);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool multi_process_incoming_tun(struct multi_context *m, const unsigned int mpp_flags)
|
||||
{
|
||||
if (!(m->top.options.ce.bulk_mode))
|
||||
{
|
||||
return multi_process_incoming_tun_part2(m, mpp_flags);
|
||||
}
|
||||
else
|
||||
{
|
||||
return multi_process_incoming_tun_part3(m, mpp_flags);
|
||||
}
|
||||
}
|
||||
|
||||
bool multi_in_tun(struct multi_context *m, const unsigned int mpp_flags)
|
||||
{
|
||||
if (INST_LENG(m))
|
||||
{
|
||||
multi_process_inp_tun_post(m, mpp_flags);
|
||||
}
|
||||
else
|
||||
{
|
||||
struct context *c = &(m->top);
|
||||
read_incoming_tun(c);
|
||||
if (!IS_SIG(c))
|
||||
{
|
||||
multi_process_incoming_tun(m, mpp_flags);
|
||||
}
|
||||
if (!IS_SIG(c))
|
||||
{
|
||||
multi_process_inp_tun_post(m, mpp_flags);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Process a possible client-to-client/bcast/mcast message in the
|
||||
* queue.
|
||||
|
|
@ -3663,7 +3810,7 @@ multi_process_timeout(struct multi_context *m, const unsigned int mpp_flags)
|
|||
void
|
||||
multi_process_drop_outgoing_tun(struct multi_context *m, const unsigned int mpp_flags)
|
||||
{
|
||||
struct multi_instance *mi = m->pending;
|
||||
struct multi_instance *mi = m->pending2;
|
||||
|
||||
ASSERT(mi);
|
||||
|
||||
|
|
|
|||
|
|
@ -193,6 +193,7 @@ struct multi_context
|
|||
#endif
|
||||
|
||||
struct multi_instance *pending;
|
||||
struct multi_instance *pending2;
|
||||
struct multi_instance *earliest_wakeup;
|
||||
struct multi_instance **mpp_touched;
|
||||
struct context_buffers *context_buffers;
|
||||
|
|
@ -216,6 +217,10 @@ struct multi_context
|
|||
#endif
|
||||
|
||||
struct deferred_signal_schedule_entry deferred_shutdown_signal;
|
||||
|
||||
int inst_indx;
|
||||
int inst_leng;
|
||||
struct multi_instance **inst_list;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -255,6 +260,7 @@ struct multi_route
|
|||
*/
|
||||
void tunnel_server(struct context *top);
|
||||
|
||||
int min_max(int a, int b, int c);
|
||||
|
||||
const char *multi_instance_string(const struct multi_instance *mi, bool null, struct gc_arena *gc);
|
||||
|
||||
|
|
@ -352,6 +358,9 @@ bool multi_process_incoming_link(struct multi_context *m, struct multi_instance
|
|||
*/
|
||||
bool multi_process_incoming_tun(struct multi_context *m, const unsigned int mpp_flags);
|
||||
|
||||
bool multi_process_inp_tun_post(struct multi_context *m, const unsigned int mpp_flags);
|
||||
|
||||
bool multi_in_tun(struct multi_context *m, const unsigned int mpp_flags);
|
||||
|
||||
void multi_process_drop_outgoing_tun(struct multi_context *m, const unsigned int mpp_flags);
|
||||
|
||||
|
|
@ -413,7 +422,6 @@ static inline struct multi_instance *
|
|||
multi_process_outgoing_link_pre(struct multi_context *m)
|
||||
{
|
||||
struct multi_instance *mi = NULL;
|
||||
|
||||
if (m->pending)
|
||||
{
|
||||
mi = m->pending;
|
||||
|
|
@ -638,7 +646,7 @@ multi_get_timeout_instance(struct multi_context *m, struct timeval *dest)
|
|||
static inline bool
|
||||
multi_process_outgoing_tun(struct multi_context *m, const unsigned int mpp_flags)
|
||||
{
|
||||
struct multi_instance *mi = m->pending;
|
||||
struct multi_instance *mi = m->pending2;
|
||||
bool ret = true;
|
||||
|
||||
ASSERT(mi);
|
||||
|
|
@ -658,8 +666,7 @@ multi_process_outgoing_tun(struct multi_context *m, const unsigned int mpp_flags
|
|||
| OPT_P_COMP | OPT_P_SOCKFLAGS)
|
||||
|
||||
static inline bool
|
||||
multi_process_outgoing_link_dowork(struct multi_context *m, struct multi_instance *mi,
|
||||
const unsigned int mpp_flags)
|
||||
multi_process_outgoing_link_dowork(struct multi_context *m, struct multi_instance *mi, const unsigned int mpp_flags)
|
||||
{
|
||||
bool ret = true;
|
||||
set_prefix(mi);
|
||||
|
|
@ -706,6 +713,13 @@ multi_set_pending(struct multi_context *m, struct multi_instance *mi)
|
|||
{
|
||||
m->pending = mi;
|
||||
}
|
||||
|
||||
static inline void
|
||||
multi_set_pending2(struct multi_context *m, struct multi_instance *mi)
|
||||
{
|
||||
m->pending2 = mi;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigns a peer-id to a a client and adds the instance to the
|
||||
* the instances array of the \c multi_context structure.
|
||||
|
|
|
|||
|
|
@ -284,12 +284,9 @@ multi_io_dispatch(struct multi_context *m, struct multi_instance *mi, const int
|
|||
|
||||
switch (action)
|
||||
{
|
||||
case TA_INST_LENG:
|
||||
case TA_TUN_READ:
|
||||
read_incoming_tun(&m->top);
|
||||
if (!IS_SIG(&m->top))
|
||||
{
|
||||
multi_process_incoming_tun(m, mpp_flags);
|
||||
}
|
||||
multi_in_tun(m, mpp_flags);
|
||||
break;
|
||||
|
||||
case TA_SOCKET_READ:
|
||||
|
|
@ -355,52 +352,34 @@ multi_io_post(struct multi_context *m, struct multi_instance *mi, const int acti
|
|||
struct context *c = multi_get_context(m, mi);
|
||||
int newaction = TA_UNDEF;
|
||||
|
||||
#define MTP_NONE 0
|
||||
#define MTP_TUN_OUT (1 << 0)
|
||||
#define MTP_LINK_OUT (1 << 1)
|
||||
unsigned int flags = MTP_NONE;
|
||||
if (LINK_OUT(c))
|
||||
{
|
||||
newaction = TA_SOCKET_WRITE;
|
||||
goto last;
|
||||
}
|
||||
else if (INST_LENG(m))
|
||||
{
|
||||
newaction = TA_INST_LENG;
|
||||
goto last;
|
||||
}
|
||||
|
||||
if (TUN_OUT(c))
|
||||
{
|
||||
flags |= MTP_TUN_OUT;
|
||||
newaction = TA_TUN_WRITE;
|
||||
goto last;
|
||||
}
|
||||
if (LINK_OUT(c))
|
||||
else if (LINK_LEFT(c))
|
||||
{
|
||||
flags |= MTP_LINK_OUT;
|
||||
newaction = TA_SOCKET_READ_RESIDUAL;
|
||||
goto last;
|
||||
}
|
||||
|
||||
switch (flags)
|
||||
if (mi)
|
||||
{
|
||||
case MTP_TUN_OUT | MTP_LINK_OUT:
|
||||
case MTP_TUN_OUT:
|
||||
newaction = TA_TUN_WRITE;
|
||||
break;
|
||||
|
||||
case MTP_LINK_OUT:
|
||||
newaction = TA_SOCKET_WRITE;
|
||||
break;
|
||||
|
||||
case MTP_NONE:
|
||||
if (mi && sockets_read_residual(c))
|
||||
{
|
||||
newaction = TA_SOCKET_READ_RESIDUAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
multi_io_set_global_rw_flags(m, mi);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
struct gc_arena gc = gc_new();
|
||||
msg(M_FATAL, "MULTI IO: multi_io_post bad state, mi=%s flags=%d",
|
||||
multi_instance_string(mi, false, &gc), flags);
|
||||
gc_free(&gc);
|
||||
break;
|
||||
}
|
||||
multi_io_set_global_rw_flags(m, mi);
|
||||
}
|
||||
|
||||
last:
|
||||
dmsg(D_MULTI_DEBUG, "MULTI IO: multi_io_post %s -> %s", pract(action), pract(newaction));
|
||||
|
||||
return newaction;
|
||||
|
|
@ -454,19 +433,17 @@ multi_io_process_io(struct multi_context *m)
|
|||
{
|
||||
socket_reset_listen_persistent(ev_arg->u.sock);
|
||||
mi = multi_create_instance_tcp(m, ev_arg->u.sock);
|
||||
if (mi) { multi_io_action(m, mi, TA_INITIAL, false); }
|
||||
}
|
||||
else
|
||||
{
|
||||
multi_process_io_udp(m, ev_arg->u.sock);
|
||||
mi = m->pending;
|
||||
if (m->pending) { multi_io_action(m, m->pending, TA_INITIAL, false); }
|
||||
if (m->pending2) { multi_io_action(m, m->pending2, TA_INITIAL, false); }
|
||||
}
|
||||
/* monitor and/or handle events that are
|
||||
* triggered in succession by the first one
|
||||
* before returning to the main loop. */
|
||||
if (mi)
|
||||
{
|
||||
multi_io_action(m, mi, TA_INITIAL, false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -551,7 +528,7 @@ multi_io_action(struct multi_context *m, struct multi_instance *mi, int action,
|
|||
* On our first pass, poll will be false because we already know
|
||||
* that input is available, and to call io_wait would be redundant.
|
||||
*/
|
||||
if (poll && action != TA_SOCKET_READ_RESIDUAL)
|
||||
if (poll && action != TA_SOCKET_READ_RESIDUAL && action != TA_INST_LENG)
|
||||
{
|
||||
const int orig_action = action;
|
||||
action = multi_io_wait_lite(m, mi, action, &tun_input_pending);
|
||||
|
|
@ -586,10 +563,22 @@ multi_io_action(struct multi_context *m, struct multi_instance *mi, int action,
|
|||
* for a particular instance, point to
|
||||
* that instance.
|
||||
*/
|
||||
int retry_undef = 0;
|
||||
if (m->pending)
|
||||
{
|
||||
mi = m->pending;
|
||||
}
|
||||
if (m->pending2)
|
||||
{
|
||||
if (!m->pending)
|
||||
{
|
||||
mi = m->pending2;
|
||||
}
|
||||
else
|
||||
{
|
||||
retry_undef = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Based on the effects of the action,
|
||||
|
|
@ -597,6 +586,11 @@ multi_io_action(struct multi_context *m, struct multi_instance *mi, int action,
|
|||
* possibly transition to a new action state.
|
||||
*/
|
||||
action = multi_io_post(m, mi, action);
|
||||
if ((action == TA_UNDEF) && (retry_undef == 1))
|
||||
{
|
||||
mi = m->pending2;
|
||||
action = multi_io_post(m, mi, action);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we are finished processing the original action,
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@
|
|||
#define TA_INITIAL 8
|
||||
#define TA_TIMEOUT 9
|
||||
#define TA_TUN_WRITE_TIMEOUT 10
|
||||
#define TA_INST_LENG 11
|
||||
|
||||
/*
|
||||
* I/O state and events tracker
|
||||
|
|
|
|||
|
|
@ -112,6 +112,14 @@ struct context_buffers
|
|||
*/
|
||||
struct buffer read_link_buf;
|
||||
struct buffer read_tun_buf;
|
||||
|
||||
struct buffer read_tun_bufs[TUN_BAT_MAX];
|
||||
struct buffer read_tun_max;
|
||||
struct buffer send_tun_max;
|
||||
struct buffer to_tun_max;
|
||||
|
||||
int bulk_indx;
|
||||
int bulk_leng;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -373,9 +381,12 @@ struct context_2
|
|||
* struct context_buffers.
|
||||
*/
|
||||
struct buffer buf;
|
||||
struct buffer buf2;
|
||||
struct buffer to_tun;
|
||||
struct buffer to_link;
|
||||
|
||||
struct buffer bufs[TUN_BAT_MAX];
|
||||
|
||||
/* should we print R|W|r|w to console on packet transfers? */
|
||||
bool log_rw;
|
||||
|
||||
|
|
|
|||
|
|
@ -305,6 +305,7 @@ static const char usage_message[] =
|
|||
" 'maybe' -- Use per-route hints\n"
|
||||
" 'yes' -- Always DF (Don't Fragment)\n"
|
||||
"--mtu-test : Empirically measure and report MTU.\n"
|
||||
"--bulk-mode : Use bulk TUN/TCP reads/writes.\n"
|
||||
#ifdef ENABLE_FRAGMENT
|
||||
"--fragment max : Enable internal datagram fragmentation so that no UDP\n"
|
||||
" datagrams are sent which are larger than max bytes.\n"
|
||||
|
|
@ -3262,6 +3263,11 @@ options_postprocess_mutate_invariant(struct options *options)
|
|||
options->pkcs11_providers[0] = DEFAULT_PKCS11_MODULE;
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((options->ce.proto != PROTO_TCP) && (options->ce.proto != PROTO_TCP_SERVER) && (options->ce.proto != PROTO_TCP_CLIENT))
|
||||
{
|
||||
options->ce.bulk_mode = false;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -9272,6 +9278,10 @@ add_option(struct options *options, char *p[], bool is_inline, const char *file,
|
|||
}
|
||||
options->vlan_pvid = (uint16_t)vlan_pvid;
|
||||
}
|
||||
else if (streq(p[0], "bulk-mode"))
|
||||
{
|
||||
options->ce.bulk_mode = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
int i;
|
||||
|
|
|
|||
|
|
@ -177,6 +177,9 @@ struct connection_entry
|
|||
|
||||
/* Allow only client that support resending the wrapped client key */
|
||||
bool tls_crypt_v2_force_cookie;
|
||||
|
||||
/* Bulk mode allows for multiple tun reads + larger tcp writes */
|
||||
bool bulk_mode;
|
||||
};
|
||||
|
||||
struct remote_entry
|
||||
|
|
|
|||
Loading…
Reference in a new issue