使用cmsg公共库解析cmsg信息,对业务层提供获取cmsg句柄的接口

This commit is contained in:
luqiuwen
2019-06-01 17:00:36 +08:00
parent 1b872c246d
commit 77aa3063f7
11 changed files with 133 additions and 283 deletions

View File

@@ -13,41 +13,16 @@
#include <MESA/MESA_prof_load.h>
#include <tfe_stream.h>
#include <tfe_cmsg.h>
#include <acceptor_scm.h>
#include <proxy.h>
#include <platform.h>
#
#ifndef TFE_CONFIG_SCM_SOCKET_FILE
#define TFE_CONFIG_SCM_SOCKET_FILE "/var/run/.tfe_kmod_scm_socket"
#endif
/* The KNI and TFE communicate with each other by UNIX-based socket,
* and the protocol between them is based on TLV format(Type-Length-Value).
* The byte order for each entry in the protocol are Host-Ordered.
*
* I. Magic and Total counts of T-L-V tuples, at front of the SOCKET stream.
* II. After Magic header, the stream consist of several T-L-V tuples.
*
* Note. Magic = 0x4d5a
* Consider of the byte align problem, the minimum length of the value is 4bytes(32-bits).
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Magic | Total counts of TLV |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Type | Length |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Value |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Type | Length |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Value |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | ....... |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
struct acceptor_scm
{
/* INPUT */
@@ -65,209 +40,12 @@ struct acceptor_scm
pthread_t thread;
};
enum tcp_restore_info_tlv_type
{
TCP_RESTORE_INFO_TLV_SEQ,
TCP_RESTORE_INFO_TLV_ACK,
TCP_RESTORE_INFO_TLV_MSS_CLIENT,
TCP_RESTORE_INFO_TLV_MSS_SERVER,
TCP_RESTORE_INFO_TLV_WSACLE_CLIENT,
TCP_RESTORE_INFO_TLV_WSACLE_SERVER,
TCP_RESTORE_INFO_TLV_SACK_CLIENT,
TCP_RESTORE_INFO_TLV_SACK_SERVER,
TCP_RESTORE_INFO_TLV_TS_CLIENT,
TCP_RESTORE_INFO_TLV_TS_SERVER,
TCP_RESTORE_INFO_TLV_PROTOCOL,
TCP_RESTORE_INFO_TLV_USER_DEFINED
};
struct tcp_restore_info_endpoint
{
struct sockaddr_storage addr;
uint32_t seq;
uint32_t ack;
bool wscale_perm;
bool timestamp_perm;
bool sack_perm;
uint16_t mss;
uint8_t wscale;
};
struct tcp_restore_info
{
struct tcp_restore_info_endpoint client;
struct tcp_restore_info_endpoint server;
unsigned int protocol;
};
struct tcp_restore_info_tlv
{
uint16_t type;
uint16_t length;
union
{
uint8_t value_as_uint8[0];
uint16_t value_as_uint16[0];
uint32_t value_as_uint32[0];
unsigned char value_as_string[0];
};
} __attribute__((packed));
struct tcp_restore_info_header
{
uint8_t __magic__[2]; /* Must be 0x4d, 0x5a */
uint16_t nr_tlvs;
struct tcp_restore_info_tlv tlvs[0];
} __attribute__((packed));
#define TCP_RESTORE_TCPOPT_KIND 88
#define TCP_RESTORE_TCPOPT_LENGTH 4
/* Copy from tfe-kmod */
int tcp_restore_info_parse_from_cmsg(struct acceptor_scm * ctx,
const char * data, unsigned int datalen, struct tcp_restore_info * out)
{
struct tcp_restore_info_header * header = (struct tcp_restore_info_header *)data;
unsigned int tlv_iter;
unsigned int nr_tlvs;
if(unlikely(header->__magic__[0] != 0x4d || header->__magic__[1] != 0x5a))
{
TFE_LOG_ERROR(ctx->logger, "Invalid restore info format: wrong magic, drop it.\n");
goto invalid_format;
}
nr_tlvs = ntohs(header->nr_tlvs);
if (unlikely(nr_tlvs >= 256))
{
TFE_LOG_ERROR(ctx->logger, "Invalid restore info format: numbers of tlvs is larger than 256, drop it.\n");
goto invalid_format;
}
if (unlikely(datalen < sizeof(struct tcp_restore_info_header)))
{
TFE_LOG_ERROR(ctx->logger, "Invalid restore info format: length is shorter than tlv header, drop it.\n");
goto invalid_format;
}
datalen -= sizeof(struct tcp_restore_info_header);
data += sizeof(struct tcp_restore_info_header);
for(tlv_iter = 0; tlv_iter < nr_tlvs; tlv_iter++)
{
struct tcp_restore_info_tlv * tlv = (struct tcp_restore_info_tlv *)data;
uint16_t tlv_type = ntohs(tlv->type);
uint16_t tlv_length = ntohs(tlv->length);
unsigned int __length = tlv_length;
if(unlikely(datalen < __length))
{
TFE_LOG_ERROR(ctx->logger, "Invalid restore info format: left space is smaller than tlv's length, "
"datalen is %u, tlv's length is %u, drop it.", datalen, __length);
goto invalid_format;
}
if(unlikely(tlv_length < sizeof(uint16_t) * 2))
{
TFE_LOG_ERROR(ctx->logger, "Invalid restore info format: invalid tlv length, "
"should larger than sizeof(type) + sizeof(length).");
goto invalid_format;
}
tlv_length -= sizeof(uint16_t) * 2;
#define __CHECK_TLV_LENGTH(x) do { if(unlikely(x != tlv_length)) { \
TFE_LOG_ERROR(ctx->logger, "Invalid restore format: invalid tlv length, should be %u, actually is %u, drop it.", \
(unsigned int)x, (unsigned int)tlv_length); goto invalid_format; }} while(0)
switch(tlv_type)
{
case TCP_RESTORE_INFO_TLV_SEQ:
__CHECK_TLV_LENGTH(sizeof(uint32_t));
out->client.seq = ntohl(tlv->value_as_uint32[0]);
out->server.ack = ntohl(tlv->value_as_uint32[0]);
break;
case TCP_RESTORE_INFO_TLV_ACK:
__CHECK_TLV_LENGTH(sizeof(uint32_t));
out->client.ack = ntohl(tlv->value_as_uint32[0]);
out->server.seq = ntohl(tlv->value_as_uint32[0]);
break;
case TCP_RESTORE_INFO_TLV_TS_CLIENT:
__CHECK_TLV_LENGTH(sizeof(uint8_t));
out->client.timestamp_perm = !!(tlv->value_as_uint8[0]);
break;
case TCP_RESTORE_INFO_TLV_TS_SERVER:
__CHECK_TLV_LENGTH(sizeof(uint8_t));
out->server.timestamp_perm = !!(tlv->value_as_uint8[0]);
break;
case TCP_RESTORE_INFO_TLV_WSACLE_CLIENT:
__CHECK_TLV_LENGTH(sizeof(uint8_t));
out->client.wscale_perm = true;
out->client.wscale = tlv->value_as_uint8[0];
break;
case TCP_RESTORE_INFO_TLV_WSACLE_SERVER:
__CHECK_TLV_LENGTH(sizeof(uint8_t));
out->server.wscale_perm = true;
out->server.wscale = tlv->value_as_uint8[0];
break;
case TCP_RESTORE_INFO_TLV_SACK_CLIENT:
__CHECK_TLV_LENGTH(sizeof(uint8_t));
out->client.sack_perm = true;
break;
case TCP_RESTORE_INFO_TLV_SACK_SERVER:
__CHECK_TLV_LENGTH(sizeof(uint8_t));
out->server.sack_perm = true;
break;
case TCP_RESTORE_INFO_TLV_MSS_CLIENT:
__CHECK_TLV_LENGTH(sizeof(uint16_t));
out->client.mss = ntohs(tlv->value_as_uint16[0]);
break;
case TCP_RESTORE_INFO_TLV_MSS_SERVER:
__CHECK_TLV_LENGTH(sizeof(uint16_t));
out->server.mss = ntohs(tlv->value_as_uint16[0]);
break;
case TCP_RESTORE_INFO_TLV_PROTOCOL:
__CHECK_TLV_LENGTH(sizeof(uint8_t));
out->protocol = tlv->value_as_uint8[0];
break;
case TCP_RESTORE_INFO_TLV_USER_DEFINED:
break;
default:
TFE_LOG_ERROR(ctx->logger, "Invalid restore info format: unsupported type %x, drop it.\n", tlv_type);
goto invalid_format;
}
data += __length;
datalen -= __length;
}
return 0;
invalid_format:
return -EINVAL;
}
void acceptor_scm_event(evutil_socket_t fd, short what, void * user)
{
struct acceptor_scm * __ctx = (struct acceptor_scm *) user;
struct cmsghdr * __cmsghdr;
struct tfe_proxy_accept_para __accept_para{};
struct tcp_restore_info restore_info{};
struct tfe_cmsg * cmsg = NULL;
int * __fds = NULL;
assert(__ctx != NULL && __ctx->thread == pthread_self());
@@ -322,18 +100,16 @@ void acceptor_scm_event(evutil_socket_t fd, short what, void * user)
goto __die;
}
if (tcp_restore_info_parse_from_cmsg(__ctx, __buffer, (size_t)rd, &restore_info) < 0)
{
TFE_LOG_ERROR(__ctx->logger, "Failed at parsing TLV format, drop the connection.");
goto __drop_recieved_fds;
}
/* Apply a cmsg structure */
if (tfe_cmsg_deserialize((const unsigned char *)__buffer, (uint16_t)rd, &cmsg) < 0)
{
/* TODO: dump the buffer in hexdump format */
TFE_LOG_ERROR(__ctx->logger, "failed at cmsg_deserialize(), invalid format.");
goto __drop_recieved_fds;
}
__accept_para.downstream_fd = __fds[0];
__accept_para.upstream_fd = __fds[1];
__accept_para.session_type = restore_info.protocol ? STREAM_PROTO_SSL : STREAM_PROTO_PLAIN;
TFE_PROXY_STAT_INCREASE(STAT_FD_OPEN_BY_KNI_ACCEPT, 2);
if (tfe_proxy_fds_accept(__ctx->proxy, &__accept_para) < 0)
TFE_PROXY_STAT_INCREASE(STAT_FD_OPEN_BY_KNI_ACCEPT, 2);
if (tfe_proxy_fds_accept(__ctx->proxy, __fds[0], __fds[1], cmsg) < 0)
{
goto __drop_recieved_fds;
}

View File

@@ -30,6 +30,8 @@
#include <tfe_future.h>
#include <tfe_stream.h>
#include <tfe_proxy.h>
#include <tfe_plugin.h>
#include <tfe_cmsg.h>
#include <platform.h>
#include <proxy.h>
@@ -37,7 +39,6 @@
#include <tcp_stream.h>
#include <MESA/MESA_prof_load.h>
#include <MESA/field_stat2.h>
#include <tfe_plugin.h>
extern struct ssl_policy_enforcer* ssl_policy_enforcer_create(void* logger);
extern enum ssl_stream_action ssl_policy_enforce(struct ssl_stream *upstream, void* u_para);
@@ -99,16 +100,28 @@ void tfe_proxy_thread_ctx_release(struct tfe_thread_ctx * thread_ctx)
ATOMIC_DEC(&thread_ctx->load);
}
int tfe_proxy_fds_accept(struct tfe_proxy * ctx, const struct tfe_proxy_accept_para * para)
int tfe_proxy_fds_accept(struct tfe_proxy * ctx, int fd_downstream, int fd_upstream, struct tfe_cmsg * cmsg)
{
tfe_thread_ctx * worker_thread_ctx = tfe_proxy_thread_ctx_acquire(ctx);
struct tfe_thread_ctx * worker_thread_ctx = tfe_proxy_thread_ctx_acquire(ctx);
struct tfe_stream * stream = tfe_stream_create(ctx, worker_thread_ctx);
tfe_stream_option_set(stream, TFE_STREAM_OPT_SESSION_TYPE, &para->session_type, sizeof(para->session_type));
tfe_stream_option_set(stream, TFE_STREAM_OPT_KEYRING_ID, &para->keyring_id, sizeof(para->keyring_id));
enum tfe_stream_proto stream_protocol;
uint16_t __size;
int result = tfe_cmsg_get_value(cmsg, TFE_CMSG_TCP_RESTORE_PROTOCOL, (char *)&stream_protocol,
sizeof(stream_protocol), &__size);
if (unlikely(result < 0))
{
TFE_LOG_ERROR(ctx->logger, "failed at fetch connection's protocol from cmsg: %s", strerror(-result));
goto __errout;
}
tfe_stream_option_set(stream, TFE_STREAM_OPT_SESSION_TYPE, &stream_protocol, sizeof(stream_protocol));
tfe_stream_cmsg_setup(stream, cmsg);
/* FOR DEBUG */
if (para->passthrough || ctx->tcp_all_passthrough)
if (unlikely(ctx->tcp_all_passthrough))
{
bool __true = true;
enum tfe_stream_proto __session_type = STREAM_PROTO_PLAIN;
@@ -117,17 +130,16 @@ int tfe_proxy_fds_accept(struct tfe_proxy * ctx, const struct tfe_proxy_accept_p
tfe_stream_option_set(stream, TFE_STREAM_OPT_SESSION_TYPE, &__session_type, sizeof(__session_type));
}
int ret = tfe_stream_init_by_fds(stream, para->downstream_fd, para->upstream_fd);
if (ret < 0)
result = tfe_stream_init_by_fds(stream, fd_downstream, fd_upstream);
if (result < 0)
{
TFE_LOG_ERROR(ctx->logger, "%p, Fds(downstream = %d, upstream = %d, type = %d) accept failed.",
stream, para->downstream_fd, para->upstream_fd, para->session_type);
goto __errout;
stream, fd_downstream, fd_upstream, stream_protocol); goto __errout;
}
else
{
TFE_LOG_DEBUG(ctx->logger, "%p, Fds(downstream = %d, upstream = %d, type = %d) accepted.",
stream, para->downstream_fd, para->upstream_fd, para->session_type);
stream, fd_downstream, fd_upstream, stream_protocol);
}
return 0;

View File

@@ -820,7 +820,6 @@ static void ssl_async_peek_client_hello(struct future * f, evutil_socket_t fd, s
struct peek_client_hello_ctx * ctx = ALLOC(struct peek_client_hello_ctx, 1);
ctx->ev = event_new(evbase, fd, EV_READ, peek_client_hello_cb, p);
ctx->evbase = evbase;
ctx->parse_client_cipher=parse_cipher;
ctx->logger = logger;
promise_set_ctx(p, (void *) ctx, peek_client_hello_ctx_free_cb);
event_add(ctx->ev, NULL);

View File

@@ -1300,6 +1300,18 @@ int tfe_stream_option_set(struct tfe_stream * stream, enum tfe_stream_option opt
return 0;
}
struct tfe_cmsg * tfe_stream_get0_cmsg(const struct tfe_stream * stream)
{
struct tfe_stream_private * _stream = container_of(stream, struct tfe_stream_private, head);
return _stream->cmsg;
}
void tfe_stream_cmsg_setup(const struct tfe_stream * stream, struct tfe_cmsg * cmsg)
{
struct tfe_stream_private * _stream = container_of(stream, struct tfe_stream_private, head);
assert(_stream->cmsg == NULL);
_stream->cmsg = cmsg;
}
void tfe_stream_write_access_log(const struct tfe_stream * stream, int level, const char * fmt, ...)
{
va_list arg_ptr;